Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALPINS_H
#define MBED_PERIPHERALPINS_H
#include "pinmap.h"
#include "PeripheralNames.h"
/************RTC***************/
extern const PinMap PinMap_RTC[];
/************ADC***************/
extern const PinMap PinMap_ADC[];
/************DAC***************/
extern const PinMap PinMap_DAC[];
/************I2C***************/
extern const PinMap PinMap_I2C_SDA[];
extern const PinMap PinMap_I2C_SCL[];
/************UART***************/
extern const PinMap PinMap_UART_TX[];
extern const PinMap PinMap_UART_RX[];
extern const PinMap PinMap_UART_CTS[];
extern const PinMap PinMap_UART_RTS[];
/************SPI***************/
extern const PinMap PinMap_SPI_SCLK[];
extern const PinMap PinMap_SPI_MOSI[];
extern const PinMap PinMap_SPI_MISO[];
extern const PinMap PinMap_SPI_SSEL[];
/************PWM***************/
extern const PinMap PinMap_PWM[];
#endif

View File

@@ -0,0 +1,35 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PORTNAMES_H
#define MBED_PORTNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
Gpio1 = 1,
Gpio2 = 2,
Gpio3 = 3,
Gpio4 = 4,
Gpio5 = 5
} PortName;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,88 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "analogin_api.h"
#if DEVICE_ANALOGIN
#include "cmsis.h"
#include "pinmap.h"
#include "gpio_api.h"
#include "PeripheralNames.h"
#include "fsl_adc.h"
#include "PeripheralPins.h"
/* Array of ADC peripheral base address. */
static ADC_Type *const adc_addrs[] = ADC_BASE_PTRS;
void analogin_init(analogin_t *obj, PinName pin)
{
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
MBED_ASSERT(obj->adc != (ADCName)NC);
uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT;
adc_config_t adc_config;
gpio_t gpio;
ADC_GetDefaultConfig(&adc_config);
ADC_Init(adc_addrs[instance], &adc_config);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(adc_addrs[instance], false);
#endif
ADC_DoAutoCalibration(adc_addrs[instance]);
/* Need to ensure the pin is in input mode */
gpio_init(&gpio, pin);
gpio_dir(&gpio, PIN_INPUT);
}
uint16_t analogin_read_u16(analogin_t *obj)
{
uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT;
adc_channel_config_t adc_channel_config;
adc_channel_config.channelNumber = obj->adc & 0xF;
adc_channel_config.enableInterruptOnConversionCompleted = false;
/*
When in software trigger mode, each conversion would be launched once calling the "ADC_ChannelConfigure()"
function, which works like writing a conversion command and executing it. For another channel's conversion,
just to change the "channelNumber" field in channel configuration structure, and call the function
"ADC_ChannelConfigure()"" again.
Also, the "enableInterruptOnConversionCompleted" inside the channel configuration structure is a parameter
for the conversion command. It takes affect just for the current conversion. If the interrupt is still required
for the following conversion, it is necessary to assert the "enableInterruptOnConversionCompleted" every
time for each command.
*/
ADC_SetChannelConfig(adc_addrs[instance], 0, &adc_channel_config);
while (0U == ADC_GetChannelStatusFlags(adc_addrs[instance], 0))
{
}
return ADC_GetChannelConversionValue(adc_addrs[instance], 0);
}
float analogin_read(analogin_t *obj)
{
uint16_t value = analogin_read_u16(obj);
return (float)value * (1.0f / (float)0xFFFF);
}
const PinMap *analogin_pinmap()
{
return PinMap_ADC;
}
#endif

View File

