Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
640
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/flash_api.c
Normal file
640
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/flash_api.c
Normal 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
306
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/i2c_api.c
Normal file
306
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/i2c_api.c
Normal 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
|
||||
122
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c
Normal file
122
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c
Normal 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 */
|
||||
@@ -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
|
||||
158
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pinmap.c
Normal file
158
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pinmap.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
46
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c
Normal file
46
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c
Normal 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);
|
||||
}
|
||||
|
||||
208
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c
Normal file
208
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
148
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c
Normal file
148
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user