@@ -0,0 +1,640 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "flash_api.h"
#include "mbed_toolchain.h"
#include "mbed_critical.h"
#if DEVICE_FLASH
#include "fsl_flexspi.h"
#include "fsl_cache.h"
#include "flash_defines.h"
AT_QUICKACCESS_SECTION_CODE(void flexspi_update_lut_ram(void));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_write_enable_ram(uint32_t baseAddr));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_wait_bus_busy_ram(void));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_erase_sector_ram(uint32_t address));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_page_program_ram(uint32_t address,
const uint32_t *src,
uint32_t size));
AT_QUICKACCESS_SECTION_CODE(void flexspi_nor_flash_read_data_ram(uint32_t addr,
uint32_t *buffer,
uint32_t size));
AT_QUICKACCESS_SECTION_CODE(void *flexspi_memset(void *buf, int c, size_t n));
/**
* @brief Set bytes in memory. If put this code in SRAM, Make sure this code
* does not call functions in Flash.
*
* @return pointer to start of buffer
*/
void *flexspi_memset(void *buf, int c, size_t n)
{
/* do byte-sized initialization until word-aligned or finished */
unsigned char *d_byte = (unsigned char *)buf;
unsigned char c_byte = (unsigned char)c;
while (((unsigned int)d_byte) & 0x3) {
if (n == 0) {
return buf;
}
*(d_byte++) = c_byte;
n--;
};
/* do word-sized initialization as long as possible */
unsigned int *d_word = (unsigned int *)d_byte;
unsigned int c_word = (unsigned int)(unsigned char)c;
c_word |= c_word << 8;
c_word |= c_word << 16;
while (n >= sizeof(unsigned int)) {
*(d_word++) = c_word;
n -= sizeof(unsigned int);
}
/* do byte-sized initialization until finished */
d_byte = (unsigned char *)d_word;
while (n > 0) {
*(d_byte++) = c_byte;
n--;
}
return buf;
}
#ifdef HYPERFLASH_BOOT
AT_QUICKACCESS_SECTION_CODE(void flexspi_lower_clock_ram(void));
AT_QUICKACCESS_SECTION_CODE(void flexspi_clock_update_ram(void));
void flexspi_update_lut_ram(void)
{
flexspi_config_t config;
flexspi_memset(&config, 0, sizeof(config));
/*Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
/*Set AHB buffer size for reading data through AHB bus. */
config.ahbConfig.enableAHBPrefetch = true;
/*Allow AHB read start address do not follow the alignment requirement. */
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableAHBCachable = true;
/* enable diff clock and DQS */
config.enableSckBDiffOpt = true;
config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;
config.enableCombination = true;
FLEXSPI_Init(FLEXSPI, &config);
/* Configure flash settings according to serial flash feature. */
FLEXSPI_SetFlashConfig(FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);
/* Update LUT table. */
FLEXSPI_UpdateLUT(FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);
FLEXSPI_SoftwareReset(FLEXSPI);
/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}
status_t flexspi_nor_write_enable_ram(uint32_t baseAddr)
{
flexspi_transfer_t flashXfer;
status_t status = kStatus_Success;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
/* Write enable */
flashXfer.deviceAddress = baseAddr;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
return status;
}
status_t flexspi_nor_wait_bus_busy_ram(void)
{
/* Wait status ready. */
bool isBusy = false;
uint32_t readValue = 0;
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS;
flashXfer.data = &readValue;
flashXfer.dataSize = 2;
do {
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
if (readValue & 0x8000) {
isBusy = false;
} else {
isBusy = true;
}
if (readValue & 0x3200) {
status = kStatus_Fail;
break;
}
} while (isBusy);
return status;
}
status_t flexspi_nor_flash_erase_sector_ram(uint32_t address)
{
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
/* Write enable */
status = flexspi_nor_write_enable_ram(address);
if (status != kStatus_Success) {
return status;
}
flashXfer.deviceAddress = address;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 4;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nor_wait_bus_busy_ram();
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
return status;
}
void flexspi_lower_clock_ram(void)
{
unsigned int reg = 0;
/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
FLEXSPI_Enable(FLEXSPI, false);
/* Disable FlexSPI clock */
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
/* flexspi clock 66M, DDR mode, internal clock 33M. */
reg = CCM->CSCMR1;
reg &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
reg |= CCM_CSCMR1_FLEXSPI_PODF(3);
CCM->CSCMR1 = reg;
/* Enable FlexSPI clock */
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
FLEXSPI_Enable(FLEXSPI, true);
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}
void flexspi_clock_update_ram(void)
{
/* Program finished, speed the clock to 133M. */
/* Wait for bus idle before change flash configuration. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
FLEXSPI_Enable(FLEXSPI, false);
/* Disable FlexSPI clock */
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
/* flexspi clock 260M, DDR mode, internal clock 130M. */
CCM->CSCMR1 &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
/* Enable FlexSPI clock */
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
FLEXSPI_Enable(FLEXSPI, true);
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}
status_t flexspi_nor_flash_page_program_ram(uint32_t address, const uint32_t *src, uint32_t size)
{
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;
uint32_t offset = 0;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
flexspi_lower_clock_ram();
while (size > 0) {
/* Write enable */
status = flexspi_nor_write_enable_ram(address + offset);
if (status != kStatus_Success) {
return status;
}
/* Prepare page program command */
flashXfer.deviceAddress = address + offset;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM;
flashXfer.data = (uint32_t *)(src + offset);
flashXfer.dataSize = BOARD_FLASH_PAGE_SIZE;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nor_wait_bus_busy_ram();
if (status != kStatus_Success) {
return status;
}
size -= BOARD_FLASH_PAGE_SIZE;
offset += BOARD_FLASH_PAGE_SIZE;
}
flexspi_clock_update_ram();
return status;
}
#else
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_enable_quad_mode_ram(void));
status_t flexspi_nor_enable_quad_mode_ram(void)
{
flexspi_transfer_t flashXfer;
uint32_t writeValue = FLASH_QUAD_ENABLE;
status_t status = kStatus_Success;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
/* Write enable */
status = flexspi_nor_write_enable_ram(0);
if (status != kStatus_Success) {
return status;
}
/* Enable quad mode. */
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG;
flashXfer.data = &writeValue;
flashXfer.dataSize = 1;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nor_wait_bus_busy_ram();
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
return status;
}
void flexspi_update_lut_ram(void)
{
flexspi_config_t config;
flexspi_memset(&config, 0, sizeof(config));
/*Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
/*Set AHB buffer size for reading data through AHB bus. */
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBCachable = true;
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;
FLEXSPI_Init(FLEXSPI, &config);
/* Configure flash settings according to serial flash feature. */
FLEXSPI_SetFlashConfig(FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);
/* Update LUT table. */
FLEXSPI_UpdateLUT(FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
flexspi_nor_enable_quad_mode_ram();
}
status_t flexspi_nor_write_enable_ram(uint32_t baseAddr)
{
flexspi_transfer_t flashXfer;
status_t status = kStatus_Success;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
/* Write enable */
flashXfer.deviceAddress = baseAddr;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
return status;
}
status_t flexspi_nor_wait_bus_busy_ram(void)
{
/* Wait status ready. */
bool isBusy;
uint32_t readValue;
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READSTATUSREG;
flashXfer.data = &readValue;
flashXfer.dataSize = 1;
do {
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
if (FLASH_BUSY_STATUS_POL) {
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) {
isBusy = true;
} else {
isBusy = false;
}
} else {
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) {
isBusy = false;
} else {
isBusy = true;
}
}
} while (isBusy);
return status;
}
status_t flexspi_nor_flash_erase_sector_ram(uint32_t address)
{
flexspi_transfer_t flashXfer;
status_t status = kStatus_Success;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
/* Write enable */
flashXfer.deviceAddress = address;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
flashXfer.deviceAddress = address;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nor_wait_bus_busy_ram();
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
return status;
}
status_t flexspi_nor_flash_page_program_ram(uint32_t address, const uint32_t *src, uint32_t size)
{
flexspi_transfer_t flashXfer;
status_t status = kStatus_Success;
uint32_t offset = 0;
flexspi_memset(&flashXfer, 0, sizeof(flashXfer));
while (size > 0) {
/* Write enable */
status = flexspi_nor_write_enable_ram(address + offset);
if (status != kStatus_Success) {
return status;
}
/* Prepare page program command */
flashXfer.deviceAddress = address + offset;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD;
flashXfer.data = (uint32_t *)(src + offset);
flashXfer.dataSize = BOARD_FLASH_PAGE_SIZE;
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nor_wait_bus_busy_ram();
if (status != kStatus_Success) {
return status;
}
size -= BOARD_FLASH_PAGE_SIZE;
offset += BOARD_FLASH_PAGE_SIZE;
}
/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);
return status;
}
#endif
void flexspi_nor_flash_read_data_ram(uint32_t addr, uint32_t *buffer, uint32_t size)
{
memcpy(buffer, (void *)addr, size);
}
int32_t flash_init(flash_t *obj)
{
core_util_critical_section_enter();
flexspi_update_lut_ram();
core_util_critical_section_exit();
return 0;
}
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
{
status_t status = kStatus_Success;
int32_t ret = 0;
core_util_critical_section_enter();
status = flexspi_nor_flash_erase_sector_ram(address - FlexSPI_AMBA_BASE);
if (status != kStatus_Success) {
ret = -1;
} else {
DCACHE_InvalidateByRange(address, BOARD_FLASH_SECTOR_SIZE);
}
core_util_critical_section_exit();
return ret;
}
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{
status_t status = kStatus_Success;
int32_t ret = 0;
core_util_critical_section_enter();
status = flexspi_nor_flash_page_program_ram(address - FlexSPI_AMBA_BASE, (uint32_t *)data, size);
if (status != kStatus_Success) {
ret = -1;
} else {
DCACHE_InvalidateByRange(address, size);
}
core_util_critical_section_exit();
return ret;
}
int32_t flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size)
{
flexspi_nor_flash_read_data_ram(address, (uint32_t *)data, size);
return 0;
}
int32_t flash_free(flash_t *obj)
{
return 0;
}
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
{
uint32_t sectorsize = MBED_FLASH_INVALID_SIZE;
uint32_t devicesize = BOARD_FLASH_SIZE;
uint32_t startaddr = BOARD_FLASH_START_ADDR;
if ((address >= startaddr) && (address < (startaddr + devicesize))) {
sectorsize = BOARD_FLASH_SECTOR_SIZE;
}
return sectorsize;
}
uint32_t flash_get_page_size(const flash_t *obj)
{
return BOARD_FLASH_PAGE_SIZE;
}
uint32_t flash_get_start_address(const flash_t *obj)
{
return BOARD_FLASHIAP_START_ADDR;
}
uint32_t flash_get_size(const flash_t *obj)
{
return BOARD_FLASHIAP_SIZE;
}
uint8_t flash_get_erase_value(const flash_t *obj)
{
(void)obj;
return 0xFF;
}
#endif //DEVICE_FLASH

View File

@@ -0,0 +1,83 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "gpio_api.h"
#include "pinmap.h"
#include "fsl_gpio.h"
static GPIO_Type * const gpio_addrs[] = GPIO_BASE_PTRS;
uint32_t gpio_set(PinName pin)
{
MBED_ASSERT(pin != (PinName)NC);
uint32_t pin_num = pin & 0xFF;
pin_function(pin, GPIO_MUX_PORT);
return 1 << pin_num;
}
void gpio_init(gpio_t *obj, PinName pin)
{
clock_ip_name_t gpio_clocks[] = GPIO_CLOCKS;
obj->pin = pin;
if (pin == (PinName)NC)
return;
CLOCK_EnableClock(gpio_clocks[pin >> GPIO_PORT_SHIFT]);
pin_function(pin, GPIO_MUX_PORT);
}
void gpio_mode(gpio_t *obj, PinMode mode)
{
pin_mode(obj->pin, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = (obj->pin >> GPIO_PORT_SHIFT) & 0xF;
uint32_t gpio_pin_num = obj->pin & 0xFF;
GPIO_Type *base = gpio_addrs[port];
switch (direction) {
case PIN_INPUT:
base->GDIR &= ~(1U << gpio_pin_num);
break;
case PIN_OUTPUT:
base->GDIR |= (1U << gpio_pin_num);
break;
}
}
void gpio_write(gpio_t *obj, int value)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = (obj->pin >> GPIO_PORT_SHIFT) & 0xF;
uint32_t gpio_pin_num = obj->pin & 0xFF;
GPIO_WritePinOutput(gpio_addrs[port], gpio_pin_num, value);
}
int gpio_read(gpio_t *obj)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = (obj->pin >> GPIO_PORT_SHIFT) & 0xF;
uint32_t gpio_pin_num = obj->pin & 0xFF;
return (int)GPIO_ReadPinInput(gpio_addrs[port], gpio_pin_num);
}

View File

@@ -0,0 +1,261 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include "cmsis.h"
#include "gpio_irq_api.h"
#if DEVICE_INTERRUPTIN
#include "gpio_api.h"
#include "fsl_gpio.h"
#include "mbed_error.h"
#define CHANNEL_NUM 160
#define IRQ_DISABLED (0)
#define IRQ_RISING_EDGE (2)
#define IRQ_FALLING_EDGE (3)
#define IRQ_EITHER_EDGE (4)
static uint32_t channel_ids[CHANNEL_NUM] = {0};
static gpio_irq_handler irq_handler;
static GPIO_Type * const gpio_addrs[] = GPIO_BASE_PTRS;
/* Array of PORT IRQ number. */
static const IRQn_Type gpio_low_irqs[] = GPIO_COMBINED_LOW_IRQS;
static const IRQn_Type gpio_high_irqs[] = GPIO_COMBINED_HIGH_IRQS;
static void handle_interrupt_in(PortName port, int ch_base)
{
uint32_t i;
uint32_t interrupt_flags;
GPIO_Type *port_base = gpio_addrs[port];
interrupt_flags = GPIO_GetPinsInterruptFlags(port_base);
for (i = 0; i < 32; i++) {
if (interrupt_flags & (1 << i)) {
uint32_t id = channel_ids[ch_base + i];
if (id == 0) {
continue;
}
gpio_irq_event event = IRQ_NONE;
if (port_base->EDGE_SEL & (1U << i)) {
/* Either edge was selected, find the edge that triggered the interrupt */
event = (GPIO_ReadPinInput(port_base, i)) ? (IRQ_RISE) : (IRQ_FALL);
} else {
/* Detect if falling or rising edge */
uint32_t icr;
uint32_t icrShift;
icrShift = i;
if (i < 16) {
icr = port_base->ICR1;
} else {
icr = port_base->ICR2;
icrShift -= 16;
}
if (((icr >> (2 * icrShift)) & 0x3) == IRQ_RISING_EDGE) {
event = IRQ_RISE;
}
if (((icr >> (2 * icrShift)) & 0x3) == IRQ_FALLING_EDGE) {
event = IRQ_FALL;
}
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
}
}
GPIO_ClearPinsInterruptFlags(port_base, interrupt_flags);
}
void gpio1_irq(void)
{
handle_interrupt_in(Gpio1, 0);
}
void gpio2_irq(void)
{
handle_interrupt_in(Gpio2, 32);
}
void gpio3_irq(void)
{
handle_interrupt_in(Gpio3, 64);
}
void gpio4_irq(void)
{
handle_interrupt_in(Gpio4, 96);
}
void gpio5_irq(void)
{
handle_interrupt_in(Gpio5, 128);
}
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
if (pin == NC) {
return -1;
}
irq_handler = handler;
obj->port = (pin >> GPIO_PORT_SHIFT) & 0xF;
obj->pin = (pin & 0xFF);
uint32_t ch_base = 0;
uint32_t vector = (uint32_t)gpio1_irq;
switch (obj->port) {
case Gpio1:
ch_base = 0;
vector = (uint32_t)gpio1_irq;
break;
case Gpio2:
ch_base = 32;
vector = (uint32_t)gpio2_irq;
break;
case Gpio3:
ch_base = 64;
vector = (uint32_t)gpio3_irq;
break;
case Gpio4:
ch_base = 96;
vector = (uint32_t)gpio4_irq;
break;
case Gpio5:
ch_base = 128;
vector = (uint32_t)gpio5_irq;
break;
default:
error("gpio_irq only supported on port A-E.");
break;
}
if (obj->pin > 15) {
NVIC_SetVector(gpio_high_irqs[obj->port], vector);
NVIC_EnableIRQ(gpio_high_irqs[obj->port]);
} else {
NVIC_SetVector(gpio_low_irqs[obj->port], vector);
NVIC_EnableIRQ(gpio_low_irqs[obj->port]);
}
obj->ch = ch_base + obj->pin;
channel_ids[obj->ch] = id;
return 0;
}
void gpio_irq_free(gpio_irq_t *obj)
{
channel_ids[obj->ch] = 0;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
GPIO_Type *base = gpio_addrs[obj->port];
gpio_interrupt_mode_t irq_settings = kGPIO_NoIntmode;
uint32_t icr;
uint32_t icrShift;
uint32_t irq_curr_settings = IRQ_DISABLED;
icrShift = obj->pin;
if (obj->pin < 16) {
icr = base->ICR1;
} else {
icr = base->ICR2;
icrShift -= 16;
}
if (base->EDGE_SEL & (1U << obj->pin)) {
irq_curr_settings = IRQ_EITHER_EDGE;
} else {
if (((icr >> (2 * icrShift)) & 0x3) == IRQ_RISING_EDGE) {
irq_curr_settings = IRQ_RISING_EDGE;
}
if (((icr >> (2 * icrShift)) & 0x3) == IRQ_FALLING_EDGE) {
irq_curr_settings = IRQ_FALLING_EDGE;
}
}
switch (irq_curr_settings) {
case IRQ_DISABLED:
if (enable)
irq_settings = (event == IRQ_RISE) ? (kGPIO_IntRisingEdge) : (kGPIO_IntFallingEdge);
break;
case IRQ_RISING_EDGE:
if (enable) {
irq_settings = (event == IRQ_RISE) ? (kGPIO_IntRisingEdge) : (kGPIO_IntRisingOrFallingEdge);
} else {
if (event == IRQ_FALL)
irq_settings = kGPIO_IntRisingEdge;
}
break;
case IRQ_FALLING_EDGE:
if (enable) {
irq_settings = (event == IRQ_FALL) ? (kGPIO_IntFallingEdge) : (kGPIO_IntRisingOrFallingEdge);
} else {
if (event == IRQ_RISE)
irq_settings = kGPIO_IntFallingEdge;
}
break;
case IRQ_EITHER_EDGE:
if (enable) {
irq_settings = kGPIO_IntRisingOrFallingEdge;
} else {
irq_settings = (event == IRQ_RISE) ? (kGPIO_IntFallingEdge) : (kGPIO_IntRisingEdge);
}
break;
}
if (irq_settings == kGPIO_NoIntmode) {
GPIO_DisableInterrupts(base, 1U << obj->pin);
} else {
GPIO_SetPinInterruptConfig(base, obj->pin, irq_settings);
GPIO_EnableInterrupts(base, 1U << obj->pin);
}
}
void gpio_irq_enable(gpio_irq_t *obj)
{
if (obj->pin > 15) {
NVIC_EnableIRQ(gpio_high_irqs[obj->port]);
} else {
NVIC_EnableIRQ(gpio_low_irqs[obj->port]);
}
}
void gpio_irq_disable(gpio_irq_t *obj)
{
if (obj->pin > 15) {
NVIC_DisableIRQ(gpio_high_irqs[obj->port]);
} else {
NVIC_DisableIRQ(gpio_low_irqs[obj->port]);
}
}
#endif

View File

@@ -0,0 +1,36 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_GPIO_OBJECT_H
#define MBED_GPIO_OBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PinName pin;
} gpio_t;
static inline int gpio_is_connected(const gpio_t *obj)
{
return obj->pin != (PinName)NC;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,306 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "i2c_api.h"
#if DEVICE_I2C
#include "cmsis.h"
#include "pinmap.h"
#include "fsl_lpi2c.h"
#include "PeripheralPins.h"
/* Array of I2C peripheral base address. */
static LPI2C_Type *const i2c_addrs[] = LPI2C_BASE_PTRS;
extern void i2c_setup_clock();
extern uint32_t i2c_get_clock();
void pin_mode_opendrain(PinName pin, bool enable);
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
{
uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->instance = pinmap_merge(i2c_sda, i2c_scl);
MBED_ASSERT((int)obj->instance != NC);
lpi2c_master_config_t master_config;
i2c_setup_clock();
LPI2C_MasterGetDefaultConfig(&master_config);
LPI2C_MasterInit(i2c_addrs[obj->instance], &master_config, i2c_get_clock());
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
pin_mode(sda, PullUp_22K);
pin_mode(scl, PullUp_22K);
pin_mode_opendrain(sda, true);
pin_mode_opendrain(scl, true);
}
int i2c_start(i2c_t *obj)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
int status = 0;
obj->address_set = 0;
/* Clear all flags. */
LPI2C_MasterClearStatusFlags(base, kLPI2C_MasterEndOfPacketFlag |
kLPI2C_MasterStopDetectFlag |
kLPI2C_MasterNackDetectFlag |
kLPI2C_MasterArbitrationLostFlag |
kLPI2C_MasterFifoErrFlag |
kLPI2C_MasterPinLowTimeoutFlag |
kLPI2C_MasterDataMatchFlag);
/* Turn off auto-stop option. */
base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
return status;
}
int i2c_stop(i2c_t *obj)
{
if (LPI2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) {
return 1;
}
obj->address_set = 0;
return 0;
}
void i2c_frequency(i2c_t *obj, int hz)
{
uint32_t busClock;
busClock = i2c_get_clock();
LPI2C_MasterSetBaudRate(i2c_addrs[obj->instance], busClock, hz);
}
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
lpi2c_master_transfer_t master_xfer;
memset(&master_xfer, 0, sizeof(master_xfer));
master_xfer.slaveAddress = address >> 1;
master_xfer.direction = kLPI2C_Read;
master_xfer.data = (uint8_t *)data;
master_xfer.dataSize = length;
if (!stop) {
master_xfer.flags |= kLPI2C_TransferNoStopFlag;
}
/* The below function will issue a STOP signal at the end of the transfer.
* This is required by the hardware in order to receive the last byte
*/
if (LPI2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
return I2C_ERROR_NO_SLAVE;
}
return length;
}
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
lpi2c_master_transfer_t master_xfer;
if (length == 0) {
if (LPI2C_MasterStart(base, address >> 1, kLPI2C_Write) != kStatus_Success) {
return I2C_ERROR_NO_SLAVE;
}
/* Wait till START has been flushed out of the FIFO */
while (!(base->MSR & kLPI2C_MasterBusBusyFlag)) {
}
/* Send the STOP signal */
base->MTDR = LPI2C_MTDR_CMD(0x2U);
/* Wait till STOP has been sent successfully */
while (!(base->MSR & kLPI2C_MasterStopDetectFlag)) {
}
if (base->MSR & kLPI2C_MasterNackDetectFlag) {
return I2C_ERROR_NO_SLAVE;
} else {
return length;
}
}
memset(&master_xfer, 0, sizeof(master_xfer));
master_xfer.slaveAddress = address >> 1;
master_xfer.direction = kLPI2C_Write;
master_xfer.data = (uint8_t *)data;
master_xfer.dataSize = length;
if (!stop) {
master_xfer.flags |= kLPI2C_TransferNoStopFlag;
}
if (LPI2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
return I2C_ERROR_NO_SLAVE;
}
return length;
}
void i2c_reset(i2c_t *obj)
{
i2c_stop(obj);
}
int i2c_byte_read(i2c_t *obj, int last)
{
uint8_t data;
LPI2C_Type *base = i2c_addrs[obj->instance];
lpi2c_master_transfer_t master_xfer;
memset(&master_xfer, 0, sizeof(master_xfer));
master_xfer.direction = kLPI2C_Read;
master_xfer.data = &data;
master_xfer.dataSize = 1;
master_xfer.flags = kLPI2C_TransferNoStopFlag | kLPI2C_TransferNoStartFlag;
if (LPI2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
return I2C_ERROR_NO_SLAVE;
}
return data;
}
int i2c_byte_write(i2c_t *obj, int data)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
uint32_t status;
size_t txCount;
size_t txFifoSize = FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
/* Clear error flags. */
LPI2C_MasterClearStatusFlags(base, LPI2C_MasterGetStatusFlags(base));
/* Wait till there is room in the TX FIFO */
do {
/* Get the number of words in the tx fifo and compute empty slots. */
LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
txCount = txFifoSize - txCount;
} while (!txCount);
if (!obj->address_set) {
obj->address_set = 1;
/* Issue start command. */
base->MTDR = LPI2C_MTDR_CMD(0x4U) | LPI2C_MTDR_DATA(data);
} else {
/* Write byte into LPI2C master data register. */
base->MTDR = data;
}
/* Wait till data is pushed out of the FIFO */
while (!(base->MSR & kLPI2C_MasterTxReadyFlag)) {
}
status = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
if (status == kStatus_Success) {
return 1;
} else if (status == kStatus_LPI2C_Nak) {
return 0;
} else {
return 2;
}
}
const PinMap *i2c_master_sda_pinmap()
{
return PinMap_I2C_SDA;
}
const PinMap *i2c_master_scl_pinmap()
{
return PinMap_I2C_SCL;
}
const PinMap *i2c_slave_sda_pinmap()
{
return PinMap_I2C_SDA;
}
const PinMap *i2c_slave_scl_pinmap()
{
return PinMap_I2C_SCL;
}
#if DEVICE_I2CSLAVE
void i2c_slave_mode(i2c_t *obj, int enable_slave)
{
lpi2c_slave_config_t slave_config;
LPI2C_SlaveGetDefaultConfig(&slave_config);
slave_config.enableSlave = (bool)enable_slave;
LPI2C_SlaveInit(i2c_addrs[obj->instance], &slave_config, i2c_get_clock());
}
int i2c_slave_receive(i2c_t *obj)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
uint32_t status_flags = LPI2C_SlaveGetStatusFlags(base);
if (status_flags & kLPI2C_SlaveAddressValidFlag) {
if (base->SASR & kLPI2C_Read) {
// read addressed
return 1;
} else {
// write addressed
return 3;
}
} else {
// slave not addressed
return 0;
}
}
int i2c_slave_read(i2c_t *obj, char *data, int length)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
int actual_rx;
LPI2C_SlaveReceive(base, (uint8_t *)data, length, (size_t *)&actual_rx);
return actual_rx;
}
int i2c_slave_write(i2c_t *obj, const char *data, int length)
{
LPI2C_Type *base = i2c_addrs[obj->instance];
int actual_rx;
LPI2C_SlaveSend(base, (uint8_t *)data, length, (size_t *)&actual_rx);
return actual_rx;
}
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
{
i2c_addrs[obj->instance]->SAMR = LPI2C_SAMR_ADDR0(address & 0xfe);
}
#endif
#endif

View File

@@ -0,0 +1,122 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if DEVICE_LPTICKER
#include "lp_ticker_api.h"
#include "fsl_gpt.h"
#include "cmsis.h"
const ticker_info_t* lp_ticker_get_info()
{
static const ticker_info_t info = {
32768, // 32kHz
32 // 32 bit counter
};
return &info;
}
static bool lp_ticker_inited = false;
static void gpt_isr(void)
{
GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag);
GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
lp_ticker_irq_handler();
}
/** Initialize the low power ticker
*
*/
void lp_ticker_init(void)
{
gpt_config_t gptConfig;
if (!lp_ticker_inited) {
/* Setup GPT */
GPT_GetDefaultConfig(&gptConfig);
/* Use 32kHz drive */
gptConfig.clockSource = kGPT_ClockSource_LowFreq;
gptConfig.enableFreeRun = true;
gptConfig.enableMode = false;
gptConfig.enableRunInDoze = true;
GPT_Init(GPT2, &gptConfig);
GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
NVIC_ClearPendingIRQ(GPT2_IRQn);
NVIC_SetVector(GPT2_IRQn, (uint32_t)gpt_isr);
EnableIRQ(GPT2_IRQn);
GPT_StartTimer(GPT2);
lp_ticker_inited = true;
} else {
GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
}
}
/** Read the current counter
*
* @return The current timer's counter value in ticks
*/
uint32_t lp_ticker_read(void)
{
return GPT_GetCurrentTimerCount(GPT2);
}
/** Set interrupt for specified timestamp
*
* @param timestamp The time in ticks to be set
*/
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
if (timestamp == 0) {
timestamp = 1;
}
GPT_StopTimer(GPT2);
GPT_SetOutputCompareValue(GPT2, kGPT_OutputCompare_Channel1, timestamp);
GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag);
GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
GPT_StartTimer(GPT2);
}
void lp_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(GPT2_IRQn);
}
/** Disable low power ticker interrupt
*
*/
void lp_ticker_disable_interrupt(void)
{
GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
}
/** Clear the low power ticker interrupt
*
*/
void lp_ticker_clear_interrupt(void)
{
GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag);
}
void lp_ticker_free(void)
{
GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);
NVIC_DisableIRQ(GPT2_IRQn);
}
#endif /* DEVICE_LPTICKER */

View File

@@ -0,0 +1,81 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_OBJECTS_H
#define MBED_OBJECTS_H
#include "cmsis.h"
#include "PortNames.h"
#include "PeripheralNames.h"
#include "PinNames.h"
#ifdef __cplusplus
extern "C" {
#endif
struct gpio_irq_s {
uint32_t port;
uint32_t pin;
uint32_t ch;
};
struct port_s {
PortName port;
uint32_t mask;
};
struct pwmout_s {
PWMName pwm_name;
};
struct serial_s {
int index;
};
struct analogin_s {
ADCName adc;
};
struct i2c_s {
uint32_t instance;
uint8_t address_set;
};
struct spi_s {
uint32_t instance;
uint8_t bits;
};
struct dac_s {
DACName dac;
};
struct trng_s {
uint8_t dummy;
};
#if DEVICE_FLASH
struct flash_s {
uint8_t dummy;
};
#endif
#include "gpio_object.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,158 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "PeripheralPins.h"
#include "mbed_error.h"
#include "fsl_clock.h"
/* Array of IOMUX base address. */
static uint32_t iomux_base_addrs[FSL_FEATURE_SOC_IGPIO_COUNT] = { 0x401F80BC, 0x401F813C, 0u, 0x401F8014, 0x400A8000 };
/* Get the IOMUX register address from the GPIO3 pin number */
static uint32_t get_iomux_reg_base(PinName pin)
{
int32_t gpio_pin = pin & 0xFF;
uint32_t retval = 0;
if ((gpio_pin >= 0) && (gpio_pin < 12)) {
retval = 0x401F81D4 + (gpio_pin * 4);
} else if ((gpio_pin >= 12) && (gpio_pin < 18)) {
retval = 0x401F81BC + ((gpio_pin - 12) * 4);
} else if ((gpio_pin >= 18) && (gpio_pin < 28)) {
retval = 0x401F8094 + ((gpio_pin - 18) * 4);
}
return retval;
}
void pin_function(PinName pin, int function)
{
MBED_ASSERT(pin != (PinName)NC);
uint32_t muxregister = iomux_base_addrs[(pin >> GPIO_PORT_SHIFT) - 1];
uint32_t daisyregister;
CLOCK_EnableClock(kCLOCK_Iomuxc);
/* Get mux register address */
if (muxregister == 0) {
muxregister = get_iomux_reg_base(pin);
} else {
muxregister = muxregister + ((pin & 0xFF) * 4);
}
/* Write to the mux register */
*((volatile uint32_t *)muxregister) = IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(function) |
IOMUXC_SW_MUX_CTL_PAD_SION((function >> SION_BIT_SHIFT) & 0x1);
/* If required write to the input daisy register */
daisyregister = (function >> DAISY_REG_SHIFT) & 0xFFF;
if (daisyregister != 0) {
daisyregister = daisyregister + 0x401F8000;
*((volatile uint32_t *)daisyregister) = IOMUXC_SELECT_INPUT_DAISY(((function >> DAISY_REG_VALUE_SHIFT) & 0xF));
}
}
void pin_mode(PinName pin, PinMode mode)
{
MBED_ASSERT(pin != (PinName)NC);
uint32_t instance = pin >> GPIO_PORT_SHIFT;
uint32_t reg;
uint32_t muxregister = iomux_base_addrs[instance - 1];
uint32_t configregister;
if (muxregister == 0) {
muxregister = get_iomux_reg_base(pin);
} else {
muxregister = muxregister + ((pin & 0xFF) * 4);
}
/* Get pad register address */
if (instance == 5) {
configregister = muxregister + 0x10;
} else {
configregister = muxregister + 0x1F0;
}
reg = *((volatile uint32_t *)configregister);
switch (mode) {
case PullNone:
/* Write 0 to the PUE bit & 1 to the PKE bit to set the pad to keeper mode */
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
reg |= (IOMUXC_SW_PAD_CTL_PAD_PKE_MASK);
break;
case PullDown:
/* Write 1 to PKE & PUE bit to enable the pull configuration and 0 to PUS bit for 100K pull down */
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_PUS_MASK);
reg |= (IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
break;
case PullUp_47K:
/* Write 1 to PKE & PUE bit to enable the pull configuration and 1 to PUS bit for 47K pull up*/
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_PUS_MASK);
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS(1);
reg |= (IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
break;
case PullUp_100K:
/* Write 1 to PKE & PUE bit to enable the pull configuration and 2 to PUS bit for 100K pull up*/
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_PUS_MASK);
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS(2);
reg |= (IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
break;
case PullUp_22K:
/* Write 1 to PKE & PUE bit to enable the pull configuration and 3 to PUS bit for 22K pull up*/
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_PUS_MASK);
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS(3);
reg |= (IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
break;
default:
break;
}
/* Below settings for DSE and SPEED fields per test results */
reg = (reg & ~(IOMUXC_SW_PAD_CTL_PAD_DSE_MASK | IOMUXC_SW_PAD_CTL_PAD_SPEED_MASK)) |
IOMUXC_SW_PAD_CTL_PAD_DSE(6) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2);
/* Write value to the pad register */
*((volatile uint32_t *)configregister) = reg;
}
void pin_mode_opendrain(PinName pin, bool enable)
{
MBED_ASSERT(pin != (PinName)NC);
uint32_t instance = pin >> GPIO_PORT_SHIFT;
uint32_t muxregister = iomux_base_addrs[instance - 1];
uint32_t configregister;
if (muxregister == 0) {
muxregister = get_iomux_reg_base(pin);
} else {
muxregister = muxregister + ((pin & 0xFF) * 4);
}
/* Get pad register address */
if (instance == 5) {
configregister = muxregister + 0x10;
} else {
configregister = muxregister + 0x1F0;
}
if (enable) {
*((volatile uint32_t *)configregister) |= IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
} else {
*((volatile uint32_t *)configregister) &= ~IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
}
}

View File

@@ -0,0 +1,87 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "port_api.h"
#if DEVICE_PORTIN || DEVICE_PORTOUT
#include "pinmap.h"
#include "gpio_api.h"
/* Array of GPIO peripheral base address. */
static GPIO_Type *const port_addrs[] = GPIO_BASE_PTRS;
PinName port_pin(PortName port, int pin_n)
{
return (PinName)((port << GPIO_PORT_SHIFT) | pin_n);
}
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
{
obj->port = port;
obj->mask = mask;
// The function is set per pin: reuse gpio logic
for (uint32_t i = 0; i < 32; i++) {
if (obj->mask & (1 << i)) {
gpio_set(port_pin(obj->port, i));
}
}
port_dir(obj, dir);
}
void port_mode(port_t *obj, PinMode mode)
{
// The mode is set per pin: reuse pinmap logic
for (uint32_t i = 0; i < 32; i++) {
if (obj->mask & (1 << i)) {
pin_mode(port_pin(obj->port, i), mode);
}
}
}
void port_dir(port_t *obj, PinDirection dir)
{
GPIO_Type *base = port_addrs[obj->port];
uint32_t direction = base->GDIR;
switch (dir) {
case PIN_INPUT :
direction &= ~obj->mask;
break;
case PIN_OUTPUT:
direction |= obj->mask;
break;
}
base->GDIR = direction;
}
void port_write(port_t *obj, int value)
{
GPIO_Type *base = port_addrs[obj->port];
uint32_t input = base->DR & ~obj->mask;
base->DR = (input | (uint32_t)(value & obj->mask));
}
int port_read(port_t *obj)
{
GPIO_Type *base = port_addrs[obj->port];
return (int)(base->DR & obj->mask);
}
#endif

View File

@@ -0,0 +1,231 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "pwmout_api.h"
#if DEVICE_PWMOUT
#include "cmsis.h"
#include "pinmap.h"
#include "fsl_pwm.h"
#include "PeripheralPins.h"
static float pwm_clock_mhz = 0;
/* Array of PWM peripheral base address. */
static PWM_Type *const pwm_addrs[] = PWM_BASE_PTRS;
extern void pwm_setup();
extern uint32_t pwm_get_clock();
void pwmout_init(pwmout_t* obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
uint32_t pwm_base_clock;
uint32_t instance = (pwm >> PWM_SHIFT) & 0x7;
uint32_t module = (pwm >> PWM_MODULE_SHIFT) & 0x3;
uint32_t pwmchannel = pwm & 0x1;
pwm_config_t pwmInfo;
static uint32_t clkdiv;
obj->pwm_name = pwm;
pwm_base_clock = pwm_get_clock();
if (pwm_clock_mhz == 0) {
float clkval = (float)pwm_base_clock / 1000000.0f;
while (clkval > 1) {
clkdiv++;
clkval /= 2.0f;
if (clkdiv == 7) {
break;
}
}
pwm_clock_mhz = clkval;
}
pwm_setup(instance);
/* Initialize PWM module */
PWM_GetDefaultConfig(&pwmInfo);
pwmInfo.prescale = (pwm_clock_prescale_t)clkdiv;
PWM_Init(pwm_addrs[instance], (pwm_submodule_t)module, &pwmInfo);
pwm_signal_param_t channel_config = {
.level = kPWM_HighTrue,
.dutyCyclePercent = 0,
.deadtimeValue = 0
};
if (pwmchannel == 0) {
channel_config.pwmChannel = kPWM_PwmA;
} else {
channel_config.pwmChannel = kPWM_PwmB;
}
// Setup the module signals to be low
PWM_SetupPwm(pwm_addrs[instance], (pwm_submodule_t)module, &channel_config, 1, kPWM_EdgeAligned, 50, pwm_base_clock);
/* Set the load okay bit for all submodules to load registers from their buffer */
PWM_SetPwmLdok(pwm_addrs[instance], (1 << module), true);
/* Start the timer for the sub-module */
PWM_StartTimer(pwm_addrs[instance], (1 << module));
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
{
uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x7;
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
PWM_StopTimer(pwm_addrs[instance], (1 << module));
}
void pwmout_write(pwmout_t* obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
} else if (value > 1.0f) {
value = 1.0f;
}
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
uint32_t pwmchannel = obj->pwm_name & 0x1;
uint16_t pulseCnt = 0;
pulseCnt = base->SM[module].VAL1;
uint32_t new_count = (uint32_t)((float)(pulseCnt) * value);
/* Setup the PWM dutycycle */
if (pwmchannel == 0) {
base->SM[module].VAL2 = 0;
base->SM[module].VAL3 = new_count;
} else {
base->SM[module].VAL4 = 0;
base->SM[module].VAL5 = new_count;
}
/* Set the load okay bit */
PWM_SetPwmLdok(base, (1 << module), true);
}
float pwmout_read(pwmout_t* obj)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
uint32_t pwmchannel = obj->pwm_name & 0x1;
uint16_t count;
uint16_t mod = (base->SM[module].VAL1) & PWM_VAL1_VAL1_MASK;
if (pwmchannel == 0) {
count = (base->SM[module].VAL3) & PWM_VAL3_VAL3_MASK;
} else {
count = (base->SM[module].VAL5) & PWM_VAL5_VAL5_MASK;
}
if (mod == 0) {
return 0.0;
}
float v = (float)(count) / (float)(mod);
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}
// Set the PWM period, keeping the duty cycle the same.
void pwmout_period_us(pwmout_t* obj, int us)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
float dc = pwmout_read(obj);
uint32_t pwm_base_clock;
pwm_base_clock = pwm_get_clock();
uint32_t clkdiv = 0;
pwm_clock_mhz = (float) pwm_base_clock / 1000000.0f;
uint32_t mod = (pwm_clock_mhz * (float) us) - 1;
while (mod > 0xFFFF) {
++clkdiv;
pwm_clock_mhz /= 2.0f;
mod = (pwm_clock_mhz * (float) us) - 1;
if (clkdiv == 7) {
break;
}
}
uint32_t PRSC = base->SM[module].CTRL & ~PWM_CTRL_PRSC_MASK;
PRSC |= PWM_CTRL_PRSC(clkdiv);
base->SM[module].CTRL = PRSC;
/* Indicates the end of the PWM period */
base->SM[module].VAL1 = PWM_VAL1_VAL1(mod);
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
uint32_t pwmchannel = obj->pwm_name & 0x1;
uint32_t value = (uint32_t)(pwm_clock_mhz * (float)us);
/* Setup the PWM dutycycle */
if (pwmchannel == 0) {
base->SM[module].VAL2 = 0;
base->SM[module].VAL3 = value;
} else {
base->SM[module].VAL4 = 0;
base->SM[module].VAL5 = value;
}
/* Set the load okay bit */
PWM_SetPwmLdok(base, (1 << module), true);
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;
}
#endif

View File

@@ -0,0 +1,94 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rtc_api.h"
#if DEVICE_RTC
#include "fsl_snvs_lp.h"
static bool rtc_time_set = false;
void rtc_init(void)
{
snvs_lp_srtc_config_t snvsRtcConfig;
SNVS_LP_SRTC_GetDefaultConfig(&snvsRtcConfig);
SNVS_LP_SRTC_Init(SNVS, &snvsRtcConfig);
SNVS_LP_SRTC_StartTimer(SNVS);
}
void rtc_free(void)
{
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
defined(SNVS_LP_CLOCKS))
CLOCK_DisableClock(kCLOCK_SnvsLp0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*
* Little check routine to see if the RTC has been enabled
* 0 = Disabled, 1 = Enabled
*/
int rtc_isenabled(void)
{
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
defined(SNVS_LP_CLOCKS))
CLOCK_EnableClock(kCLOCK_SnvsLp0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
const bool rtc_init_done = ((SNVS->LPCR & SNVS_LPCR_SRTC_ENV_MASK) >> SNVS_LPCR_SRTC_ENV_SHIFT);
/* If RTC is not initialized, then disable the clock gate on exit. */
if(!rtc_init_done) {
rtc_free();
}
return (rtc_init_done & rtc_time_set);
}
time_t rtc_read(void)
{
uint32_t seconds = 0;
uint32_t tmp = 0;
/* Do consecutive reads until value is correct */
do {
seconds = tmp;
tmp = (SNVS->LPSRTCMR << 17U) | (SNVS->LPSRTCLR >> 15U);
} while (tmp != seconds);
return (time_t)seconds;
}
void rtc_write(time_t t)
{
if (t == 0) {
t = 1;
}
SNVS_LP_SRTC_StopTimer(SNVS);
SNVS->LPSRTCMR = (uint32_t)(t >> 17U);
SNVS->LPSRTCLR = (uint32_t)(t << 15U);
SNVS_LP_SRTC_StartTimer(SNVS);
rtc_time_set = true;
}
#endif

View File

@@ -0,0 +1,381 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "serial_api.h"
#if DEVICE_SERIAL
// math.h required for floating point operations for baud rate calculation
#include <math.h>
#include "mbed_assert.h"
#include <string.h>
#include "cmsis.h"
#include "pinmap.h"
#include "fsl_lpuart.h"
#include "PeripheralPins.h"
#include "fsl_clock_config.h"
/* LPUART starts from index 1 */
static uint32_t serial_irq_ids[FSL_FEATURE_SOC_LPUART_COUNT + 1] = {0};
static uart_irq_handler irq_handler;
/* Array of UART peripheral base address. */
static LPUART_Type *const uart_addrs[] = LPUART_BASE_PTRS;
int stdio_uart_inited = 0;
serial_t stdio_uart;
extern void serial_setup_clock(void);
extern uint32_t serial_get_clock(void);
void serial_init(serial_t *obj, PinName tx, PinName rx)
{
uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX);
uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX);
obj->index = pinmap_merge(uart_tx, uart_rx);
MBED_ASSERT((int)obj->index != NC);
serial_setup_clock();
lpuart_config_t config;
LPUART_GetDefaultConfig(&config);
config.baudRate_Bps = 9600;
config.enableTx = false;
config.enableRx = false;
LPUART_Init(uart_addrs[obj->index], &config, serial_get_clock());
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
if (tx != NC) {
LPUART_EnableTx(uart_addrs[obj->index], true);
pin_mode(tx, PullDefault);
}
if (rx != NC) {
LPUART_EnableRx(uart_addrs[obj->index], true);
pin_mode(rx, PullDefault);
}
if (obj->index == STDIO_UART) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj)
{
LPUART_Deinit(uart_addrs[obj->index]);
serial_irq_ids[obj->index] = 0;
}
void serial_baud(serial_t *obj, int baudrate)
{
LPUART_SetBaudRate(uart_addrs[obj->index], (uint32_t)baudrate, serial_get_clock());
}
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
{
LPUART_Type *base = uart_addrs[obj->index];
uint8_t temp;
/* Set bit count and parity mode. */
temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
if (parity != ParityNone) {
/* Enable Parity */
temp |= (LPUART_CTRL_PE_MASK | LPUART_CTRL_M_MASK);
if (parity == ParityOdd) {
temp |= LPUART_CTRL_PT_MASK;
} else if (parity == ParityEven) {
// PT=0 so nothing more to do
} else {
// Hardware does not support forced parity
MBED_ASSERT(0);
}
}
base->CTRL = temp;
#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
/* set stop bit per char */
temp = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)--stop_bits);
#endif
}
/******************************************************************************
* INTERRUPTS HANDLING
******************************************************************************/
static inline void uart_irq(uint32_t transmit_empty, uint32_t receive_full, uint32_t index)
{
LPUART_Type *base = uart_addrs[index];
/* If RX overrun. */
if (LPUART_STAT_OR_MASK & base->STAT) {
/* Read base->D, otherwise the RX does not work. */
(void)base->DATA;
LPUART_ClearStatusFlags(base, kLPUART_RxOverrunFlag);
}
if (serial_irq_ids[index] != 0) {
if (transmit_empty) {
irq_handler(serial_irq_ids[index], TxIrq);
}
if (receive_full) {
irq_handler(serial_irq_ids[index], RxIrq);
}
}
}
void uart1_irq()
{
uint32_t status_flags = LPUART1->STAT;
uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 1);
}
void uart2_irq()
{
uint32_t status_flags = LPUART2->STAT;
uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 2);
}
void uart3_irq()
{
uint32_t status_flags = LPUART3->STAT;
uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 3);
}
void uart4_irq()
{
uint32_t status_flags = LPUART4->STAT;
uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 4);
}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
{
irq_handler = handler;
serial_irq_ids[obj->index] = id;
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
{
IRQn_Type uart_irqs[] = LPUART_RX_TX_IRQS;
uint32_t vector = 0;
switch (obj->index) {
case 1:
vector = (uint32_t)&uart1_irq;
break;
case 2:
vector = (uint32_t)&uart2_irq;
break;
case 3:
vector = (uint32_t)&uart3_irq;
break;
case 4:
vector = (uint32_t)&uart4_irq;
break;
default:
break;
}
if (enable) {
switch (irq) {
case RxIrq:
LPUART_EnableInterrupts(uart_addrs[obj->index], kLPUART_RxDataRegFullInterruptEnable);
break;
case TxIrq:
LPUART_EnableInterrupts(uart_addrs[obj->index], kLPUART_TxDataRegEmptyInterruptEnable);
break;
default:
break;
}
NVIC_SetVector(uart_irqs[obj->index], vector);
NVIC_EnableIRQ(uart_irqs[obj->index]);
} else { // disable
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
switch (irq) {
case RxIrq:
LPUART_DisableInterrupts(uart_addrs[obj->index], kLPUART_RxDataRegFullInterruptEnable);
break;
case TxIrq:
LPUART_DisableInterrupts(uart_addrs[obj->index], kLPUART_TxDataRegEmptyInterruptEnable);
break;
default:
break;
}
switch (other_irq) {
case RxIrq:
all_disabled = ((LPUART_GetEnabledInterrupts(uart_addrs[obj->index]) & kLPUART_RxDataRegFullInterruptEnable) == 0);
break;
case TxIrq:
all_disabled = ((LPUART_GetEnabledInterrupts(uart_addrs[obj->index]) & kLPUART_TxDataRegEmptyInterruptEnable) == 0);
break;
default:
break;
}
if (all_disabled)
NVIC_DisableIRQ(uart_irqs[obj->index]);
}
}
int serial_getc(serial_t *obj)
{
uint8_t data;
LPUART_ReadBlocking(uart_addrs[obj->index], &data, 1);
return data;
}
void serial_putc(serial_t *obj, int c)
{
while (!serial_writable(obj));
LPUART_WriteByte(uart_addrs[obj->index], (uint8_t)c);
}
int serial_readable(serial_t *obj)
{
uint32_t status_flags = LPUART_GetStatusFlags(uart_addrs[obj->index]);
if (status_flags & kLPUART_RxOverrunFlag) {
LPUART_ClearStatusFlags(uart_addrs[obj->index], kLPUART_RxOverrunFlag);
}
return (status_flags & kLPUART_RxDataRegFullFlag);
}
int serial_writable(serial_t *obj)
{
uint32_t status_flags = LPUART_GetStatusFlags(uart_addrs[obj->index]);
if (status_flags & kLPUART_RxOverrunFlag) {
LPUART_ClearStatusFlags(uart_addrs[obj->index], kLPUART_RxOverrunFlag);
}
return (status_flags & kLPUART_TxDataRegEmptyFlag);
}
void serial_clear(serial_t *obj)
{
}
void serial_pinout_tx(PinName tx)
{
pinmap_pinout(tx, PinMap_UART_TX);
}
void serial_break_set(serial_t *obj)
{
uart_addrs[obj->index]->CTRL |= LPUART_CTRL_SBK_MASK;
}
void serial_break_clear(serial_t *obj)
{
uart_addrs[obj->index]->CTRL &= ~LPUART_CTRL_SBK_MASK;
}
const PinMap *serial_tx_pinmap()
{
return PinMap_UART_TX;
}
const PinMap *serial_rx_pinmap()
{
return PinMap_UART_RX;
}
const PinMap *serial_cts_pinmap()
{
#if !DEVICE_SERIAL_FC
static const PinMap PinMap_UART_CTS[] = {
{NC, NC, 0}
};
#endif
return PinMap_UART_CTS;
}
const PinMap *serial_rts_pinmap()
{
#if !DEVICE_SERIAL_FC
static const PinMap PinMap_UART_RTS[] = {
{NC, NC, 0}
};
#endif
return PinMap_UART_RTS;
}
static int serial_is_enabled(uint32_t uart_index)
{
int clock_enabled = 0;
switch (uart_index) {
case 1:
clock_enabled = (CCM->CCGR5 & CCM_CCGR5_CG12_MASK) >> CCM_CCGR5_CG12_SHIFT;
break;
case 2:
clock_enabled = (CCM->CCGR0 & CCM_CCGR0_CG14_MASK) >> CCM_CCGR0_CG14_SHIFT;
break;
case 3:
clock_enabled = (CCM->CCGR0 & CCM_CCGR0_CG6_MASK) >> CCM_CCGR0_CG6_SHIFT;
break;
case 4:
clock_enabled = (CCM->CCGR1 & CCM_CCGR1_CG12_MASK) >> CCM_CCGR1_CG12_SHIFT;
break;
case 5:
clock_enabled = (CCM->CCGR3 & CCM_CCGR3_CG1_MASK) >> CCM_CCGR3_CG1_SHIFT;
break;
case 6:
clock_enabled = (CCM->CCGR3 & CCM_CCGR3_CG3_MASK) >> CCM_CCGR3_CG3_SHIFT;
break;
case 7:
clock_enabled = (CCM->CCGR5 & CCM_CCGR5_CG13_MASK) >> CCM_CCGR5_CG13_SHIFT;
break;
case 8:
clock_enabled = (CCM->CCGR6 & CCM_CCGR6_CG7_MASK) >> CCM_CCGR6_CG7_SHIFT;
break;
default:
break;
}
return clock_enabled;
}
bool serial_check_tx_ongoing()
{
LPUART_Type *base;
int i;
bool uart_tx_ongoing = false;
/* The first LPUART instance number is 1 */
for (i = 1; i <= FSL_FEATURE_SOC_LPUART_COUNT; i++) {
/* First check if UART is enabled */
if (!serial_is_enabled(i)) {
/* UART is not enabled, check the next instance */
continue;
}
base = uart_addrs[i];
/* Check if data is waiting to be written out of transmit buffer */
if (!(kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags((LPUART_Type *)base))) {
uart_tx_ongoing = true;
break;
}
}
return uart_tx_ongoing;
}
#endif

View File

@@ -0,0 +1,46 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sleep_api.h"
#include "cmsis.h"
#include "fsl_clock.h"
extern void vPortPRE_SLEEP_PROCESSING(clock_mode_t powermode);
extern void vPortPOST_SLEEP_PROCESSING(clock_mode_t powermode);
extern bool serial_check_tx_ongoing();
void hal_sleep(void)
{
__DSB();
__WFI();
__ISB();
}
void hal_deepsleep(void)
{
/* Check if any of the UART's is transmitting data */
if (serial_check_tx_ongoing()) {
return;
}
vPortPRE_SLEEP_PROCESSING(kCLOCK_ModeStop);
__DSB();
__WFI();
__ISB();
vPortPOST_SLEEP_PROCESSING(kCLOCK_ModeStop);
}

View File

@@ -0,0 +1,208 @@
/* mbed Microcontroller Library
* Copyright (c) 2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <math.h>
#include "mbed_assert.h"
#include "spi_api.h"
#if DEVICE_SPI
#include "cmsis.h"
#include "pinmap.h"
#include "mbed_error.h"
#include "fsl_lpspi.h"
#include "PeripheralPins.h"
/* Array of SPI peripheral base address. */
static LPSPI_Type *const spi_address[] = LPSPI_BASE_PTRS;
extern uint32_t spi_get_clock(void);
extern void spi_setup_clock();
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
{
// determine the SPI to use
uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
obj->instance = pinmap_merge(spi_data, spi_cntl);
MBED_ASSERT((int)obj->instance != NC);
// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK);
if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL);
}
spi_setup_clock();
}
void spi_free(spi_t *obj)
{
LPSPI_Deinit(spi_address[obj->instance]);
}
void spi_format(spi_t *obj, int bits, int mode, int slave)
{
lpspi_master_config_t master_config;
lpspi_slave_config_t slave_config;
if (slave) {
/* Slave config */
LPSPI_SlaveGetDefaultConfig(&slave_config);
slave_config.bitsPerFrame = (uint32_t)bits;;
slave_config.cpol = (mode & 0x2) ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh;
slave_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
LPSPI_SlaveInit(spi_address[obj->instance], &slave_config);
} else {
/* Master config */
LPSPI_MasterGetDefaultConfig(&master_config);
master_config.bitsPerFrame = (uint32_t)bits;;
master_config.cpol = (mode & 0x2) ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh;
master_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
master_config.direction = kLPSPI_MsbFirst;
LPSPI_MasterInit(spi_address[obj->instance], &master_config, spi_get_clock());
}
}
void spi_frequency(spi_t *obj, int hz)
{
uint32_t busClock = spi_get_clock();
uint32_t tcrPrescaleValue = 0;
LPSPI_Type *spibase = spi_address[obj->instance];
/* Disable the LPSPI module before setting the baudrate */
LPSPI_Enable(spibase, false);
LPSPI_MasterSetBaudRate(spibase, (uint32_t)hz, busClock, &tcrPrescaleValue);
spibase->TCR = (spibase->TCR & ~LPSPI_TCR_PRESCALE_MASK) | LPSPI_TCR_PRESCALE(tcrPrescaleValue);
/* Enable the LPSPI module */
LPSPI_Enable(spibase, true);
}
static inline int spi_readable(spi_t * obj)
{
return (LPSPI_GetStatusFlags(spi_address[obj->instance]) & kLPSPI_RxDataReadyFlag);
}
int spi_master_write(spi_t *obj, int value)
{
uint32_t rx_data;
LPSPI_WriteData(spi_address[obj->instance], value);
// wait rx buffer full
while (!spi_readable(obj));
rx_data = LPSPI_ReadData(spi_address[obj->instance]);
LPSPI_ClearStatusFlags(spi_address[obj->instance], kLPSPI_TransferCompleteFlag);
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
// Default write is done in each and every call, in future can create HAL API instead
LPSPI_SetDummyData(spi_address[obj->instance], write_fill);
LPSPI_MasterTransferBlocking(spi_address[obj->instance], &(lpspi_transfer_t){
.txData = (uint8_t *)tx_buffer,
.rxData = (uint8_t *)rx_buffer,
.dataSize = total,
.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_SlaveByteSwap,
});
return total;
}
int spi_slave_receive(spi_t *obj)
{
return spi_readable(obj);
}
int spi_slave_read(spi_t *obj)
{
uint32_t rx_data;
while (!spi_readable(obj));
rx_data = LPSPI_ReadData(spi_address[obj->instance]);
return rx_data & 0xffff;
}
void spi_slave_write(spi_t *obj, int value)
{
/*Write the word to TX register*/
LPSPI_WriteData(spi_address[obj->instance], (uint32_t)value);
/* Transfer is not complete until transfer complete flag sets */
while (!(LPSPI_GetStatusFlags(spi_address[obj->instance]) & kLPSPI_FrameCompleteFlag))
{
}
LPSPI_ClearStatusFlags(spi_address[obj->instance], kLPSPI_FrameCompleteFlag);
}
const PinMap *spi_master_mosi_pinmap()
{
return PinMap_SPI_MOSI;
}
const PinMap *spi_master_miso_pinmap()
{
return PinMap_SPI_MISO;
}
const PinMap *spi_master_clk_pinmap()
{
return PinMap_SPI_SCLK;
}
const PinMap *spi_master_cs_pinmap()
{
return PinMap_SPI_SSEL;
}
const PinMap *spi_slave_mosi_pinmap()
{
return PinMap_SPI_MOSI;
}
const PinMap *spi_slave_miso_pinmap()
{
return PinMap_SPI_MISO;
}
const PinMap *spi_slave_clk_pinmap()
{
return PinMap_SPI_SCLK;
}
const PinMap *spi_slave_cs_pinmap()
{
return PinMap_SPI_SSEL;
}
#endif

View File

@@ -0,0 +1,49 @@
/*
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdlib.h>
#include "cmsis.h"
#include "fsl_trng.h"
#include "trng_api.h"
void trng_init(trng_t *obj)
{
(void)obj;
trng_config_t trngConfig;
TRNG_GetDefaultConfig(&trngConfig);
TRNG_Init(TRNG, &trngConfig);
}
void trng_free(trng_t *obj)
{
(void)obj;
TRNG_Deinit(TRNG);
}
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
{
(void)obj;
if(TRNG_GetRandomData(TRNG, output, length) != kStatus_Success) {
return -1;
}
*output_length = length;
return 0;
}

View File

@@ -0,0 +1,148 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include "us_ticker_api.h"
#include "us_ticker_defines.h"
#include "fsl_pit.h"
#include "fsl_clock_config.h"
const ticker_info_t* us_ticker_get_info()
{
static const ticker_info_t info = {
1000000, // 1 MHz
32 // 32 bit counter
};
return &info;
}
static bool us_ticker_inited = false;
extern void us_ticker_setup_clock();
extern uint32_t us_ticker_get_clock();
static void pit_isr(void)
{
PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK);
PIT_ClearStatusFlags(PIT, kPIT_Chnl_2, PIT_TFLG_TIF_MASK);
PIT_StopTimer(PIT, kPIT_Chnl_2);
PIT_StopTimer(PIT, kPIT_Chnl_3);
us_ticker_irq_handler();
}
/** Initialize the high frequency ticker
*
*/
void us_ticker_init(void)
{
/* Common for ticker/timer. */
uint32_t busClock;
us_ticker_setup_clock();
busClock = us_ticker_get_clock();
/* Let the timer to count if re-init. */
if (!us_ticker_inited) {
/* Structure to initialize PIT. */
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
PIT_Init(PIT, &pitConfig);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF);
PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true);
PIT_StartTimer(PIT, kPIT_Chnl_0);
PIT_StartTimer(PIT, kPIT_Chnl_1);
}
/* Configure interrupt generation counters and disable ticker interrupts. */
PIT_StopTimer(PIT, kPIT_Chnl_3);
PIT_StopTimer(PIT, kPIT_Chnl_2);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1);
PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true);
NVIC_SetVector(PIT_IRQn, (uint32_t) pit_isr);
NVIC_EnableIRQ(PIT_IRQn);
PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable);
us_ticker_inited = true;
}
/** Read the current counter
*
* @return The current timer's counter value in ticks
*/
uint32_t (us_ticker_read)()
{
return us_ticker_read();
}
/** Disable us ticker interrupt
*
*/
void us_ticker_disable_interrupt(void)
{
PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable);
}
/** Clear us ticker interrupt
*
*/
void us_ticker_clear_interrupt(void)
{
PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK);
}
/** Set interrupt for specified timestamp
*
* @param timestamp The time in ticks when interrupt should be generated
*/
void us_ticker_set_interrupt(timestamp_t timestamp)
{
/* We get here absolute interrupt time which takes into account counter overflow.
* Since we use additional count-down timer to generate interrupt we need to calculate
* load value based on time-stamp.
*/
const uint32_t now_ticks = us_ticker_read();
uint32_t delta_ticks =
timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks);
if (delta_ticks == 0) {
/* The requested delay is less than the minimum resolution of this counter. */
delta_ticks = 1;
}
PIT_StopTimer(PIT, kPIT_Chnl_3);
PIT_StopTimer(PIT, kPIT_Chnl_2);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks);
PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable);
PIT_StartTimer(PIT, kPIT_Chnl_3);
PIT_StartTimer(PIT, kPIT_Chnl_2);
}
/** Fire us ticker interrupt
*
*/
void us_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(PIT_IRQn);
}
void us_ticker_free(void)
{
}

View File

@@ -0,0 +1,30 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NXP_US_TICKER_DEFINES_H_
#define _NXP_US_TICKER_DEFINES_H_
#include "fsl_pit.h"
#define US_TICKER_PERIOD_NUM 1
#define US_TICKER_PERIOD_DEN 1
#define US_TICKER_MASK 0xFFFFFFFF
/* Macro-optimised form of us_ticker_read */
#define us_ticker_read() (~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)))
#endif /* _NXP_US_TICKER_DEFINES_H_ */

View File

@@ -0,0 +1,90 @@
/* mbed Microcontroller Library
* Copyright (c) 2020 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "watchdog_api.h"
#if DEVICE_WATCHDOG
#include "reset_reason_api.h"
#include "fsl_rtwdog.h"
#include "fsl_clock.h"
#include "platform/mbed_wait_api.h"
// Platform specific watchdog definitions
#define LPO_CLOCK_FREQUENCY 32768
#define MAX_TIMEOUT 0xFFFFUL
#define DELAY_TIME 100000U
// Number of decrements in the timeout register per millisecond
#define TICKS_PER_MS ((LPO_CLOCK_FREQUENCY) / 1000)
// Maximum timeout that can be specified in milliseconds
#define MAX_TIMEOUT_MS ((MAX_TIMEOUT) / (TICKS_PER_MS))
watchdog_status_t hal_watchdog_init(const watchdog_config_t *config)
{
uint32_t temp;
rtwdog_config_t cfg;
/* When system is boot up, WDOG32 is disabled. We must wait for at least 2.5
* periods of wdog32 clock to reconfigure wodg32. So Delay a while to wait for
* the previous configuration taking effect. */
for (temp = 0; temp < DELAY_TIME; temp++) {
__NOP();
}
RTWDOG_GetDefaultConfig(&cfg);
cfg.workMode.enableStop = true;
cfg.workMode.enableDebug = true;
cfg.timeoutValue = (TICKS_PER_MS * config->timeout_ms);
RTWDOG_Init(RTWDOG, &cfg);
return WATCHDOG_STATUS_OK;
}
void hal_watchdog_kick(void)
{
RTWDOG_Refresh(RTWDOG);
}
watchdog_status_t hal_watchdog_stop(void)
{
RTWDOG_Deinit(RTWDOG);
return WATCHDOG_STATUS_OK;
}
uint32_t hal_watchdog_get_reload_value(void)
{
const uint32_t timeout = RTWDOG->TOVAL;
return (timeout / TICKS_PER_MS);
}
watchdog_features_t hal_watchdog_get_platform_features(void)
{
watchdog_features_t features;
features.max_timeout = MAX_TIMEOUT_MS;
features.update_config = true;
features.disable_watchdog = true;
features.clock_typical_frequency = 32000;
features.clock_max_frequency = 32768;
return features;
}
#endif // DEVICE_WATCHDOG