diff --git a/targets/TARGET_NUVOTON/TARGET_M480/analogin_api.c b/targets/TARGET_NUVOTON/TARGET_M480/analogin_api.c index 3b38c57d53..988193ebdc 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/analogin_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/analogin_api.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "analogin_api.h" #if DEVICE_ANALOGIN @@ -45,38 +45,38 @@ static const struct nu_modinit_s adc_modinit_tab[] = { }; void analogin_init(analogin_t *obj, PinName pin) -{ +{ obj->adc = (ADCName) pinmap_peripheral(pin, PinMap_ADC); MBED_ASSERT(obj->adc != (ADCName) NC); const struct nu_modinit_s *modinit = get_modinit(obj->adc, adc_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->adc); - + EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc); - + // NOTE: All channels (identified by ADCName) share a ADC module. This reset will also affect other channels of the same ADC module. if (! eadc_modinit_mask) { // Reset this module if no channel enabled SYS_ResetModule(modinit->rsetidx); - + // Select clock source of paired channels CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); // Enable clock of paired channels CLK_EnableModuleClock(modinit->clkidx); - + // Set the ADC internal sampling time, input mode as single-end and enable the A/D converter EADC_Open(eadc_base, EADC_CTL_DIFFEN_SINGLE_END); } - + uint32_t chn = NU_MODSUBINDEX(obj->adc); - + // Wire pinout pinmap_pinout(pin, PinMap_ADC); - + // Configure the sample module Nmod for analog input channel Nch and software trigger source EADC_ConfigSampleModule(eadc_base, chn, EADC_SOFTWARE_TRIGGER, chn); - + eadc_modinit_mask |= 1 << chn; } @@ -84,7 +84,7 @@ uint16_t analogin_read_u16(analogin_t *obj) { EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc); uint32_t chn = NU_MODSUBINDEX(obj->adc); - + EADC_START_CONV(eadc_base, 1 << chn); while (EADC_GET_DATA_VALID_FLAG(eadc_base, 1 << chn) != (1 << chn)); uint16_t conv_res_12 = EADC_GET_CONV_DATA(eadc_base, chn); @@ -92,7 +92,7 @@ uint16_t analogin_read_u16(analogin_t *obj) // conv_res_12: 0000 b11b10b9b8 b7b6b5b4 b3b2b1b0 // conv_res_16: b11b10b9b8 b7b6b5b4 b3b2b1b0 b11b10b9b8 uint16_t conv_res_16 = (conv_res_12 << 4) | (conv_res_12 >> 8); - + return conv_res_16; } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index 4d4aebbf44..9e6c9f258d 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -13,38 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - #include "can_api.h" - #include "m480_gpio.h" - #include "m480_can.h" - - #if DEVICE_CAN - #include - #include "cmsis.h" - #include "pinmap.h" - #include "PeripheralPins.h" - #include "nu_modutil.h" - #include "nu_miscutil.h" - #include "nu_bitutil.h" - #include "mbed_critical.h" - - #define NU_CAN_DEBUG 0 - #define CAN_NUM 2 - - static uint32_t can_irq_ids[CAN_NUM] = {0}; - static can_irq_handler can0_irq_handler; - static can_irq_handler can1_irq_handler; + +#include "can_api.h" +#include "m480_gpio.h" +#include "m480_can.h" + +#if DEVICE_CAN +#include +#include "cmsis.h" +#include "pinmap.h" +#include "PeripheralPins.h" +#include "nu_modutil.h" +#include "nu_miscutil.h" +#include "nu_bitutil.h" +#include "mbed_critical.h" + +#define NU_CAN_DEBUG 0 +#define CAN_NUM 2 + +static uint32_t can_irq_ids[CAN_NUM] = {0}; +static can_irq_handler can0_irq_handler; +static can_irq_handler can1_irq_handler; extern uint32_t CAN_GetCANBitRate(CAN_T *tCAN); extern void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask); extern void CAN_LeaveInitMode(CAN_T *tCAN); extern void CAN_LeaveTestMode(CAN_T *tCAN); extern void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask); - - static const struct nu_modinit_s can_modinit_tab[] = { + +static const struct nu_modinit_s can_modinit_tab[] = { {CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL}, {CAN_1, CAN1_MODULE, 0, 0, CAN1_RST, CAN1_IRQn, NULL}, - + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; @@ -54,68 +54,67 @@ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); obj->can = (CANName)pinmap_merge(can_td, can_rd); MBED_ASSERT((int)obj->can != NC); - + const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->can); - + // Reset this module SYS_ResetModule(modinit->rsetidx); - NVIC_DisableIRQ(CAN0_IRQn); - NVIC_DisableIRQ(CAN1_IRQn); - + NVIC_DisableIRQ(CAN0_IRQn); + NVIC_DisableIRQ(CAN1_IRQn); + // Enable IP clock CLK_EnableModuleClock(modinit->clkidx); - + if(obj->can == CAN_1) { obj->index = 1; - } - else + } else obj->index = 0; - + pinmap_pinout(td, PinMap_CAN_TD); pinmap_pinout(rd, PinMap_CAN_RD); -#if 0 +#if 0 /* TBD: For M487 mbed Board Transmitter Setting (RS Pin) */ - GPIO_SetMode(PA, BIT2| BIT3, GPIO_MODE_OUTPUT); + GPIO_SetMode(PA, BIT2| BIT3, GPIO_MODE_OUTPUT); PA2 = 0x00; - PA3 = 0x00; + PA3 = 0x00; #endif CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE); - + can_filter(obj, 0, 0, CANStandard, 0); - } - +} + void can_init(can_t *obj, PinName rd, PinName td) { can_init_freq(obj, rd, td, 500000); } - + void can_free(can_t *obj) { const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab); - + MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->can); - + // Reset this module SYS_ResetModule(modinit->rsetidx); - + CLK_DisableModuleClock(modinit->clkidx); } int can_frequency(can_t *obj, int hz) { CAN_SetBaudRate((CAN_T *)NU_MODBASE(obj->can), hz); - + return CAN_GetCANBitRate((CAN_T *)NU_MODBASE(obj->can)); } -static void can_irq(CANName name, int id) +static void can_irq(CANName name, int id) { - + CAN_T *can = (CAN_T *)NU_MODBASE(name); uint32_t u8IIDRstatus; @@ -128,7 +127,7 @@ static void can_irq(CANName name, int id) if(can->STATUS & CAN_STATUS_RXOK_Msk) { can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_RX); + can1_irq_handler(can_irq_ids[id], IRQ_RX); else can0_irq_handler(can_irq_ids[id], IRQ_RX); } @@ -136,7 +135,7 @@ static void can_irq(CANName name, int id) if(can->STATUS & CAN_STATUS_TXOK_Msk) { can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_TX); + can1_irq_handler(can_irq_ids[id], IRQ_TX); else can0_irq_handler(can_irq_ids[id], IRQ_TX); @@ -147,31 +146,31 @@ static void can_irq(CANName name, int id) /**************************/ if(can->STATUS & CAN_STATUS_EWARN_Msk) { if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_ERROR); + can1_irq_handler(can_irq_ids[id], IRQ_ERROR); else can0_irq_handler(can_irq_ids[id], IRQ_ERROR); } if(can->STATUS & CAN_STATUS_BOFF_Msk) { if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_BUS); + can1_irq_handler(can_irq_ids[id], IRQ_BUS); else can0_irq_handler(can_irq_ids[id], IRQ_BUS); } } else if (u8IIDRstatus!=0) { if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_OVERRUN); + can1_irq_handler(can_irq_ids[id], IRQ_OVERRUN); else can0_irq_handler(can_irq_ids[id], IRQ_OVERRUN); - + CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */ } else if(can->WU_STATUS == 1) { can->WU_STATUS = 0; /* Write '0' to clear */ if(id) - can1_irq_handler(can_irq_ids[id] , IRQ_WAKEUP); + can1_irq_handler(can_irq_ids[id], IRQ_WAKEUP); else can0_irq_handler(can_irq_ids[id], IRQ_WAKEUP); } @@ -193,70 +192,66 @@ void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) can1_irq_handler = handler; else can0_irq_handler = handler; - can_irq_ids[obj->index] = id; + can_irq_ids[obj->index] = id; } void can_irq_free(can_t *obj) { CAN_DisableInt((CAN_T *)NU_MODBASE(obj->can), (CAN_CON_IE_Msk|CAN_CON_SIE_Msk|CAN_CON_EIE_Msk)); - + can_irq_ids[obj->index] = 0; - + if(!obj->index) NVIC_DisableIRQ(CAN0_IRQn); else NVIC_DisableIRQ(CAN1_IRQn); - - + + } void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) { uint8_t u8Mask; - + u8Mask = ((enable != 0 )? CAN_CON_IE_Msk :0); - - switch (irq) - { - case IRQ_ERROR: - case IRQ_BUS: - case IRQ_PASSIVE: - u8Mask = u8Mask | CAN_CON_EIE_Msk | CAN_CON_SIE_Msk; - break; - - case IRQ_RX: - case IRQ_TX: - case IRQ_OVERRUN: - case IRQ_WAKEUP: - u8Mask = u8Mask | CAN_CON_SIE_Msk; - break; - - default: - break; - + + switch (irq) { + case IRQ_ERROR: + case IRQ_BUS: + case IRQ_PASSIVE: + u8Mask = u8Mask | CAN_CON_EIE_Msk | CAN_CON_SIE_Msk; + break; + + case IRQ_RX: + case IRQ_TX: + case IRQ_OVERRUN: + case IRQ_WAKEUP: + u8Mask = u8Mask | CAN_CON_SIE_Msk; + break; + + default: + break; + } CAN_EnterInitMode((CAN_T*)NU_MODBASE(obj->can), u8Mask); - + CAN_LeaveInitMode((CAN_T*)NU_MODBASE(obj->can)); - - if(!obj->index) - { + + if(!obj->index) { NVIC_SetVector(CAN0_IRQn, (uint32_t)&CAN0_IRQHandler); NVIC_EnableIRQ(CAN0_IRQn); - } - else - { + } else { NVIC_SetVector(CAN1_IRQn, (uint32_t)&CAN1_IRQHandler); NVIC_EnableIRQ(CAN1_IRQn); } - + } int can_write(can_t *obj, CAN_Message msg, int cc) { STR_CANMSG_T CMsg; - + CMsg.IdType = (uint32_t)msg.format; CMsg.FrameType = (uint32_t)!msg.type; CMsg.Id = msg.id; @@ -271,79 +266,78 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) STR_CANMSG_T CMsg; if(!CAN_Receive((CAN_T *)(NU_MODBASE(obj->can)), handle, &CMsg)) - return 0; - + return 0; + msg->format = (CANFormat)CMsg.IdType; msg->type = (CANType)!CMsg.FrameType; msg->id = CMsg.Id; msg->len = CMsg.DLC; memcpy(&msg->data[0], &CMsg.Data[0], 8); - + return 1; } int can_mode(can_t *obj, CanMode mode) { int success = 0; - switch (mode) - { - case MODE_RESET: - CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can)); - success = 1; - break; - - case MODE_NORMAL: - CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_BASIC_Msk); - success = 1; - break; - - case MODE_SILENT: - CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk); - success = 1; - break; - - case MODE_TEST_LOCAL: - case MODE_TEST_GLOBAL: - CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_LBACK_Msk); - success = 1; - break; - - case MODE_TEST_SILENT: - CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); - success = 1; - break; - - default: - success = 0; - break; - + switch (mode) { + case MODE_RESET: + CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can)); + success = 1; + break; + + case MODE_NORMAL: + CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_BASIC_Msk); + success = 1; + break; + + case MODE_SILENT: + CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk); + success = 1; + break; + + case MODE_TEST_LOCAL: + case MODE_TEST_GLOBAL: + CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_LBACK_Msk); + success = 1; + break; + + case MODE_TEST_SILENT: + CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + success = 1; + break; + + default: + success = 0; + break; + } - - + + return success; } int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) { - return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle , (uint32_t)format, id); + return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id); } void can_reset(can_t *obj) { const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab); - + MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->can); - + // Reset this module SYS_ResetModule(modinit->rsetidx); - + } unsigned char can_rderror(can_t *obj) { - CAN_T *can = (CAN_T *)NU_MODBASE(obj->can); + CAN_T *can = (CAN_T *)NU_MODBASE(obj->can); return ((can->ERR>>8)&0xFF); } @@ -357,5 +351,5 @@ void can_monitor(can_t *obj, int silent) { CAN_EnterTestMode((CAN_T *)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk); } - + #endif // DEVICE_CAN diff --git a/targets/TARGET_NUVOTON/TARGET_M480/dma_api.c b/targets/TARGET_NUVOTON/TARGET_M480/dma_api.c index bd478b9cbb..2e8a65ecba 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/dma_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/dma_api.c @@ -46,19 +46,19 @@ void dma_init(void) if (dma_inited) { return; } - + dma_inited = 1; dma_chn_mask = ~NU_PDMA_CH_Msk; memset(dma_chn_arr, 0x00, sizeof (dma_chn_arr)); - + // Reset this module SYS_ResetModule(dma_modinit.rsetidx); - + // Enable IP clock CLK_EnableModuleClock(dma_modinit.clkidx); - + PDMA_Open(0); - + NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var); NVIC_EnableIRQ(dma_modinit.irq_n); } @@ -68,12 +68,12 @@ int dma_channel_allocate(uint32_t capabilities) if (! dma_inited) { dma_init(); } - + int i = nu_cto(dma_chn_mask); if (i != 32) { - dma_chn_mask |= 1 << i; - memset(dma_chn_arr + i - NU_PDMA_CH_Pos, 0x00, sizeof (struct nu_dma_chn_s)); - return i; + dma_chn_mask |= 1 << i; + memset(dma_chn_arr + i - NU_PDMA_CH_Pos, 0x00, sizeof (struct nu_dma_chn_s)); + return i; } // No channel available @@ -85,18 +85,18 @@ int dma_channel_free(int channelid) if (channelid != DMA_ERROR_OUT_OF_CHANNELS) { dma_chn_mask &= ~(1 << channelid); } - + return 0; } void dma_set_handler(int channelid, uint32_t handler, uint32_t id, uint32_t event) { MBED_ASSERT(dma_chn_mask & (1 << channelid)); - + dma_chn_arr[channelid - NU_PDMA_CH_Pos].handler = (void (*)(uint32_t, uint32_t)) handler; dma_chn_arr[channelid - NU_PDMA_CH_Pos].id = id; dma_chn_arr[channelid - NU_PDMA_CH_Pos].event = event; - + // Set interrupt vector if someone has removed it. NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var); NVIC_EnableIRQ(dma_modinit.irq_n); @@ -110,13 +110,13 @@ PDMA_T *dma_modbase(void) static void pdma_vec(void) { uint32_t intsts = PDMA_GET_INT_STATUS(); - + // Abort if (intsts & PDMA_INTSTS_ABTIF_Msk) { uint32_t abtsts = PDMA_GET_ABORT_STS(); // Clear all Abort flags PDMA_CLR_ABORT_FLAG(abtsts); - + while (abtsts) { int chn_id = nu_ctz(abtsts) - PDMA_ABTSTS_ABTIF0_Pos + NU_PDMA_CH_Pos; if (dma_chn_mask & (1 << chn_id)) { @@ -128,13 +128,13 @@ static void pdma_vec(void) abtsts &= ~(1 << (chn_id - NU_PDMA_CH_Pos + PDMA_ABTSTS_ABTIF0_Pos)); } } - + // Transfer done if (intsts & PDMA_INTSTS_TDIF_Msk) { - uint32_t tdsts = PDMA_GET_TD_STS(); + uint32_t tdsts = PDMA_GET_TD_STS(); // Clear all transfer done flags PDMA_CLR_TD_FLAG(tdsts); - + while (tdsts) { int chn_id = nu_ctz(tdsts) - PDMA_TDSTS_TDIF0_Pos + NU_PDMA_CH_Pos; if (dma_chn_mask & (1 << chn_id)) { @@ -146,13 +146,13 @@ static void pdma_vec(void) tdsts &= ~(1 << (chn_id - NU_PDMA_CH_Pos + PDMA_TDSTS_TDIF0_Pos)); } } - + // Timeout uint32_t reqto = intsts & (PDMA_INTSTS_REQTOF0_Msk | PDMA_INTSTS_REQTOF1_Msk); if (reqto) { // Clear all Timeout flags PDMA->INTSTS = reqto; - + while (reqto) { int chn_id = nu_ctz(reqto) - PDMA_INTSTS_REQTOF0_Pos + NU_PDMA_CH_Pos; if (dma_chn_mask & (1 << chn_id)) { diff --git a/targets/TARGET_NUVOTON/TARGET_M480/flash_api.c b/targets/TARGET_NUVOTON/TARGET_M480/flash_api.c index 941576327c..a5913d4a52 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/flash_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/flash_api.c @@ -21,38 +21,38 @@ // This is a flash algo binary blob. It is PIC (position independent code) that should be stored in RAM // NOTE: On ARMv7-M/ARMv8-M, instruction fetches are always little-endian. static uint32_t FLASH_ALGO[] = { - 0x4603b530, 0x2164460c, 0x4df72059, 0x20166028, 0xf8c5070d, 0x20880100, 0x0100f8c5, 0xf8d006c0, -0xf0000100, 0xb9080001, 0xbd302001, 0x680048ef, 0x0004f040, 0x4580f04f, 0x0200f8c5, 0xf8d04628, -0xf0400204, 0xf8c50004, 0xbf000204, 0xf1a11e08, 0xd1fb0101, 0x680048e6, 0x0029f040, 0x60284de4, -0x68004628, 0x0001f000, 0x2001b908, 0x48e0e7dd, 0xf0406800, 0x4dde0040, 0x20006028, 0x4601e7d5, -0x48dbbf00, 0xf0006900, 0x28000001, 0x48d8d1f9, 0xf0206800, 0x4ad60029, 0x20006010, 0x60104ad2, -0x46014770, 0x48d2bf00, 0xf0006900, 0x28000001, 0x48cfd1f9, 0xf0406800, 0x4acd0040, 0x20226010, -0xf02160d0, 0x60500003, 0x1f00f5b1, 0x48c9d101, 0x20016090, 0x61104ac6, 0x8f60f3bf, 0x48c4bf00, -0xf0006900, 0x28000001, 0x48c1d1f9, 0xf0006800, 0xb1380040, 0x680048be, 0x0040f040, 0x60104abc, -0x47702001, 0xe7fc2000, 0x4603b570, 0x2500460c, 0x4629e009, 0xf8531c6d, 0xf7ff0021, 0x1e06ffc2, -0x4630d001, 0x42a5bd70, 0x2000d3f3, 0xb570e7fa, 0x460b4604, 0x22004615, 0xf1034629, 0xf020000f, -0xbf00030f, 0x690048aa, 0x0001f000, 0xd1f92800, 0x680048a7, 0x0040f040, 0x60304ea5, 0x000ff024, -0x20276070, 0x461060f0, 0xf8511c52, 0x4ea00020, 0x60303680, 0x1c524610, 0x0020f851, 0xf8c64e9c, -0x46100084, 0xf8511c52, 0x4e990020, 0x60303688, 0x1c524610, 0x0020f851, 0x60301d36, 0x4e942001, -0x3b106130, 0xbf00e02c, 0x30c04891, 0xf0006800, 0x28000030, 0x4610d1f8, 0xf8511c52, 0x4e8c0020, -0x60303680, 0x1c524610, 0x0020f851, 0xf8c64e88, 0xbf000084, 0x30c04886, 0xf0006800, 0x280000c0, -0x4610d1f8, 0xf8511c52, 0x4e810020, 0x60303688, 0x1c524610, 0x0020f851, 0xf8c64e7d, 0x3b10008c, -0xd1d02b00, 0x487abf00, 0xf0006900, 0x28000001, 0xbd70d1f9, 0x4603b510, 0xf0201cc8, 0xbf000103, -0x69004873, 0x0001f000, 0xd1f92800, 0x68004870, 0x0040f040, 0x60204c6e, 0x60e02021, 0xf023e020, -0x4c6b0003, 0x68106060, 0x200160a0, 0xf3bf6120, 0xbf008f60, 0x69004866, 0x0001f000, 0xd1f92800, -0x68004863, 0x0040f000, 0x4861b138, 0xf0406800, 0x4c5f0040, 0x20016020, 0x1d1bbd10, 0x1f091d12, -0xd1dc2900, 0xe7f72000, 0x47f0e92d, 0x460c4605, 0xf04f4616, 0x46c20800, 0x4855bf00, 0xf0006900, -0x28000001, 0x4852d1f9, 0xf0406800, 0x49500040, 0x1ce06008, 0x0403f020, 0xf3c5e02f, 0xb9600008, -0x7f00f5b4, 0xf44fd309, 0xeb067700, 0x46390208, 0xf7ff4628, 0x4682ff2c, 0xf3c5e016, 0xb9580008, -0xd3092c10, 0x070ff024, 0x0208eb06, 0x46284639, 0xff1df7ff, 0xe0074682, 0xeb064627, 0x46390208, -0xf7ff4628, 0x4682ff87, 0x44b8443d, 0xf1ba1be4, 0xd0020f00, 0xe8bd2001, 0x2c0087f0, 0x2000d1cd, -0xb510e7f9, 0xf0231ccb, 0xbf000103, 0x691b4b30, 0x0301f003, 0xd1f92b00, 0x681b4b2d, 0x0340f043, -0x60234c2b, 0x60e32300, 0xf020e025, 0x4c280303, 0x23006063, 0x230160a3, 0xf3bf6123, 0xbf008f60, -0x691b4b23, 0x0301f003, 0xd1f92b00, 0x681b4b20, 0x0340f003, 0x4b1eb133, 0xf043681b, 0x4c1c0340, -0xbd106023, 0x689b4b1a, 0x42a36814, 0xe7f8d000, 0x1d121d00, 0x29001f09, 0xbf00d1d7, 0xb510e7f1, -0x48134603, 0xf0006e00, 0xb1680002, 0x65034810, 0x65826541, 0x4c0e2001, 0xbf0065e0, 0x6e00480c, -0x0001f000, 0xd1f92800, 0x6e004809, 0x0004f000, 0x2002b908, 0x4806bd10, 0xf0006e00, 0xb1080002, -0xe7f72001, 0xe7f52000, 0x40000100, 0x40000200, 0x4000c000, 0x0055aa03, 0x00000000, + 0x4603b530, 0x2164460c, 0x4df72059, 0x20166028, 0xf8c5070d, 0x20880100, 0x0100f8c5, 0xf8d006c0, + 0xf0000100, 0xb9080001, 0xbd302001, 0x680048ef, 0x0004f040, 0x4580f04f, 0x0200f8c5, 0xf8d04628, + 0xf0400204, 0xf8c50004, 0xbf000204, 0xf1a11e08, 0xd1fb0101, 0x680048e6, 0x0029f040, 0x60284de4, + 0x68004628, 0x0001f000, 0x2001b908, 0x48e0e7dd, 0xf0406800, 0x4dde0040, 0x20006028, 0x4601e7d5, + 0x48dbbf00, 0xf0006900, 0x28000001, 0x48d8d1f9, 0xf0206800, 0x4ad60029, 0x20006010, 0x60104ad2, + 0x46014770, 0x48d2bf00, 0xf0006900, 0x28000001, 0x48cfd1f9, 0xf0406800, 0x4acd0040, 0x20226010, + 0xf02160d0, 0x60500003, 0x1f00f5b1, 0x48c9d101, 0x20016090, 0x61104ac6, 0x8f60f3bf, 0x48c4bf00, + 0xf0006900, 0x28000001, 0x48c1d1f9, 0xf0006800, 0xb1380040, 0x680048be, 0x0040f040, 0x60104abc, + 0x47702001, 0xe7fc2000, 0x4603b570, 0x2500460c, 0x4629e009, 0xf8531c6d, 0xf7ff0021, 0x1e06ffc2, + 0x4630d001, 0x42a5bd70, 0x2000d3f3, 0xb570e7fa, 0x460b4604, 0x22004615, 0xf1034629, 0xf020000f, + 0xbf00030f, 0x690048aa, 0x0001f000, 0xd1f92800, 0x680048a7, 0x0040f040, 0x60304ea5, 0x000ff024, + 0x20276070, 0x461060f0, 0xf8511c52, 0x4ea00020, 0x60303680, 0x1c524610, 0x0020f851, 0xf8c64e9c, + 0x46100084, 0xf8511c52, 0x4e990020, 0x60303688, 0x1c524610, 0x0020f851, 0x60301d36, 0x4e942001, + 0x3b106130, 0xbf00e02c, 0x30c04891, 0xf0006800, 0x28000030, 0x4610d1f8, 0xf8511c52, 0x4e8c0020, + 0x60303680, 0x1c524610, 0x0020f851, 0xf8c64e88, 0xbf000084, 0x30c04886, 0xf0006800, 0x280000c0, + 0x4610d1f8, 0xf8511c52, 0x4e810020, 0x60303688, 0x1c524610, 0x0020f851, 0xf8c64e7d, 0x3b10008c, + 0xd1d02b00, 0x487abf00, 0xf0006900, 0x28000001, 0xbd70d1f9, 0x4603b510, 0xf0201cc8, 0xbf000103, + 0x69004873, 0x0001f000, 0xd1f92800, 0x68004870, 0x0040f040, 0x60204c6e, 0x60e02021, 0xf023e020, + 0x4c6b0003, 0x68106060, 0x200160a0, 0xf3bf6120, 0xbf008f60, 0x69004866, 0x0001f000, 0xd1f92800, + 0x68004863, 0x0040f000, 0x4861b138, 0xf0406800, 0x4c5f0040, 0x20016020, 0x1d1bbd10, 0x1f091d12, + 0xd1dc2900, 0xe7f72000, 0x47f0e92d, 0x460c4605, 0xf04f4616, 0x46c20800, 0x4855bf00, 0xf0006900, + 0x28000001, 0x4852d1f9, 0xf0406800, 0x49500040, 0x1ce06008, 0x0403f020, 0xf3c5e02f, 0xb9600008, + 0x7f00f5b4, 0xf44fd309, 0xeb067700, 0x46390208, 0xf7ff4628, 0x4682ff2c, 0xf3c5e016, 0xb9580008, + 0xd3092c10, 0x070ff024, 0x0208eb06, 0x46284639, 0xff1df7ff, 0xe0074682, 0xeb064627, 0x46390208, + 0xf7ff4628, 0x4682ff87, 0x44b8443d, 0xf1ba1be4, 0xd0020f00, 0xe8bd2001, 0x2c0087f0, 0x2000d1cd, + 0xb510e7f9, 0xf0231ccb, 0xbf000103, 0x691b4b30, 0x0301f003, 0xd1f92b00, 0x681b4b2d, 0x0340f043, + 0x60234c2b, 0x60e32300, 0xf020e025, 0x4c280303, 0x23006063, 0x230160a3, 0xf3bf6123, 0xbf008f60, + 0x691b4b23, 0x0301f003, 0xd1f92b00, 0x681b4b20, 0x0340f003, 0x4b1eb133, 0xf043681b, 0x4c1c0340, + 0xbd106023, 0x689b4b1a, 0x42a36814, 0xe7f8d000, 0x1d121d00, 0x29001f09, 0xbf00d1d7, 0xb510e7f1, + 0x48134603, 0xf0006e00, 0xb1680002, 0x65034810, 0x65826541, 0x4c0e2001, 0xbf0065e0, 0x6e00480c, + 0x0001f000, 0xd1f92800, 0x6e004809, 0x0004f000, 0x2002b908, 0x4806bd10, 0xf0006e00, 0xb1080002, + 0xe7f72001, 0xe7f52000, 0x40000100, 0x40000200, 0x4000c000, 0x0055aa03, 0x00000000, }; static const flash_algo_t flash_algo_config = { diff --git a/targets/TARGET_NUVOTON/TARGET_M480/gpio_api.c b/targets/TARGET_NUVOTON/TARGET_M480/gpio_api.c index 39f4e8e30b..1dac0de6af 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/gpio_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/gpio_api.c @@ -25,9 +25,9 @@ uint32_t gpio_set(PinName pin) if (pin == (PinName) NC) { return 0; } - + uint32_t pin_index = NU_PINNAME_TO_PIN(pin); - + #if 1 pin_function(pin, 0 << NU_MFP_POS(pin_index)); #else @@ -40,7 +40,7 @@ uint32_t gpio_set(PinName pin) void gpio_init(gpio_t *obj, PinName pin) { obj->pin = pin; - + if (obj->pin == (PinName) NC) { return; } @@ -53,7 +53,7 @@ void gpio_mode(gpio_t *obj, PinMode mode) if (obj->pin == (PinName) NC) { return; } - + pin_mode(obj->pin, mode); } @@ -62,25 +62,25 @@ void gpio_dir(gpio_t *obj, PinDirection direction) if (obj->pin == (PinName) NC) { return; } - + uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + uint32_t mode_intern = GPIO_MODE_INPUT; - + switch (direction) { - case PIN_INPUT: - mode_intern = GPIO_MODE_INPUT; - break; - - case PIN_OUTPUT: - mode_intern = GPIO_MODE_OUTPUT; - break; - - default: - return; + case PIN_INPUT: + mode_intern = GPIO_MODE_INPUT; + break; + + case PIN_OUTPUT: + mode_intern = GPIO_MODE_OUTPUT; + break; + + default: + return; } - + GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/gpio_irq_api.c b/targets/TARGET_NUVOTON/TARGET_M480/gpio_irq_api.c index 519d63da9a..48bc6f2bee 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/gpio_irq_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/gpio_irq_api.c @@ -81,13 +81,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 if (pin == NC) { return -1; } - + uint32_t pin_index = NU_PINNAME_TO_PIN(pin); uint32_t port_index = NU_PINNAME_TO_PORT(pin); if (pin_index >= NU_MAX_PIN_PER_PORT || port_index >= NU_MAX_PORT) { return -1; } - + obj->pin = pin; obj->irq_handler = (uint32_t) handler; obj->irq_id = id; @@ -95,7 +95,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 GPIO_T *gpio_base = NU_PORT_BASE(port_index); // NOTE: In InterruptIn constructor, gpio_irq_init() is called with gpio_init_in() which is responsible for multi-function pin setting. // There is no need to call gpio_set() redundantly. - + { #if MBED_CONF_M480_GPIO_IRQ_DEBOUNCE_ENABLE // Suppress compiler warning @@ -106,18 +106,18 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index); #else // Enable de-bounce if the pin is in the de-bounce enable list - + // De-bounce defaults to disabled. GPIO_DISABLE_DEBOUNCE(gpio_base, 1 << pin_index); - + PinName *debounce_pos = gpio_irq_debounce_arr; PinName *debounce_end = gpio_irq_debounce_arr + sizeof (gpio_irq_debounce_arr) / sizeof (gpio_irq_debounce_arr[0]); for (; debounce_pos != debounce_end && *debounce_pos != NC; debounce_pos ++) { uint32_t pin_index_debunce = NU_PINNAME_TO_PIN(*debounce_pos); uint32_t port_index_debounce = NU_PINNAME_TO_PORT(*debounce_pos); - + if (pin_index == pin_index_debunce && - port_index == port_index_debounce) { + port_index == port_index_debounce) { // Configure de-bounce clock source and sampling cycle time GPIO_SET_DEBOUNCE_TIME(MBED_CONF_M480_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_M480_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE); GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index); @@ -126,14 +126,14 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 } #endif } - + struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + var->obj_arr[pin_index] = obj; - + // NOTE: InterruptIn requires IRQ enabled by default. gpio_irq_enable(obj); - + return 0; } @@ -142,10 +142,10 @@ void gpio_irq_free(gpio_irq_t *obj) uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_DisableIRQ(var->irq_n); NU_PORT_BASE(port_index)->INTEN = 0; - + MBED_ASSERT(pin_index < NU_MAX_PIN_PER_PORT); var->obj_arr[pin_index] = NULL; } @@ -155,29 +155,27 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + switch (event) { - case IRQ_RISE: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING); - } - else { - gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index); - } - break; - - case IRQ_FALL: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING); - } - else { - gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index); - } - break; - - case IRQ_NONE: - default: - break; + case IRQ_RISE: + if (enable) { + GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING); + } else { + gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index); + } + break; + + case IRQ_FALL: + if (enable) { + GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING); + } else { + gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index); + } + break; + + case IRQ_NONE: + default: + break; } } @@ -185,7 +183,7 @@ void gpio_irq_enable(gpio_irq_t *obj) { uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_SetVector(var->irq_n, (uint32_t) var->vec); NVIC_EnableIRQ(var->irq_n); } @@ -194,7 +192,7 @@ void gpio_irq_disable(gpio_irq_t *obj) { uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_DisableIRQ(var->irq_n); } @@ -237,7 +235,7 @@ static void gpio_irq(struct nu_gpio_irq_var *var) // Instead, we add port_index into gpio_irq_var_arr table. uint32_t port_index = var->port_index; GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + uint32_t intsrc = gpio_base->INTSRC; uint32_t inten = gpio_base->INTEN; while (intsrc) { @@ -250,15 +248,15 @@ static void gpio_irq(struct nu_gpio_irq_var *var) } } } - - if (inten & (GPIO_INT_FALLING << pin_index)) { + + if (inten & (GPIO_INT_FALLING << pin_index)) { if (! GPIO_PIN_DATA(port_index, pin_index)) { if (obj->irq_handler) { ((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_FALL); } } } - + intsrc &= ~(1 << pin_index); } // Clear all interrupt flags diff --git a/targets/TARGET_NUVOTON/TARGET_M480/gpio_object.h b/targets/TARGET_NUVOTON/TARGET_M480/gpio_object.h index 282bae437b..d4564d3795 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/gpio_object.h +++ b/targets/TARGET_NUVOTON/TARGET_M480/gpio_object.h @@ -34,10 +34,10 @@ typedef struct { static inline void gpio_write(gpio_t *obj, int value) { - MBED_ASSERT(obj->pin != (PinName)NC); + MBED_ASSERT(obj->pin != (PinName)NC); uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); - + GPIO_PIN_DATA(port_index, pin_index) = value ? 1 : 0; } @@ -46,7 +46,7 @@ static inline int gpio_read(gpio_t *obj) MBED_ASSERT(obj->pin != (PinName)NC); uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); - + return (GPIO_PIN_DATA(port_index, pin_index) ? 1 : 0); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/i2c_api.c b/targets/TARGET_NUVOTON/TARGET_M480/i2c_api.c index 900a767f86..20c13a92a2 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/i2c_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/i2c_api.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "i2c_api.h" #if DEVICE_I2C @@ -70,7 +70,7 @@ static const struct nu_modinit_s i2c_modinit_tab[] = { {I2C_0, I2C0_MODULE, 0, 0, I2C0_RST, I2C0_IRQn, &i2c0_var}, {I2C_1, I2C1_MODULE, 0, 0, I2C1_RST, I2C1_IRQn, &i2c1_var}, {I2C_2, I2C2_MODULE, 0, 0, I2C2_RST, I2C2_IRQn, &i2c2_var}, - + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; @@ -110,20 +110,20 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL); obj->i2c.i2c = (I2CName) pinmap_merge(i2c_sda, i2c_scl); MBED_ASSERT((int)obj->i2c.i2c != NC); - + const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->i2c.i2c); - + // Reset this module SYS_ResetModule(modinit->rsetidx); - + // Enable IP clock CLK_EnableModuleClock(modinit->clkidx); pinmap_pinout(sda, PinMap_I2C_SDA); pinmap_pinout(scl, PinMap_I2C_SCL); - + #if DEVICE_I2C_ASYNCH obj->i2c.dma_usage = DMA_USAGE_NEVER; obj->i2c.event = 0; @@ -133,7 +133,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) // NOTE: Setting I2C bus clock to 100 KHz is required. See I2C::I2C in common/I2C.cpp. I2C_Open((I2C_T *) NU_MODBASE(obj->i2c.i2c), 100000); - // NOTE: INTEN bit and FSM control bits (STA, STO, SI, AA) are packed in one register CTL0. We cannot control interrupt through + // NOTE: INTEN bit and FSM control bits (STA, STO, SI, AA) are packed in one register CTL0. We cannot control interrupt through // INTEN bit without impacting FSM control bits. Use NVIC_EnableIRQ/NVIC_DisableIRQ instead for interrupt control. I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); i2c_base->CTL0 |= (I2C_CTL0_INTEN_Msk | I2C_CTL0_I2CEN_Msk); @@ -144,7 +144,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) obj->i2c.tran_ctrl = 0; obj->i2c.stop = 0; i2c_enable_vector_interrupt(obj, (uint32_t) var->vec, 1); - + // Mark this module to be inited. int i = modinit - i2c_modinit_tab; i2c_modinit_mask |= 1 << i; @@ -226,12 +226,11 @@ int i2c_byte_write(i2c_t *obj, int data) { char data_[1]; data_[0] = data & 0xFF; - + if (i2c_do_tran(obj, data_, 1, 0, 0) == 1 && - ! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) { + ! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) { return 1; - } - else { + } else { return 0; } } @@ -247,25 +246,25 @@ int i2c_byte_write(i2c_t *obj, int data) void i2c_slave_mode(i2c_t *obj, int enable_slave) { I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); - + i2c_disable_int(obj); obj->i2c.slaveaddr_state = NoData; - + // Switch to not addressed mode I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - + i2c_enable_int(obj); } int i2c_slave_receive(i2c_t *obj) { int slaveaddr_state; - + i2c_disable_int(obj); slaveaddr_state = obj->i2c.slaveaddr_state; i2c_enable_int(obj); - + return slaveaddr_state; } @@ -282,13 +281,13 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); - + i2c_disable_int(obj); - + // NOTE: On NUC472/M451, non-zero slave address can still work as GC mode is enabled. // On M480, non-zero slave address won't work as GC mode is enabled. I2C_SetSlaveAddr(i2c_base, 0, i2c_addr2bspaddr(address), I2C_GCMODE_DISABLE); - + i2c_enable_int(obj); } @@ -302,46 +301,45 @@ static int i2c_addr2bspaddr(int address) static void i2c_enable_int(i2c_t *obj) { const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); - + core_util_critical_section_enter(); - + // Enable I2C interrupt NVIC_EnableIRQ(modinit->irq_n); obj->i2c.inten = 1; - + core_util_critical_section_exit(); } static void i2c_disable_int(i2c_t *obj) { const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); - + core_util_critical_section_enter(); - + // Disable I2C interrupt NVIC_DisableIRQ(modinit->irq_n); obj->i2c.inten = 0; - + core_util_critical_section_exit(); } static int i2c_set_int(i2c_t *obj, int inten) { int inten_back; - + core_util_critical_section_enter(); - + inten_back = obj->i2c.inten; - + core_util_critical_section_exit(); - + if (inten) { i2c_enable_int(obj); - } - else { + } else { i2c_disable_int(obj); } - + return inten_back; } @@ -360,7 +358,7 @@ int i2c_allow_powerdown(void) } modinit_mask &= ~(1 << i2c_idx); } - + return 1; } @@ -369,23 +367,22 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd if (! buf || ! length) { return 0; } - + int tran_len = 0; - + i2c_disable_int(obj); obj->i2c.tran_ctrl = naklastdata ? (TRANCTRL_STARTED | TRANCTRL_NAKLASTDATA) : TRANCTRL_STARTED; obj->i2c.tran_beg = buf; obj->i2c.tran_pos = buf; obj->i2c.tran_end = buf + length; i2c_enable_int(obj); - + if (i2c_poll_tran_heatbeat_timeout(obj, NU_I2C_TIMEOUT_STAT_INT)) { #if NU_I2C_DEBUG MY_I2C_2 = obj->i2c; while (1); #endif - } - else { + } else { i2c_disable_int(obj); tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg; obj->i2c.tran_beg = NULL; @@ -393,7 +390,7 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastd obj->i2c.tran_end = NULL; i2c_enable_int(obj); } - + return tran_len; } @@ -401,7 +398,7 @@ static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync) { I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); int err = 0; - + i2c_disable_int(obj); if (i2c_poll_status_timeout(obj, i2c_is_trsn_done, NU_I2C_TIMEOUT_STAT_INT)) { @@ -410,30 +407,27 @@ static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync) MY_I2C_2 = obj->i2c; while (1); #endif - } - else { + } else { #if 1 // NOTE: Avoid duplicate Start/Stop. Otherwise, we may meet strange error. uint32_t status = I2C_GET_STATUS(i2c_base); - + switch (status) { case 0x08: // Start case 0x10: // Master Repeat Start if (i2c_ctl & I2C_CTL0_STA_Msk) { return 0; - } - else { + } else { break; } case 0xF8: // Bus Released if ((i2c_ctl & (I2C_CTL0_STA_Msk | I2C_CTL0_STO_Msk)) == I2C_CTL0_STO_Msk) { return 0; - } - else { + } else { break; } } -#endif +#endif I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); if (sync && i2c_poll_status_timeout(obj, i2c_is_trsn_done, NU_I2C_TIMEOUT_STAT_INT)) { err = I2C_ERROR_BUS_BUSY; @@ -445,7 +439,7 @@ static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync) } i2c_enable_int(obj); - + return err; } @@ -453,14 +447,14 @@ static int i2c_poll_status_timeout(i2c_t *obj, int (*is_status)(i2c_t *obj), uin { uint32_t t1, t2, elapsed = 0; int status_assert = 0; - + t1 = us_ticker_read(); while (1) { status_assert = is_status(obj); if (status_assert) { break; } - + t2 = us_ticker_read(); elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t) t2 + 0xFFFFFFFF - t1 + 1); if (elapsed >= timeout) { @@ -475,7 +469,7 @@ static int i2c_poll_status_timeout(i2c_t *obj, int (*is_status)(i2c_t *obj), uin break; } } - + return (elapsed >= timeout); } @@ -485,7 +479,7 @@ static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout) int tran_started; char *tran_pos = NULL; char *tran_pos2 = NULL; - + i2c_disable_int(obj); tran_pos = obj->i2c.tran_pos; i2c_enable_int(obj); @@ -497,7 +491,7 @@ static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout) if (! tran_started) { // Transfer completed or stopped break; } - + i2c_disable_int(obj); tran_pos2 = obj->i2c.tran_pos; i2c_enable_int(obj); @@ -507,7 +501,7 @@ static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout) tran_pos = tran_pos2; continue; } - + elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t) t2 + 0xFFFFFFFF - t1 + 1); if (elapsed >= timeout) { // Transfer idle #if NU_I2C_DEBUG @@ -522,7 +516,7 @@ static int i2c_poll_tran_heatbeat_timeout(i2c_t *obj, uint32_t timeout) break; } } - + return (elapsed >= timeout); } @@ -548,12 +542,12 @@ static int i2c_is_trsn_done(i2c_t *obj) int i2c_int; uint32_t status; int inten_back; - + inten_back = i2c_set_int(obj, 0); i2c_int = !! (i2c_base->CTL0 & I2C_CTL0_SI_Msk); status = I2C_GET_STATUS(i2c_base); i2c_set_int(obj, inten_back); - + return (i2c_int || status == 0xF8); } @@ -561,11 +555,11 @@ static int i2c_is_tran_started(i2c_t *obj) { int started; int inten_back; - + inten_back = i2c_set_int(obj, 0); started = !! (obj->i2c.tran_ctrl & TRANCTRL_STARTED); i2c_set_int(obj, inten_back); - + return started; } @@ -591,227 +585,213 @@ static void i2c_irq(i2c_t *obj) { I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); uint32_t status; - + if (I2C_GET_TIMEOUT_FLAG(i2c_base)) { I2C_ClearTimeoutFlag(i2c_base); return; } - + status = I2C_GET_STATUS(i2c_base); #if NU_I2C_DEBUG if (MY_I2C_STATUS_POS < (sizeof (MY_I2C_STATUS) / sizeof (MY_I2C_STATUS[0]))) { MY_I2C_STATUS[MY_I2C_STATUS_POS ++] = status; - } - else { + } else { memset(MY_I2C_STATUS, 0x00, sizeof (MY_I2C_STATUS)); MY_I2C_STATUS_POS = 0; } #endif - + switch (status) { - // Master Transmit - case 0x28: // Master Transmit Data ACK - case 0x18: // Master Transmit Address ACK - case 0x08: // Start - case 0x10: // Master Repeat Start - if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { - if (obj->i2c.tran_pos < obj->i2c.tran_end) { - I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++); - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - } - else { - i2c_fsm_tranfini(obj, 0); - } + // Master Transmit + case 0x28: // Master Transmit Data ACK + case 0x18: // Master Transmit Address ACK + case 0x08: // Start + case 0x10: // Master Repeat Start + if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { + if (obj->i2c.tran_pos < obj->i2c.tran_end) { + I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++); + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + } else { + i2c_fsm_tranfini(obj, 0); } - else { - i2c_disable_int(obj); - } - break; - - case 0x30: // Master Transmit Data NACK - i2c_fsm_tranfini(obj, 1); - break; - - case 0x20: // Master Transmit Address NACK - i2c_fsm_tranfini(obj, 1); - break; - - case 0x38: // Master Arbitration Lost - i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - break; - - case 0x48: // Master Receive Address NACK - i2c_fsm_tranfini(obj, 1); - break; - - case 0x40: // Master Receive Address ACK - case 0x50: // Master Receive Data ACK - case 0x58: // Master Receive Data NACK - if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { - if (obj->i2c.tran_pos < obj->i2c.tran_end) { - if (status == 0x50 || status == 0x58) { - *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); - } - - if (status == 0x58) { + } else { + i2c_disable_int(obj); + } + break; + + case 0x30: // Master Transmit Data NACK + i2c_fsm_tranfini(obj, 1); + break; + + case 0x20: // Master Transmit Address NACK + i2c_fsm_tranfini(obj, 1); + break; + + case 0x38: // Master Arbitration Lost + i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + break; + + case 0x48: // Master Receive Address NACK + i2c_fsm_tranfini(obj, 1); + break; + + case 0x40: // Master Receive Address ACK + case 0x50: // Master Receive Data ACK + case 0x58: // Master Receive Data NACK + if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { + if (obj->i2c.tran_pos < obj->i2c.tran_end) { + if (status == 0x50 || status == 0x58) { + *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); + } + + if (status == 0x58) { #if NU_I2C_DEBUG - if (obj->i2c.tran_pos != obj->i2c.tran_end) { - MY_I2C = obj->i2c; - while (1); - } + if (obj->i2c.tran_pos != obj->i2c.tran_end) { + MY_I2C = obj->i2c; + while (1); + } #endif - i2c_fsm_tranfini(obj, 1); - } - else { - uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; - if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && - obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { - // Last data - i2c_ctl &= ~I2C_CTL0_AA_Msk; - } - I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); - } - } - else { - obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; - i2c_disable_int(obj); - break; - } - } - else { - i2c_disable_int(obj); - } - break; - - //case 0x00: // Bus error - - // Slave Transmit - case 0xB8: // Slave Transmit Data ACK - case 0xA8: // Slave Transmit Address ACK - case 0xB0: // Slave Transmit Arbitration Lost - if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { - if (obj->i2c.tran_pos < obj->i2c.tran_end) { + i2c_fsm_tranfini(obj, 1); + } else { uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; - - I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++); - if (obj->i2c.tran_pos == obj->i2c.tran_end && - obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { + if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && + obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { // Last data i2c_ctl &= ~I2C_CTL0_AA_Msk; } I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); } - else { - obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; - i2c_disable_int(obj); - break; - } - } - else { + } else { + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; i2c_disable_int(obj); + break; } - obj->i2c.slaveaddr_state = ReadAddressed; - break; - //case 0xA0: // Slave Transmit Repeat Start or Stop - case 0xC0: // Slave Transmit Data NACK - case 0xC8: // Slave Transmit Last Data ACK - obj->i2c.slaveaddr_state = NoData; - i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - break; - - // Slave Receive - case 0x80: // Slave Receive Data ACK - case 0x88: // Slave Receive Data NACK - case 0x60: // Slave Receive Address ACK - case 0x68: // Slave Receive Arbitration Lost - obj->i2c.slaveaddr_state = WriteAddressed; - if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { - if (obj->i2c.tran_pos < obj->i2c.tran_end) { - if (status == 0x80 || status == 0x88) { - *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); - } - - if (status == 0x88) { + } else { + i2c_disable_int(obj); + } + break; + + //case 0x00: // Bus error + + // Slave Transmit + case 0xB8: // Slave Transmit Data ACK + case 0xA8: // Slave Transmit Address ACK + case 0xB0: // Slave Transmit Arbitration Lost + if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { + if (obj->i2c.tran_pos < obj->i2c.tran_end) { + uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; + + I2C_SET_DATA(i2c_base, *obj->i2c.tran_pos ++); + if (obj->i2c.tran_pos == obj->i2c.tran_end && + obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { + // Last data + i2c_ctl &= ~I2C_CTL0_AA_Msk; + } + I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); + } else { + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; + i2c_disable_int(obj); + break; + } + } else { + i2c_disable_int(obj); + } + obj->i2c.slaveaddr_state = ReadAddressed; + break; + //case 0xA0: // Slave Transmit Repeat Start or Stop + case 0xC0: // Slave Transmit Data NACK + case 0xC8: // Slave Transmit Last Data ACK + obj->i2c.slaveaddr_state = NoData; + i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + break; + + // Slave Receive + case 0x80: // Slave Receive Data ACK + case 0x88: // Slave Receive Data NACK + case 0x60: // Slave Receive Address ACK + case 0x68: // Slave Receive Arbitration Lost + obj->i2c.slaveaddr_state = WriteAddressed; + if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { + if (obj->i2c.tran_pos < obj->i2c.tran_end) { + if (status == 0x80 || status == 0x88) { + *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); + } + + if (status == 0x88) { #if NU_I2C_DEBUG - if (obj->i2c.tran_pos != obj->i2c.tran_end) { - MY_I2C = obj->i2c; - while (1); - } + if (obj->i2c.tran_pos != obj->i2c.tran_end) { + MY_I2C = obj->i2c; + while (1); + } #endif - obj->i2c.slaveaddr_state = NoData; - i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - } - else { - uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; - if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && + obj->i2c.slaveaddr_state = NoData; + i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + } else { + uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; + if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { - // Last data - i2c_ctl &= ~I2C_CTL0_AA_Msk; - } - I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); + // Last data + i2c_ctl &= ~I2C_CTL0_AA_Msk; } + I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); } - else { - obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; - i2c_disable_int(obj); - break; - } - } - else { + } else { + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; i2c_disable_int(obj); + break; } - break; - //case 0xA0: // Slave Receive Repeat Start or Stop - - // GC mode - //case 0xA0: // GC mode Repeat Start or Stop - case 0x90: // GC mode Data ACK - case 0x98: // GC mode Data NACK - case 0x70: // GC mode Address ACK - case 0x78: // GC mode Arbitration Lost - obj->i2c.slaveaddr_state = WriteAddressed; - if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { - if (obj->i2c.tran_pos < obj->i2c.tran_end) { - if (status == 0x90 || status == 0x98) { - *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); - } - - if (status == 0x98) { + } else { + i2c_disable_int(obj); + } + break; + //case 0xA0: // Slave Receive Repeat Start or Stop + + // GC mode + //case 0xA0: // GC mode Repeat Start or Stop + case 0x90: // GC mode Data ACK + case 0x98: // GC mode Data NACK + case 0x70: // GC mode Address ACK + case 0x78: // GC mode Arbitration Lost + obj->i2c.slaveaddr_state = WriteAddressed; + if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { + if (obj->i2c.tran_pos < obj->i2c.tran_end) { + if (status == 0x90 || status == 0x98) { + *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); + } + + if (status == 0x98) { #if NU_I2C_DEBUG - if (obj->i2c.tran_pos != obj->i2c.tran_end) { - MY_I2C = obj->i2c; - while (1); - } + if (obj->i2c.tran_pos != obj->i2c.tran_end) { + MY_I2C = obj->i2c; + while (1); + } #endif - obj->i2c.slaveaddr_state = NoData; - i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); - } - else { - uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; - if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && + obj->i2c.slaveaddr_state = NoData; + i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + } else { + uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; + if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && obj->i2c.tran_ctrl & TRANCTRL_NAKLASTDATA) { - // Last data - i2c_ctl &= ~I2C_CTL0_AA_Msk; - } - I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); + // Last data + i2c_ctl &= ~I2C_CTL0_AA_Msk; } + I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); } - else { - obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; - i2c_disable_int(obj); - break; - } - } - else { + } else { + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; i2c_disable_int(obj); + break; } - break; - - case 0xF8: // Bus Released - break; - - default: - i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); + } else { + i2c_disable_int(obj); + } + break; + + case 0xF8: // Bus Released + break; + + default: + i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); } } @@ -820,9 +800,9 @@ static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl) I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); obj->i2c.stop = 0; - + obj->i2c.tran_ctrl = 0; - + I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); obj->i2c.slaveaddr_state = NoData; } @@ -832,7 +812,7 @@ static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked) if (lastdatanaked) { obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED; } - + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; i2c_disable_int(obj); } @@ -843,9 +823,9 @@ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, { // NOTE: M451 I2C only supports 7-bit slave address. The mbed I2C address passed in is shifted left by 1 bit (7-bit addr << 1). MBED_ASSERT((address & 0xFFFFFF00) == 0); - + // NOTE: First transmit and then receive. - + (void) hint; obj->i2c.dma_usage = DMA_USAGE_NEVER; obj->i2c.stop = stop; @@ -864,107 +844,101 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj) I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); uint32_t status = I2C_GET_STATUS(i2c_base); switch (status) { - case 0x08: // Start - case 0x10: {// Master Repeat Start - if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { - I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 0))); - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); + case 0x08: // Start + case 0x10: {// Master Repeat Start + if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { + I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 0))); + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); + } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 1))); + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); + } else { + event = I2C_EVENT_TRANSFER_COMPLETE; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); } - else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { - I2C_SET_DATA(i2c_base, (i2c_addr2data(obj->i2c.address, 1))); - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); - } - else { - event = I2C_EVENT_TRANSFER_COMPLETE; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - } - break; } - - case 0x18: // Master Transmit Address ACK - case 0x28: // Master Transmit Data ACK - if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { - uint8_t *tx = (uint8_t *)obj->tx_buff.buffer; - I2C_SET_DATA(i2c_base, tx[obj->tx_buff.pos ++]); - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); - } - else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); - } - else { - event = I2C_EVENT_TRANSFER_COMPLETE; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - } - break; - - case 0x20: // Master Transmit Address NACK - event = I2C_EVENT_ERROR_NO_SLAVE; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - break; - - case 0x30: // Master Transmit Data NACK - if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { - event = I2C_EVENT_TRANSFER_EARLY_NACK; - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); - } - else { - event = I2C_EVENT_TRANSFER_COMPLETE; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - } - break; - - case 0x38: // Master Arbitration Lost - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); // Enter not addressed SLV mode - event = I2C_EVENT_ERROR; - break; - - case 0x50: // Master Receive Data ACK - if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { - uint8_t *rx = (uint8_t *) obj->rx_buff.buffer; - rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c))); - } - case 0x40: // Master Receive Address ACK - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | ((obj->rx_buff.pos != obj->rx_buff.length - 1) ? I2C_CTL0_AA_Msk : 0)); - break; - - case 0x48: // Master Receive Address NACK - event = I2C_EVENT_ERROR_NO_SLAVE; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } - break; - - case 0x58: // Master Receive Data NACK - if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { - uint8_t *rx = (uint8_t *) obj->rx_buff.buffer; - rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c))); - } - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); - break; - - case 0x00: // Bus error - event = I2C_EVENT_ERROR; - i2c_reset(obj); - break; - - default: - event = I2C_EVENT_ERROR; - if (obj->i2c.stop) { - I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); - } + break; } - + + case 0x18: // Master Transmit Address ACK + case 0x28: // Master Transmit Data ACK + if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { + uint8_t *tx = (uint8_t *)obj->tx_buff.buffer; + I2C_SET_DATA(i2c_base, tx[obj->tx_buff.pos ++]); + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); + } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); + } else { + event = I2C_EVENT_TRANSFER_COMPLETE; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } + } + break; + + case 0x20: // Master Transmit Address NACK + event = I2C_EVENT_ERROR_NO_SLAVE; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } + break; + + case 0x30: // Master Transmit Data NACK + if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { + event = I2C_EVENT_TRANSFER_EARLY_NACK; + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); + } else { + event = I2C_EVENT_TRANSFER_COMPLETE; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } + } + break; + + case 0x38: // Master Arbitration Lost + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk); // Enter not addressed SLV mode + event = I2C_EVENT_ERROR; + break; + + case 0x50: // Master Receive Data ACK + if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + uint8_t *rx = (uint8_t *) obj->rx_buff.buffer; + rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c))); + } + case 0x40: // Master Receive Address ACK + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_SI_Msk | ((obj->rx_buff.pos != obj->rx_buff.length - 1) ? I2C_CTL0_AA_Msk : 0)); + break; + + case 0x48: // Master Receive Address NACK + event = I2C_EVENT_ERROR_NO_SLAVE; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } + break; + + case 0x58: // Master Receive Data NACK + if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + uint8_t *rx = (uint8_t *) obj->rx_buff.buffer; + rx[obj->rx_buff.pos ++] = I2C_GET_DATA(((I2C_T *) NU_MODBASE(obj->i2c.i2c))); + } + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk); + break; + + case 0x00: // Bus error + event = I2C_EVENT_ERROR; + i2c_reset(obj); + break; + + default: + event = I2C_EVENT_ERROR; + if (obj->i2c.stop) { + I2C_SET_CONTROL_REG(i2c_base, I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk); + } + } + if (event) { i2c_rollback_vector_interrupt(obj); } @@ -973,11 +947,11 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj) } uint8_t i2c_active(i2c_t *obj) -{ +{ const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->i2c.i2c); - + // Vector will be changed for async transfer. Use it to judge if async transfer is on-going. uint32_t vec = NVIC_GetVector(modinit->irq_n); struct nu_i2c_var *var = (struct nu_i2c_var *) modinit->var; @@ -1005,12 +979,11 @@ static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->i2c.i2c); - + if (enable) { NVIC_SetVector(modinit->irq_n, handler); i2c_enable_int(obj); - } - else { + } else { i2c_disable_int(obj); } @@ -1021,7 +994,7 @@ static void i2c_rollback_vector_interrupt(i2c_t *obj) const struct nu_modinit_s *modinit = get_modinit(obj->i2c.i2c, i2c_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->i2c.i2c); - + struct nu_i2c_var *var = (struct nu_i2c_var *) modinit->var; i2c_enable_vector_interrupt(obj, (uint32_t) var->vec, 1); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c index cc6846ba6c..36bf2dc46b 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "lp_ticker_api.h" #if DEVICE_LOWPOWERTIMER @@ -56,7 +56,7 @@ void lp_ticker_init(void) return; } lp_ticker_inited = 1; - + counter_major = 0; cd_major_minor_clks = 0; cd_minor_clks = 0; @@ -65,7 +65,7 @@ void lp_ticker_init(void) // Reset module SYS_ResetModule(timer2_modinit.rsetidx); SYS_ResetModule(timer3_modinit.rsetidx); - + // Select IP clock source CLK_SetModuleClock(timer2_modinit.clkidx, timer2_modinit.clksrc, timer2_modinit.clkdiv); CLK_SetModuleClock(timer3_modinit.clkidx, timer3_modinit.clksrc, timer3_modinit.clkdiv); @@ -84,92 +84,88 @@ void lp_ticker_init(void) // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer2/* | TIMER_CTL_CNTDATEN_Msk*/; ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CMP = cmp_timer2; - + // Set vector NVIC_SetVector(timer2_modinit.irq_n, (uint32_t) timer2_modinit.var); NVIC_SetVector(timer3_modinit.irq_n, (uint32_t) timer3_modinit.var); - + NVIC_EnableIRQ(timer2_modinit.irq_n); NVIC_EnableIRQ(timer3_modinit.irq_n); - + TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); - + // NOTE: TIMER_Start() first and then lp_ticker_set_interrupt(); otherwise, we may get stuck in lp_ticker_read() because // timer is not running. - + // Start timer TIMER_Start((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); - + // Schedule wakeup to match semantics of lp_ticker_get_compare_match() lp_ticker_set_interrupt(wakeup_tick); - - + + } timestamp_t lp_ticker_read() -{ +{ if (! lp_ticker_inited) { lp_ticker_init(); } - + TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); - + do { uint64_t major_minor_clks; uint32_t minor_clks; - + // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { core_util_critical_section_enter(); - + // NOTE: Order of reading minor_us/carry here is significant. minor_clks = TIMER_GetCounter(timer2_base); uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Handle carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_clks > (TMR2_CLK_PER_TMR2_INT / 2)) { major_minor_clks = (counter_major + 1) * TMR2_CLK_PER_TMR2_INT; - } - else { + } else { major_minor_clks = (counter_major + carry) * TMR2_CLK_PER_TMR2_INT + minor_clks; } - + core_util_critical_section_exit(); - } - while (minor_clks == 0 || minor_clks == TMR2_CLK_PER_TMR2_INT); + } while (minor_clks == 0 || minor_clks == TMR2_CLK_PER_TMR2_INT); // Add power-down compensation return ((uint64_t) major_minor_clks * US_PER_SEC / TMR2_CLK_PER_SEC / US_PER_TICK); - } - while (0); + } while (0); } void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t now = lp_ticker_read(); wakeup_tick = timestamp; - + TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); - + /** * FIXME: Scheduled alarm may go off incorrectly due to wrap around. * Conditions in which delta is negative: * 1. Wrap around * 2. Newly scheduled alarm is behind now - */ + */ //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now); int delta = (int) (timestamp - now); if (delta > 0) { cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; lp_ticker_arm_cd(); - } - else { + } else { cd_major_minor_clks = cd_minor_clks = 0; /** * This event was in the past. Set the interrupt as pending, but don't process it here. * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ + */ NVIC_SetPendingIRQ(timer3_modinit.irq_n); } } @@ -199,8 +195,7 @@ static void tmr3_vec(void) if (cd_major_minor_clks == 0) { // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler(); lp_ticker_irq_handler(); - } - else { + } else { lp_ticker_arm_cd(); } } @@ -208,13 +203,13 @@ static void tmr3_vec(void) static void lp_ticker_arm_cd(void) { TIMER_T * timer3_base = (TIMER_T *) NU_MODBASE(timer3_modinit.modname); - + // Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit // NUC472/M451: See TIMER_CTL_RSTCNT_Msk // M480 timer3_base->CNT = 0; while (timer3_base->CNT & TIMER_CNT_RSTACT_Msk); - // One-shot mode, Clock = 1 KHz + // One-shot mode, Clock = 1 KHz uint32_t clk_timer3 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); uint32_t prescale_timer3 = clk_timer3 / TMR3_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer3 != (uint32_t) -1) && prescale_timer3 <= 127); @@ -222,11 +217,11 @@ static void lp_ticker_arm_cd(void) // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. timer3_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk/* | TIMER_CTL_CNTDATEN_Msk*/); timer3_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer3/* | TIMER_CTL_CNTDATEN_Msk*/; - + cd_minor_clks = cd_major_minor_clks; cd_minor_clks = NU_CLAMP(cd_minor_clks, TMR_CMP_MIN, TMR_CMP_MAX); timer3_base->CMP = cd_minor_clks; - + TIMER_EnableInt(timer3_base); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); TIMER_Start(timer3_base); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/pinmap.c b/targets/TARGET_NUVOTON/TARGET_M480/pinmap.c index 5b20762370..3e360a708e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/pinmap.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/pinmap.c @@ -29,7 +29,7 @@ void pin_function(PinName pin, int data) uint32_t port_index = NU_PINNAME_TO_PORT(pin); __IO uint32_t *GPx_MFPx = ((__IO uint32_t *) &SYS->GPA_MFPL) + port_index * 2 + (pin_index / 8); uint32_t MFP_Msk = NU_MFP_MSK(pin_index); - + // E.g.: SYS->GPA_MFPL = (SYS->GPA_MFPL & (~SYS_GPA_MFPL_PA0MFP_Msk) ) | SYS_GPA_MFPL_PA0MFP_SC0_CD ; *GPx_MFPx = (*GPx_MFPx & (~MFP_Msk)) | data; } @@ -43,31 +43,31 @@ void pin_mode(PinName pin, PinMode mode) uint32_t pin_index = NU_PINNAME_TO_PIN(pin); uint32_t port_index = NU_PINNAME_TO_PORT(pin); GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + uint32_t mode_intern = GPIO_MODE_INPUT; - + switch (mode) { - case PullUp: - mode_intern = GPIO_MODE_INPUT; - break; - - case PullDown: - case PullNone: - // NOTE: Not support - return; - - case PushPull: - mode_intern = GPIO_MODE_OUTPUT; - break; - - case OpenDrain: - mode_intern = GPIO_MODE_OPEN_DRAIN; - break; - - case Quasi: - mode_intern = GPIO_MODE_QUASI; - break; + case PullUp: + mode_intern = GPIO_MODE_INPUT; + break; + + case PullDown: + case PullNone: + // NOTE: Not support + return; + + case PushPull: + mode_intern = GPIO_MODE_OUTPUT; + break; + + case OpenDrain: + mode_intern = GPIO_MODE_OPEN_DRAIN; + break; + + case Quasi: + mode_intern = GPIO_MODE_QUASI; + break; } - + GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/port_api.c b/targets/TARGET_NUVOTON/TARGET_M480/port_api.c index 84278d0dbb..159f8d1c50 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/port_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/port_api.c @@ -39,7 +39,7 @@ void port_init(port_t *obj, PortName port, int mask, PinDirection dir) gpio_set(port_pin(port, i)); } } - + port_dir(obj, dir); } @@ -61,7 +61,7 @@ void port_dir(port_t *obj, PinDirection dir) void port_mode(port_t *obj, PinMode mode) { uint32_t i; - + for (i = 0; i < GPIO_PIN_MAX; i++) { if (obj->mask & (1 << i)) { pin_mode(port_pin(obj->port, i), mode); @@ -73,7 +73,7 @@ void port_write(port_t *obj, int value) { uint32_t i; uint32_t port_index = obj->port; - + for (i = 0; i < GPIO_PIN_MAX; i++) { if (obj->mask & (1 << i)) { GPIO_PIN_DATA(port_index, i) = (value & obj->mask) ? 1 : 0; @@ -86,13 +86,13 @@ int port_read(port_t *obj) uint32_t i; uint32_t port_index = obj->port; int value = 0; - + for (i = 0; i < GPIO_PIN_MAX; i++) { if (obj->mask & (1 << i)) { value = value | (GPIO_PIN_DATA(port_index, i) << i); } } - + return value; } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/pwmout_api.c b/targets/TARGET_NUVOTON/TARGET_M480/pwmout_api.c index 3db17576f4..721bd26a56 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/pwmout_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/pwmout_api.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "pwmout_api.h" #if DEVICE_PWMOUT @@ -53,7 +53,7 @@ static const struct nu_modinit_s pwm_modinit_tab[] = { {PWM_1_3, EPWM1_MODULE, CLK_CLKSEL2_EPWM1SEL_PCLK1, 0, EPWM1_RST, EPWM1P1_IRQn, &pwm1_var}, {PWM_1_4, EPWM1_MODULE, CLK_CLKSEL2_EPWM1SEL_PCLK1, 0, EPWM1_RST, EPWM1P2_IRQn, &pwm1_var}, {PWM_1_5, EPWM1_MODULE, CLK_CLKSEL2_EPWM1SEL_PCLK1, 0, EPWM1_RST, EPWM1P2_IRQn, &pwm1_var}, - + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; @@ -67,16 +67,16 @@ void pwmout_init(pwmout_t* obj, PinName pin) const struct nu_modinit_s *modinit = get_modinit(obj->pwm, pwm_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->pwm); - + // NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module. if (! ((struct nu_pwm_var *) modinit->var)->en_msk) { // Reset this module if no channel enabled SYS_ResetModule(modinit->rsetidx); } - + EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm); uint32_t chn = NU_MODSUBINDEX(obj->pwm); - + // NOTE: Channels 0/1/2/3/4/5 share a clock source. if ((((struct nu_pwm_var *) modinit->var)->en_msk & 0x3F) == 0) { // Select clock source of paired channels @@ -84,17 +84,17 @@ void pwmout_init(pwmout_t* obj, PinName pin) // Enable clock of paired channels CLK_EnableModuleClock(modinit->clkidx); } - + // Wire pinout pinmap_pinout(pin, PinMap_PWM); - + // Default: period = 10 ms, pulse width = 0 ms obj->period_us = 1000 * 10; obj->pulsewidth_us = 0; pwmout_config(obj, 0); - + ((struct nu_pwm_var *) modinit->var)->en_msk |= 1 << chn; - + // Mark this module to be inited. int i = modinit - pwm_modinit_tab; pwm_modinit_mask |= 1 << i; @@ -105,17 +105,17 @@ void pwmout_free(pwmout_t* obj) EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm); uint32_t chn = NU_MODSUBINDEX(obj->pwm); EPWM_ForceStop(pwm_base, 1 << chn); - + const struct nu_modinit_s *modinit = get_modinit(obj->pwm, pwm_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->pwm); ((struct nu_pwm_var *) modinit->var)->en_msk &= ~(1 << chn); - - + + if ((((struct nu_pwm_var *) modinit->var)->en_msk & 0x3F) == 0) { CLK_DisableModuleClock(modinit->clkidx); } - + // Mark this module to be deinited. int i = modinit - pwm_modinit_tab; pwm_modinit_mask &= ~(1 << i); @@ -184,7 +184,7 @@ int pwmout_allow_powerdown(void) } modinit_mask &= ~(1 << pwm_idx); } - + return 1; } @@ -192,19 +192,19 @@ static void pwmout_config(pwmout_t* obj, int start) { EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm); uint32_t chn = NU_MODSUBINDEX(obj->pwm); - + // To avoid abnormal pulse on (re-)configuration, follow the sequence: stop/configure(/re-start). // NOTE: The issue is met in ARM mbed CI test tests-api-pwm on M487. EPWM_ForceStop(pwm_base, 1 << chn); - + // NOTE: Support period < 1s // NOTE: ARM mbed CI test fails due to first PWM pulse error. Workaround by: // 1. Inverse duty cycle (100 - duty) // 2. Inverse PWM output polarity - // This trick is here to pass ARM mbed CI test. First PWM pulse error still remains. + // This trick is here to pass ARM mbed CI test. First PWM pulse error still remains. EPWM_ConfigOutputChannel2(pwm_base, chn, 1000 * 1000, 100 - obj->pulsewidth_us * 100 / obj->period_us, obj->period_us); pwm_base->POLCTL |= 1 << (EPWM_POLCTL_PINV0_Pos + chn); - + if (start) { // Enable output of the specified PWM channel EPWM_EnableOutput(pwm_base, 1 << chn); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c b/targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c index 5f438ef0e6..5047ccad03 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/rtc_api.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "rtc_api.h" #if DEVICE_RTC @@ -33,7 +33,7 @@ void rtc_init(void) if (rtc_isenabled()) { return; } - + RTC_Open(NULL); } @@ -49,7 +49,7 @@ int rtc_isenabled(void) // Enable IP clock CLK_EnableModuleClock(rtc_modinit.clkidx); } - + // NOTE: Check RTC Init Active flag to support crossing reset cycle. return !! (RTC->INIT & RTC_INIT_ACTIVE_Msk); } @@ -76,10 +76,10 @@ time_t rtc_read(void) if (! rtc_isenabled()) { rtc_init(); } - + S_RTC_TIME_DATA_T rtc_datetime; RTC_GetDateAndTime(&rtc_datetime); - + struct tm timeinfo; // Convert struct tm to S_RTC_TIME_DATA_T @@ -102,12 +102,12 @@ void rtc_write(time_t t) if (! rtc_isenabled()) { rtc_init(); } - + // Convert timestamp to struct tm struct tm *timeinfo = localtime(&t); S_RTC_TIME_DATA_T rtc_datetime; - + // Convert S_RTC_TIME_DATA_T to struct tm rtc_datetime.u32Year = timeinfo->tm_year + YEAR0; rtc_datetime.u32Month = timeinfo->tm_mon + 1; @@ -117,7 +117,7 @@ void rtc_write(time_t t) rtc_datetime.u32Minute = timeinfo->tm_min; rtc_datetime.u32Second = timeinfo->tm_sec; rtc_datetime.u32TimeScale = RTC_CLOCK_24; - + // NOTE: Timing issue with write to RTC registers. This delay is empirical, not rational. RTC_SetDateAndTime(&rtc_datetime); wait_us(100); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/serial_api.c b/targets/TARGET_NUVOTON/TARGET_M480/serial_api.c index ceecf1e4c8..e45867c118 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/serial_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/serial_api.c @@ -172,7 +172,7 @@ static const struct nu_modinit_s uart_modinit_tab[] = { {UART_3, UART3_MODULE, CLK_CLKSEL3_UART3SEL_HIRC, CLK_CLKDIV4_UART3(1), UART3_RST, UART3_IRQn, &uart3_var}, {UART_4, UART4_MODULE, CLK_CLKSEL3_UART4SEL_HIRC, CLK_CLKDIV4_UART4(1), UART4_RST, UART4_IRQn, &uart4_var}, {UART_5, UART5_MODULE, CLK_CLKSEL3_UART5SEL_HIRC, CLK_CLKDIV4_UART5(1), UART5_RST, UART5_IRQn, &uart5_var}, - + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; @@ -182,7 +182,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { // NOTE: With armcc, serial_init() gets called from _sys_open() timing of which is before main()/mbed_sdk_init(). mbed_sdk_init(); - + // Determine which UART_x the pins are used for uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX); uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX); @@ -193,14 +193,14 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; - + if (! var->ref_cnt) { do { // Reset this module SYS_ResetModule(modinit->rsetidx); - + // Select IP clock source CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); // Enable IP clock @@ -209,20 +209,20 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) pinmap_pinout(tx, PinMap_UART_TX); pinmap_pinout(rx, PinMap_UART_RX); } while (0); - + obj->serial.pin_tx = tx; obj->serial.pin_rx = rx; } var->ref_cnt ++; - + // Configure the UART module and set its baudrate serial_baud(obj, 9600); // Configure data bits, parity, and stop bits serial_format(obj, 8, ParityNone, 1); - + obj->serial.vec = var->vec; obj->serial.irq_en = 0; - + #if DEVICE_SERIAL_ASYNCH obj->serial.dma_usage_tx = DMA_USAGE_NEVER; obj->serial.dma_usage_rx = DMA_USAGE_NEVER; @@ -236,7 +236,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } - + if (var->ref_cnt) { // Mark this module to be inited. int i = modinit - uart_modinit_tab; @@ -249,9 +249,9 @@ void serial_free(serial_t *obj) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; - + var->ref_cnt --; if (! var->ref_cnt) { #if DEVICE_SERIAL_ASYNCH @@ -267,23 +267,23 @@ void serial_free(serial_t *obj) do { UART_Close((UART_T *) NU_MODBASE(obj->serial.uart)); - + UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk)); NVIC_DisableIRQ(modinit->irq_n); - + // Disable IP clock CLK_DisableModuleClock(modinit->clkidx); } while (0); } - + if (var->obj == obj) { var->obj = NULL; } - + if (obj->serial.uart == STDIO_UART) { stdio_uart_inited = 0; } - + if (! var->ref_cnt) { // Mark this module to be deinited. int i = modinit - uart_modinit_tab; @@ -291,40 +291,42 @@ void serial_free(serial_t *obj) } } -void serial_baud(serial_t *obj, int baudrate) { +void serial_baud(serial_t *obj, int baudrate) +{ // Flush Tx FIFO. Otherwise, output data may get lost on this change. while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart))); - + obj->serial.baudrate = baudrate; UART_Open((UART_T *) NU_MODBASE(obj->serial.uart), baudrate); } -void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) +{ // Flush Tx FIFO. Otherwise, output data may get lost on this change. while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart))); - - // Sanity check arguments + + // Sanity check arguments MBED_ASSERT((data_bits == 5) || (data_bits == 6) || (data_bits == 7) || (data_bits == 8)); MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) || (parity == ParityForced1) || (parity == ParityForced0)); MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); - + obj->serial.databits = data_bits; obj->serial.parity = parity; obj->serial.stopbits = stop_bits; - + uint32_t databits_intern = (data_bits == 5) ? UART_WORD_LEN_5 : - (data_bits == 6) ? UART_WORD_LEN_6 : - (data_bits == 7) ? UART_WORD_LEN_7 : - UART_WORD_LEN_8; + (data_bits == 6) ? UART_WORD_LEN_6 : + (data_bits == 7) ? UART_WORD_LEN_7 : + UART_WORD_LEN_8; uint32_t parity_intern = (parity == ParityOdd || parity == ParityForced1) ? UART_PARITY_ODD : - (parity == ParityEven || parity == ParityForced0) ? UART_PARITY_EVEN : - UART_PARITY_NONE; + (parity == ParityEven || parity == ParityForced0) ? UART_PARITY_EVEN : + UART_PARITY_NONE; uint32_t stopbits_intern = (stop_bits == 2) ? UART_STOP_BIT_2 : UART_STOP_BIT_1; - UART_SetLine_Config((UART_T *) NU_MODBASE(obj->serial.uart), - 0, // Don't change baudrate - databits_intern, - parity_intern, - stopbits_intern); + UART_SetLine_Config((UART_T *) NU_MODBASE(obj->serial.uart), + 0, // Don't change baudrate + databits_intern, + parity_intern, + stopbits_intern); } #if DEVICE_SERIAL_FC @@ -332,7 +334,7 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart); - + // First, disable flow control completely. uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk); @@ -342,7 +344,7 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi MBED_ASSERT(uart_rts == obj->serial.uart); // Enable the pin for RTS function pinmap_pinout(rxflow, PinMap_UART_RTS); - + // NOTE: Added in M480. Before configuring RTSACTLV, disable TX/RX. uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk; while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk); @@ -350,20 +352,20 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk; // NOTE: Added in M480. After configuring RTSACTLV, re-enable TX/RX. uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk; - + uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES; - + // Enable RTS uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk; } - + if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) { // Check if CTS pin matches. uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS); MBED_ASSERT(uart_cts == obj->serial.uart); // Enable the pin for CTS function pinmap_pinout(txflow, PinMap_UART_CTS); - + // NOTE: Added in M480. Before configuring CTSACTLV, disable TX/RX. uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk; while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk); @@ -371,7 +373,7 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk; // NOTE: Added in M480. After configuring CTSACTLV, re-enable TX/RX. uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk; - + // Enable CTS uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk; } @@ -383,14 +385,14 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { // Flush Tx FIFO. Otherwise, output data may get lost on this change. while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart))); - + const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + obj->serial.irq_handler = (uint32_t) handler; obj->serial.irq_id = id; - + // Restore sync-mode vector obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec; } @@ -406,13 +408,13 @@ int serial_getc(serial_t *obj) // NOTE: Every byte access requires accompaniment of one interrupt. This has side effect of performance degradation. while (! serial_readable(obj)); int c = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); - + // NOTE: On Nuvoton targets, no H/W IRQ to match TxIrq/RxIrq. - // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively. + // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively. if (obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)) { UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); } - + return c; } @@ -421,9 +423,9 @@ void serial_putc(serial_t *obj, int c) // NOTE: Every byte access requires accompaniment of one interrupt. This has side effect of performance degradation. while (! serial_writable(obj)); UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), c); - + // NOTE: On Nuvoton targets, no H/W IRQ to match TxIrq/RxIrq. - // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively. + // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively. if (obj->serial.inten_msk & UART_INTEN_THREIEN_Msk) { UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); } @@ -495,7 +497,7 @@ static void uart_irq(serial_t *obj) ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, RxIrq); } } - + if (uart_base->INTSTS & UART_INTSTS_THREINT_Msk) { // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next write. UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk); @@ -503,7 +505,7 @@ static void uart_irq(serial_t *obj) ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, TxIrq); } } - + // FIXME: Ignore all other interrupt flags. Clear them. Otherwise, program will get stuck in interrupt. uart_base->INTSTS = uart_base->INTSTS; uart_base->FIFOSTS = uart_base->FIFOSTS; @@ -517,11 +519,11 @@ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx obj->serial.dma_usage_tx = hint; serial_check_dma_usage(&obj->serial.dma_usage_tx, &obj->serial.dma_chn_id_tx); - + // UART IRQ is necessary for both interrupt way and DMA way serial_tx_enable_event(obj, event, 1); serial_tx_buffer_set(obj, tx, tx_length, tx_width); - + int n_word = 0; if (obj->serial.dma_usage_tx == DMA_USAGE_NEVER) { // Interrupt way @@ -532,36 +534,36 @@ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + PDMA_T *pdma_base = dma_modbase(); - + pdma_base->CHCTL |= 1 << obj->serial.dma_chn_id_tx; // Enable this DMA channel PDMA_SetTransferMode(obj->serial.dma_chn_id_tx, - ((struct nu_uart_var *) modinit->var)->pdma_perp_tx, // Peripheral connected to this PDMA - 0, // Scatter-gather disabled - 0); // Scatter-gather descriptor address - PDMA_SetTransferCnt(obj->serial.dma_chn_id_tx, - (tx_width == 8) ? PDMA_WIDTH_8 : (tx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, - tx_length); + ((struct nu_uart_var *) modinit->var)->pdma_perp_tx, // Peripheral connected to this PDMA + 0, // Scatter-gather disabled + 0); // Scatter-gather descriptor address + PDMA_SetTransferCnt(obj->serial.dma_chn_id_tx, + (tx_width == 8) ? PDMA_WIDTH_8 : (tx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, + tx_length); PDMA_SetTransferAddr(obj->serial.dma_chn_id_tx, - (uint32_t) tx, // NOTE: - // NUC472: End of source address - // M451: Start of source address - // M480: Start of source address - PDMA_SAR_INC, // Source address incremental - (uint32_t) NU_MODBASE(obj->serial.uart), // Destination address - PDMA_DAR_FIX); // Destination address fixed - PDMA_SetBurstType(obj->serial.dma_chn_id_tx, - PDMA_REQ_SINGLE, // Single mode - 0); // Burst size + (uint32_t) tx, // NOTE: + // NUC472: End of source address + // M451: Start of source address + // M480: Start of source address + PDMA_SAR_INC, // Source address incremental + (uint32_t) NU_MODBASE(obj->serial.uart), // Destination address + PDMA_DAR_FIX); // Destination address fixed + PDMA_SetBurstType(obj->serial.dma_chn_id_tx, + PDMA_REQ_SINGLE, // Single mode + 0); // Burst size PDMA_EnableInt(obj->serial.dma_chn_id_tx, - PDMA_INT_TRANS_DONE); // Interrupt type + PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->serial.dma_chn_id_tx, (uint32_t) uart_dma_handler_tx, (uint32_t) obj, DMA_EVENT_ALL); serial_tx_enable_interrupt(obj, handler, 1); ((UART_T *) NU_MODBASE(obj->serial.uart))->INTEN |= UART_INTEN_TXPDMAEN_Msk; // Start DMA transfer } - + return n_word; } @@ -572,19 +574,19 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt obj->serial.dma_usage_rx = hint; serial_check_dma_usage(&obj->serial.dma_usage_rx, &obj->serial.dma_chn_id_rx); // DMA doesn't support char match, so fall back to IRQ if it is requested. - if (obj->serial.dma_usage_rx != DMA_USAGE_NEVER && - (event & SERIAL_EVENT_RX_CHARACTER_MATCH) && - char_match != SERIAL_RESERVED_CHAR_MATCH) { + if (obj->serial.dma_usage_rx != DMA_USAGE_NEVER && + (event & SERIAL_EVENT_RX_CHARACTER_MATCH) && + char_match != SERIAL_RESERVED_CHAR_MATCH) { obj->serial.dma_usage_rx = DMA_USAGE_NEVER; dma_channel_free(obj->serial.dma_chn_id_rx); obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; } - + // UART IRQ is necessary for both interrupt way and DMA way serial_rx_enable_event(obj, event, 1); serial_rx_buffer_set(obj, rx, rx_length, rx_width); serial_rx_set_char_match(obj, char_match); - + if (obj->serial.dma_usage_rx == DMA_USAGE_NEVER) { // Interrupt way serial_rx_enable_interrupt(obj, handler, 1); @@ -593,30 +595,30 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + PDMA_T *pdma_base = dma_modbase(); - + pdma_base->CHCTL |= 1 << obj->serial.dma_chn_id_rx; // Enable this DMA channel PDMA_SetTransferMode(obj->serial.dma_chn_id_rx, - ((struct nu_uart_var *) modinit->var)->pdma_perp_rx, // Peripheral connected to this PDMA - 0, // Scatter-gather disabled - 0); // Scatter-gather descriptor address - PDMA_SetTransferCnt(obj->serial.dma_chn_id_rx, - (rx_width == 8) ? PDMA_WIDTH_8 : (rx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, - rx_length); + ((struct nu_uart_var *) modinit->var)->pdma_perp_rx, // Peripheral connected to this PDMA + 0, // Scatter-gather disabled + 0); // Scatter-gather descriptor address + PDMA_SetTransferCnt(obj->serial.dma_chn_id_rx, + (rx_width == 8) ? PDMA_WIDTH_8 : (rx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, + rx_length); PDMA_SetTransferAddr(obj->serial.dma_chn_id_rx, - (uint32_t) NU_MODBASE(obj->serial.uart), // Source address - PDMA_SAR_FIX, // Source address fixed - (uint32_t) rx, // NOTE: - // NUC472: End of destination address - // M451: Start of destination address - // M480: Start of destination address - PDMA_DAR_INC); // Destination address incremental - PDMA_SetBurstType(obj->serial.dma_chn_id_rx, - PDMA_REQ_SINGLE, // Single mode - 0); // Burst size + (uint32_t) NU_MODBASE(obj->serial.uart), // Source address + PDMA_SAR_FIX, // Source address fixed + (uint32_t) rx, // NOTE: + // NUC472: End of destination address + // M451: Start of destination address + // M480: Start of destination address + PDMA_DAR_INC); // Destination address incremental + PDMA_SetBurstType(obj->serial.dma_chn_id_rx, + PDMA_REQ_SINGLE, // Single mode + 0); // Burst size PDMA_EnableInt(obj->serial.dma_chn_id_rx, - PDMA_INT_TRANS_DONE); // Interrupt type + PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->serial.dma_chn_id_rx, (uint32_t) uart_dma_handler_rx, (uint32_t) obj, DMA_EVENT_ALL); serial_rx_enable_interrupt(obj, handler, 1); @@ -628,10 +630,10 @@ void serial_tx_abort_asynch(serial_t *obj) { // Flush Tx FIFO. Otherwise, output data may get lost on this change. while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart))); - + if (obj->serial.dma_usage_tx != DMA_USAGE_NEVER) { PDMA_T *pdma_base = dma_modbase(); - + if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->serial.dma_chn_id_tx, PDMA_INT_TRANS_DONE); // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. @@ -639,7 +641,7 @@ void serial_tx_abort_asynch(serial_t *obj) } UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_TXPDMAEN_Msk); } - + // Necessary for both interrupt way and DMA way serial_enable_interrupt(obj, TxIrq, 0); serial_rollback_interrupt(obj, TxIrq); @@ -649,7 +651,7 @@ void serial_rx_abort_asynch(serial_t *obj) { if (obj->serial.dma_usage_rx != DMA_USAGE_NEVER) { PDMA_T *pdma_base = dma_modbase(); - + if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->serial.dma_chn_id_rx, PDMA_INT_TRANS_DONE); // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. @@ -657,7 +659,7 @@ void serial_rx_abort_asynch(serial_t *obj) } UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_RXPDMAEN_Msk); } - + // Necessary for both interrupt way and DMA way serial_enable_interrupt(obj, RxIrq, 0); serial_rollback_interrupt(obj, RxIrq); @@ -669,8 +671,8 @@ uint8_t serial_tx_active(serial_t *obj) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - - struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; + + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; return (obj->serial.vec == var->vec_async); } @@ -680,8 +682,8 @@ uint8_t serial_rx_active(serial_t *obj) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - - struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; + + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; return (obj->serial.vec == var->vec_async); } @@ -689,7 +691,7 @@ int serial_irq_handler_asynch(serial_t *obj) { int event_rx = 0; int event_tx = 0; - + // Necessary for both interrupt way and DMA way if (serial_is_irq_en(obj, RxIrq)) { event_rx = serial_rx_event_check(obj); @@ -697,14 +699,14 @@ int serial_irq_handler_asynch(serial_t *obj) serial_rx_abort_asynch(obj); } } - + if (serial_is_irq_en(obj, TxIrq)) { event_tx = serial_tx_event_check(obj); if (event_tx) { serial_tx_abort_asynch(obj); } } - + return (obj->serial.event & (event_rx | event_tx)); } @@ -731,7 +733,7 @@ int serial_allow_powerdown(void) } modinit_mask &= ~(1 << uart_idx); } - + return 1; } @@ -785,7 +787,7 @@ static void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable) { obj->serial.event &= ~SERIAL_EVENT_TX_MASK; obj->serial.event |= (event & SERIAL_EVENT_TX_MASK); - + if (event & SERIAL_EVENT_TX_COMPLETE) { // N/A } @@ -795,7 +797,7 @@ static void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) { obj->serial.event &= ~SERIAL_EVENT_RX_MASK; obj->serial.event |= (event & SERIAL_EVENT_RX_MASK); - + if (event & SERIAL_EVENT_RX_COMPLETE) { // N/A } @@ -830,36 +832,36 @@ static int serial_is_rx_complete(serial_t *obj) static uint32_t serial_tx_event_check(serial_t *obj) { UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart); - + if (uart_base->INTSTS & UART_INTSTS_THREINT_Msk) { // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next write. UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk); } - + uint32_t event = 0; - + if (obj->serial.dma_usage_tx == DMA_USAGE_NEVER) { serial_write_async(obj); } - + if (serial_is_tx_complete(obj)) { event |= SERIAL_EVENT_TX_COMPLETE; } - + return event; } static uint32_t serial_rx_event_check(serial_t *obj) { UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart); - + if (uart_base->INTSTS & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) { // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next read. UART_DISABLE_INT(uart_base, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); } - + uint32_t event = 0; - + if (uart_base->FIFOSTS & UART_FIFOSTS_BIF_Msk) { uart_base->FIFOSTS = UART_FIFOSTS_BIF_Msk; } @@ -871,7 +873,7 @@ static uint32_t serial_rx_event_check(serial_t *obj) uart_base->FIFOSTS = UART_FIFOSTS_PEF_Msk; event |= SERIAL_EVENT_RX_PARITY_ERROR; } - + if (uart_base->FIFOSTS & UART_FIFOSTS_RXOVIF_Msk) { uart_base->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk; event |= SERIAL_EVENT_RX_OVERFLOW; @@ -880,21 +882,21 @@ static uint32_t serial_rx_event_check(serial_t *obj) if (obj->serial.dma_usage_rx == DMA_USAGE_NEVER) { serial_read_async(obj); } - + if (serial_is_rx_complete(obj)) { event |= SERIAL_EVENT_RX_COMPLETE; } if ((obj->char_match != SERIAL_RESERVED_CHAR_MATCH) && obj->char_found) { event |= SERIAL_EVENT_RX_CHARACTER_MATCH; } - + return event; } static void uart_dma_handler_tx(uint32_t id, uint32_t event_dma) { serial_t *obj = (serial_t *) id; - + // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } @@ -905,14 +907,14 @@ static void uart_dma_handler_tx(uint32_t id, uint32_t event_dma) // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + uart_irq_async(obj); } static void uart_dma_handler_rx(uint32_t id, uint32_t event_dma) { serial_t *obj = (serial_t *) id; - + // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } @@ -923,18 +925,18 @@ static void uart_dma_handler_rx(uint32_t id, uint32_t event_dma) // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + uart_irq_async(obj); } static int serial_write_async(serial_t *obj) -{ +{ const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart); - + uint32_t tx_fifo_max = ((struct nu_uart_var *) modinit->var)->fifo_size_tx; uint32_t tx_fifo_busy = (uart_base->FIFOSTS & UART_FIFOSTS_TXPTR_Msk) >> UART_FIFOSTS_TXPTR_Pos; if (uart_base->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) { @@ -948,34 +950,34 @@ static int serial_write_async(serial_t *obj) } return 0; } - + uint32_t bytes_per_word = obj->tx_buff.width / 8; - + uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos; int n_words = 0; while (obj->tx_buff.pos < obj->tx_buff.length && tx_fifo_free >= bytes_per_word) { switch (bytes_per_word) { - case 4: - UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); - UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); - case 2: - UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); - case 1: - UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); + case 4: + UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); + UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); + case 2: + UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); + case 1: + UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++); } - + n_words ++; tx_fifo_free -= bytes_per_word; obj->tx_buff.pos ++; } - + if (n_words) { // Simulate clear of the interrupt flag if (obj->serial.inten_msk & UART_INTEN_THREIEN_Msk) { UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); } } - + return n_words; } @@ -984,38 +986,38 @@ static int serial_read_async(serial_t *obj) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + uint32_t rx_fifo_busy = (((UART_T *) NU_MODBASE(obj->serial.uart))->FIFOSTS & UART_FIFOSTS_RXPTR_Msk) >> UART_FIFOSTS_RXPTR_Pos; - + uint32_t bytes_per_word = obj->rx_buff.width / 8; - + uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos; int n_words = 0; while (obj->rx_buff.pos < obj->rx_buff.length && rx_fifo_busy >= bytes_per_word) { switch (bytes_per_word) { - case 4: - *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); - *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); - case 2: - *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); - case 1: - *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); + case 4: + *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); + *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); + case 2: + *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); + case 1: + *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart))); } - + n_words ++; rx_fifo_busy -= bytes_per_word; obj->rx_buff.pos ++; - + if ((obj->serial.event & SERIAL_EVENT_RX_CHARACTER_MATCH) && - obj->char_match != SERIAL_RESERVED_CHAR_MATCH) { + obj->char_match != SERIAL_RESERVED_CHAR_MATCH) { uint8_t *rx_cmp = rx; switch (bytes_per_word) { - case 4: - rx_cmp -= 2; - case 2: - rx_cmp --; - case 1: - rx_cmp --; + case 4: + rx_cmp -= 2; + case 2: + rx_cmp --; + case 1: + rx_cmp --; } if (*rx_cmp == obj->char_match) { obj->char_found = 1; @@ -1023,14 +1025,14 @@ static int serial_read_async(serial_t *obj) } } } - + if (n_words) { // Simulate clear of the interrupt flag if (obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)) { UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); } } - + return n_words; } @@ -1055,7 +1057,7 @@ static void serial_tx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + // Necessary for both interrupt way and DMA way struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; // With our own async vector, tx/rx handlers can be different. @@ -1069,7 +1071,7 @@ static void serial_rx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + // Necessary for both interrupt way and DMA way struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; // With our own async vector, tx/rx handlers can be different. @@ -1084,37 +1086,36 @@ static void serial_enable_interrupt(serial_t *obj, SerialIrq irq, uint32_t enabl const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + NVIC_SetVector(modinit->irq_n, (uint32_t) obj->serial.vec); NVIC_EnableIRQ(modinit->irq_n); - + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; // Multiple serial S/W objects for single UART H/W module possibly. // Bind serial S/W object to UART H/W module as interrupt is enabled. var->obj = obj; - + switch (irq) { - // NOTE: Setting inten_msk first to avoid race condition - case RxIrq: - obj->serial.inten_msk = obj->serial.inten_msk | (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); - UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); - break; - case TxIrq: - obj->serial.inten_msk = obj->serial.inten_msk | UART_INTEN_THREIEN_Msk; - UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); - break; + // NOTE: Setting inten_msk first to avoid race condition + case RxIrq: + obj->serial.inten_msk = obj->serial.inten_msk | (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); + UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); + break; + case TxIrq: + obj->serial.inten_msk = obj->serial.inten_msk | UART_INTEN_THREIEN_Msk; + UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); + break; } - } - else { // disable + } else { // disable switch (irq) { - case RxIrq: - UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); - obj->serial.inten_msk = obj->serial.inten_msk & ~(UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); - break; - case TxIrq: - UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); - obj->serial.inten_msk = obj->serial.inten_msk & ~UART_INTEN_THREIEN_Msk; - break; + case RxIrq: + UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); + obj->serial.inten_msk = obj->serial.inten_msk & ~(UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); + break; + case TxIrq: + UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk); + obj->serial.inten_msk = obj->serial.inten_msk & ~UART_INTEN_THREIEN_Msk; + break; } } } @@ -1124,9 +1125,9 @@ static void serial_rollback_interrupt(serial_t *obj, SerialIrq irq) const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->serial.uart); - + struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; - + obj->serial.vec = var->vec; serial_enable_interrupt(obj, irq, obj->serial.irq_en); } @@ -1140,8 +1141,7 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch) if (*dma_ch == DMA_ERROR_OUT_OF_CHANNELS) { *dma_usage = DMA_USAGE_NEVER; } - } - else { + } else { dma_channel_free(*dma_ch); *dma_ch = DMA_ERROR_OUT_OF_CHANNELS; } @@ -1150,16 +1150,16 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch) static int serial_is_irq_en(serial_t *obj, SerialIrq irq) { int inten_msk = 0; - + switch (irq) { - case RxIrq: - inten_msk = obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); - break; - case TxIrq: - inten_msk = obj->serial.inten_msk & UART_INTEN_THREIEN_Msk; - break; + case RxIrq: + inten_msk = obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk); + break; + case TxIrq: + inten_msk = obj->serial.inten_msk & UART_INTEN_THREIEN_Msk; + break; } - + return !! inten_msk; } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/sleep.c b/targets/TARGET_NUVOTON/TARGET_M480/sleep.c index fe0492f5f7..a6fde61172 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/sleep.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/sleep.c @@ -74,13 +74,12 @@ static void mbed_enter_sleep(struct sleep_s *obj) obj->powerdown = pwmout_allow_powerdown(); } // TODO: Check if other peripherals allow entering power-down mode - + if (obj->powerdown) { // Power-down mode (HIRC/HXT disabled, LIRC/LXT enabled) SYS_UnlockReg(); CLK_PowerDown(); SYS_LockReg(); - } - else { // CPU halt mode (HIRC/HXT enabled, LIRC/LXT enabled) + } else { // CPU halt mode (HIRC/HXT enabled, LIRC/LXT enabled) SYS_UnlockReg(); CLK_Idle(); SYS_LockReg(); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c b/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c index 603aed78a6..5075706f37 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c @@ -102,7 +102,8 @@ static const struct nu_modinit_s spi_modinit_tab[] = { {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { +void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ // Determine which SPI_x the pins are used for uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI); uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO); @@ -116,26 +117,26 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + // Reset this module SYS_ResetModule(modinit->rsetidx); - + // Select IP clock source CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); // Enable IP clock CLK_EnableModuleClock(modinit->clkidx); - + pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); pinmap_pinout(ssel, PinMap_SPI_SSEL); - + obj->spi.pin_mosi = mosi; obj->spi.pin_miso = miso; obj->spi.pin_sclk = sclk; obj->spi.pin_ssel = ssel; - + #if DEVICE_SPI_ASYNCH obj->spi.dma_usage = DMA_USAGE_NEVER; obj->spi.event = 0; @@ -162,17 +163,17 @@ void spi_free(spi_t *obj) #endif SPI_Close((SPI_T *) NU_MODBASE(obj->spi.spi)); - + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + SPI_DisableInt(((SPI_T *) NU_MODBASE(obj->spi.spi)), (SPI_FIFO_RXOV_INT_MASK | SPI_FIFO_RXTH_INT_MASK | SPI_FIFO_TXTH_INT_MASK)); NVIC_DisableIRQ(modinit->irq_n); - + // Disable IP clock CLK_DisableModuleClock(modinit->clkidx); - + // Mark this module to be deinited. int i = modinit - spi_modinit_tab; spi_modinit_mask &= ~(1 << i); @@ -180,33 +181,31 @@ void spi_free(spi_t *obj) void spi_format(spi_t *obj, int bits, int mode, int slave) { MBED_ASSERT(bits >= NU_SPI_FRAME_MIN && bits <= NU_SPI_FRAME_MAX); - + SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + // NOTE 1: All configurations should be ready before enabling SPI peripheral. // NOTE 2: Re-configuration is allowed only as SPI peripheral is idle. while (SPI_IS_BUSY(spi_base)); SPI_DISABLE(spi_base); SPI_Open(spi_base, - slave ? SPI_SLAVE : SPI_MASTER, - (mode == 0) ? SPI_MODE_0 : (mode == 1) ? SPI_MODE_1 : (mode == 2) ? SPI_MODE_2 : SPI_MODE_3, - bits, - SPI_GetBusClock(spi_base)); + slave ? SPI_SLAVE : SPI_MASTER, + (mode == 0) ? SPI_MODE_0 : (mode == 1) ? SPI_MODE_1 : (mode == 2) ? SPI_MODE_2 : SPI_MODE_3, + bits, + SPI_GetBusClock(spi_base)); // NOTE: Hardcode to be MSB first. SPI_SET_MSB_FIRST(spi_base); if (! slave) { // Master if (obj->spi.pin_ssel != NC) { - // Configure SS as low active. + // Configure SS as low active. SPI_EnableAutoSS(spi_base, SPI_SS, SPI_SS_ACTIVE_LOW); - } - else { + } else { SPI_DisableAutoSS(spi_base); } - } - else { + } else { // Slave // Configure SS as low active. spi_base->SSCTL &= ~SPI_SSCTL_SSACTPOL_Msk; @@ -219,7 +218,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) void spi_frequency(spi_t *obj, int hz) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + while (SPI_IS_BUSY(spi_base)); SPI_DISABLE(spi_base); @@ -230,10 +229,10 @@ void spi_frequency(spi_t *obj, int hz) int spi_master_write(spi_t *obj, int value) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + // NOTE: Data in receive FIFO can be read out via ICE. SPI_ENABLE(spi_base); - + // Wait for tx buffer empty while(! spi_writeable(obj)); SPI_WRITE_TX(spi_base, value); @@ -241,28 +240,43 @@ int spi_master_write(spi_t *obj, int value) // Wait for rx buffer full while (! spi_readable(obj)); int value2 = SPI_READ_RX(spi_base); - + SPI_DISABLE(spi_base); - + return value2; } +int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) +{ + int total = (tx_length > rx_length) ? tx_length : rx_length; + + for (int i = 0; i < total; i++) { + char out = (i < tx_length) ? tx_buffer[i] : 0xff; + char in = spi_master_write(obj, out); + if (i < rx_length) { + rx_buffer[i] = in; + } + } + + return total; +} + #if DEVICE_SPISLAVE int spi_slave_receive(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + SPI_ENABLE(spi_base); - + return spi_readable(obj); }; int spi_slave_read(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + SPI_ENABLE(spi_base); - + // Wait for rx buffer full while (! spi_readable(obj)); int value = SPI_READ_RX(spi_base); @@ -272,9 +286,9 @@ int spi_slave_read(spi_t *obj) void spi_slave_write(spi_t *obj, int value) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + SPI_ENABLE(spi_base); - + // Wait for tx buffer empty while(! spi_writeable(obj)); SPI_WRITE_TX(spi_base, value); @@ -294,20 +308,20 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, // (1) No DMA support for non-8 multiple data width. // (2) tx length >= rx length. Otherwise, as tx DMA is done, no bus activity for remaining rx. if ((data_width % 8) || - (tx_length < rx_length)) { + (tx_length < rx_length)) { obj->spi.dma_usage = DMA_USAGE_NEVER; dma_channel_free(obj->spi.dma_chn_id_tx); obj->spi.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS; dma_channel_free(obj->spi.dma_chn_id_rx); obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; } - + // SPI IRQ is necessary for both interrupt way and DMA way spi_enable_event(obj, event, 1); spi_buffer_set(obj, tx, tx_length, rx, rx_length); - + SPI_ENABLE(spi_base); - + if (obj->spi.dma_usage == DMA_USAGE_NEVER) { // Interrupt way spi_master_write_asynch(obj, spi_fifo_depth(obj) / 2); @@ -318,57 +332,57 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + PDMA_T *pdma_base = dma_modbase(); - + // Configure tx DMA pdma_base->CHCTL |= 1 << obj->spi.dma_chn_id_tx; // Enable this DMA channel PDMA_SetTransferMode(obj->spi.dma_chn_id_tx, - ((struct nu_spi_var *) modinit->var)->pdma_perp_tx, // Peripheral connected to this PDMA - 0, // Scatter-gather disabled - 0); // Scatter-gather descriptor address - PDMA_SetTransferCnt(obj->spi.dma_chn_id_tx, - (data_width == 8) ? PDMA_WIDTH_8 : (data_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, - tx_length); + ((struct nu_spi_var *) modinit->var)->pdma_perp_tx, // Peripheral connected to this PDMA + 0, // Scatter-gather disabled + 0); // Scatter-gather descriptor address + PDMA_SetTransferCnt(obj->spi.dma_chn_id_tx, + (data_width == 8) ? PDMA_WIDTH_8 : (data_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, + tx_length); PDMA_SetTransferAddr(obj->spi.dma_chn_id_tx, - (uint32_t) tx, // NOTE: - // NUC472: End of source address - // M451/M480: Start of source address - PDMA_SAR_INC, // Source address incremental - (uint32_t) &spi_base->TX, // Destination address - PDMA_DAR_FIX); // Destination address fixed - PDMA_SetBurstType(obj->spi.dma_chn_id_tx, - PDMA_REQ_SINGLE, // Single mode - 0); // Burst size + (uint32_t) tx, // NOTE: + // NUC472: End of source address + // M451/M480: Start of source address + PDMA_SAR_INC, // Source address incremental + (uint32_t) &spi_base->TX, // Destination address + PDMA_DAR_FIX); // Destination address fixed + PDMA_SetBurstType(obj->spi.dma_chn_id_tx, + PDMA_REQ_SINGLE, // Single mode + 0); // Burst size PDMA_EnableInt(obj->spi.dma_chn_id_tx, - PDMA_INT_TRANS_DONE); // Interrupt type + PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->spi.dma_chn_id_tx, (uint32_t) spi_dma_handler_tx, (uint32_t) obj, DMA_EVENT_ALL); - + // Configure rx DMA pdma_base->CHCTL |= 1 << obj->spi.dma_chn_id_rx; // Enable this DMA channel PDMA_SetTransferMode(obj->spi.dma_chn_id_rx, - ((struct nu_spi_var *) modinit->var)->pdma_perp_rx, // Peripheral connected to this PDMA - 0, // Scatter-gather disabled - 0); // Scatter-gather descriptor address - PDMA_SetTransferCnt(obj->spi.dma_chn_id_rx, - (data_width == 8) ? PDMA_WIDTH_8 : (data_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, - rx_length); + ((struct nu_spi_var *) modinit->var)->pdma_perp_rx, // Peripheral connected to this PDMA + 0, // Scatter-gather disabled + 0); // Scatter-gather descriptor address + PDMA_SetTransferCnt(obj->spi.dma_chn_id_rx, + (data_width == 8) ? PDMA_WIDTH_8 : (data_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32, + rx_length); PDMA_SetTransferAddr(obj->spi.dma_chn_id_rx, - (uint32_t) &spi_base->RX, // Source address - PDMA_SAR_FIX, // Source address fixed - (uint32_t) rx, // NOTE: - // NUC472: End of destination address - // M451/M480: Start of destination address - PDMA_DAR_INC); // Destination address incremental - PDMA_SetBurstType(obj->spi.dma_chn_id_rx, - PDMA_REQ_SINGLE, // Single mode - 0); // Burst size + (uint32_t) &spi_base->RX, // Source address + PDMA_SAR_FIX, // Source address fixed + (uint32_t) rx, // NOTE: + // NUC472: End of destination address + // M451/M480: Start of destination address + PDMA_DAR_INC); // Destination address incremental + PDMA_SetBurstType(obj->spi.dma_chn_id_rx, + PDMA_REQ_SINGLE, // Single mode + 0); // Burst size PDMA_EnableInt(obj->spi.dma_chn_id_rx, - PDMA_INT_TRANS_DONE); // Interrupt type + PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->spi.dma_chn_id_rx, (uint32_t) spi_dma_handler_rx, (uint32_t) obj, DMA_EVENT_ALL); - + // Start tx/rx DMA transfer spi_enable_vector_interrupt(obj, handler, 1); // NOTE: It is safer to start rx DMA first and then tx DMA. Otherwise, receive FIFO is subject to overflow by tx DMA. @@ -388,20 +402,20 @@ void spi_abort_asynch(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); PDMA_T *pdma_base = dma_modbase(); - + if (obj->spi.dma_usage != DMA_USAGE_NEVER) { // Receive FIFO Overrun in case of tx length > rx length on DMA way if (spi_base->STATUS & SPI_STATUS_RXOVIF_Msk) { spi_base->STATUS = SPI_STATUS_RXOVIF_Msk; } - + if (obj->spi.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->spi.dma_chn_id_tx, PDMA_INT_TRANS_DONE); // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. pdma_base->CHCTL &= ~(1 << obj->spi.dma_chn_id_tx); } SPI_DISABLE_TX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); - + if (obj->spi.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->spi.dma_chn_id_rx, PDMA_INT_TRANS_DONE); // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. @@ -409,7 +423,7 @@ void spi_abort_asynch(spi_t *obj) } SPI_DISABLE_RX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); } - + // Necessary for both interrupt way and DMA way spi_enable_vector_interrupt(obj, 0, 0); spi_master_enable_interrupt(obj, 0); @@ -417,7 +431,7 @@ void spi_abort_asynch(spi_t *obj) // NOTE: SPI H/W may get out of state without the busy check. while (SPI_IS_BUSY(spi_base)); SPI_DISABLE(spi_base); - + SPI_ClearRxFIFO(spi_base); SPI_ClearTxFIFO(spi_base); } @@ -462,7 +476,7 @@ int spi_allow_powerdown(void) } modinit_mask &= ~(1 << spi_idx); } - + return 1; } @@ -478,7 +492,7 @@ static int spi_readable(spi_t * obj) } static void spi_enable_event(spi_t *obj, uint32_t event, uint8_t enable) -{ +{ obj->spi.event &= ~SPI_EVENT_ALL; obj->spi.event |= (event & SPI_EVENT_ALL); if (event & SPI_EVENT_RX_OVERFLOW) { @@ -491,27 +505,25 @@ static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t en const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + if (enable) { NVIC_SetVector(modinit->irq_n, handler); NVIC_EnableIRQ(modinit->irq_n); - } - else { + } else { NVIC_DisableIRQ(modinit->irq_n); } } static void spi_master_enable_interrupt(spi_t *obj, uint8_t enable) -{ +{ SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + if (enable) { uint32_t fifo_depth = spi_fifo_depth(obj); SPI_SetFIFO(spi_base, fifo_depth / 2, fifo_depth / 2); // Enable tx/rx FIFO threshold interrupt SPI_EnableInt(spi_base, SPI_FIFO_RXTH_INT_MASK | SPI_FIFO_TXTH_INT_MASK); - } - else { + } else { SPI_DisableInt(spi_base, SPI_FIFO_RXTH_INT_MASK | SPI_FIFO_TXTH_INT_MASK); } } @@ -520,16 +532,16 @@ static uint32_t spi_event_check(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); uint32_t event = 0; - + if (obj->spi.dma_usage == DMA_USAGE_NEVER) { uint32_t n_rec = spi_master_read_asynch(obj); spi_master_write_asynch(obj, n_rec); } - + if (spi_is_tx_complete(obj) && spi_is_rx_complete(obj)) { event |= SPI_EVENT_COMPLETE; } - + // Receive FIFO Overrun if (spi_base->STATUS & SPI_STATUS_RXOVIF_Msk) { spi_base->STATUS = SPI_STATUS_RXOVIF_Msk; @@ -538,7 +550,7 @@ static uint32_t spi_event_check(spi_t *obj) event |= SPI_EVENT_RX_OVERFLOW; } } - + // Receive Time-Out if (spi_base->STATUS & SPI_STATUS_RXTOIF_Msk) { spi_base->STATUS = SPI_STATUS_RXTOIF_Msk; @@ -549,7 +561,7 @@ static uint32_t spi_event_check(spi_t *obj) spi_base->STATUS = SPI_STATUS_TXUFIF_Msk; event |= SPI_EVENT_ERROR; } - + return event; } @@ -571,33 +583,32 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit) uint8_t bytes_per_word = (data_width + 7) / 8; uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos; SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + while ((n_words < max_tx) && spi_writeable(obj)) { if (spi_is_tx_complete(obj)) { // Transmit dummy as transmit buffer is empty SPI_WRITE_TX(spi_base, 0); - } - else { + } else { switch (bytes_per_word) { - case 4: - SPI_WRITE_TX(spi_base, nu_get32_le(tx)); - tx += 4; - break; - case 2: - SPI_WRITE_TX(spi_base, nu_get16_le(tx)); - tx += 2; - break; - case 1: - SPI_WRITE_TX(spi_base, *((uint8_t *) tx)); - tx += 1; - break; + case 4: + SPI_WRITE_TX(spi_base, nu_get32_le(tx)); + tx += 4; + break; + case 2: + SPI_WRITE_TX(spi_base, nu_get16_le(tx)); + tx += 2; + break; + case 1: + SPI_WRITE_TX(spi_base, *((uint8_t *) tx)); + tx += 1; + break; } - + obj->tx_buff.pos ++; } n_words ++; } - + //Return the number of words that have been sent return n_words; } @@ -623,36 +634,35 @@ static uint32_t spi_master_read_asynch(spi_t *obj) uint8_t bytes_per_word = (data_width + 7) / 8; uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos; SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + while ((n_words < max_rx) && spi_readable(obj)) { if (spi_is_rx_complete(obj)) { // Disregard as receive buffer is full SPI_READ_RX(spi_base); - } - else { + } else { switch (bytes_per_word) { - case 4: { - uint32_t val = SPI_READ_RX(spi_base); - nu_set32_le(rx, val); - rx += 4; - break; - } - case 2: { - uint16_t val = SPI_READ_RX(spi_base); - nu_set16_le(rx, val); - rx += 2; - break; - } - case 1: - *rx ++ = SPI_READ_RX(spi_base); - break; + case 4: { + uint32_t val = SPI_READ_RX(spi_base); + nu_set32_le(rx, val); + rx += 4; + break; } - + case 2: { + uint16_t val = SPI_READ_RX(spi_base); + nu_set16_le(rx, val); + rx += 2; + break; + } + case 1: + *rx ++ = SPI_READ_RX(spi_base); + break; + } + obj->rx_buff.pos ++; } n_words ++; } - + // Return the number of words received return n_words; } @@ -678,12 +688,12 @@ static void spi_check_dma_usage(DMAUsage *dma_usage, int *dma_ch_tx, int *dma_ch if (*dma_ch_rx == DMA_ERROR_OUT_OF_CHANNELS) { *dma_ch_rx = dma_channel_allocate(DMA_CAP_NONE); } - + if (*dma_ch_tx == DMA_ERROR_OUT_OF_CHANNELS || *dma_ch_rx == DMA_ERROR_OUT_OF_CHANNELS) { *dma_usage = DMA_USAGE_NEVER; } } - + if (*dma_usage == DMA_USAGE_NEVER) { dma_channel_free(*dma_ch_tx); *dma_ch_tx = DMA_ERROR_OUT_OF_CHANNELS; @@ -695,12 +705,12 @@ static void spi_check_dma_usage(DMAUsage *dma_usage, int *dma_ch_tx, int *dma_ch static uint8_t spi_get_data_width(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + uint32_t data_width = ((spi_base->CTL & SPI_CTL_DWIDTH_Msk) >> SPI_CTL_DWIDTH_Pos); if (data_width == 0) { data_width = 32; } - + return data_width; } @@ -717,7 +727,7 @@ static int spi_is_rx_complete(spi_t *obj) static void spi_dma_handler_tx(uint32_t id, uint32_t event_dma) { spi_t *obj = (spi_t *) id; - + // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } @@ -728,11 +738,11 @@ static void spi_dma_handler_tx(uint32_t id, uint32_t event_dma) // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + void (*vec)(void) = (void (*)(void)) NVIC_GetVector(modinit->irq_n); vec(); } @@ -740,7 +750,7 @@ static void spi_dma_handler_tx(uint32_t id, uint32_t event_dma) static void spi_dma_handler_rx(uint32_t id, uint32_t event_dma) { spi_t *obj = (spi_t *) id; - + // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } @@ -751,11 +761,11 @@ static void spi_dma_handler_rx(uint32_t id, uint32_t event_dma) // FIXME: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->spi.spi); - + void (*vec)(void) = (void (*)(void)) NVIC_GetVector(modinit->irq_n); vec(); } @@ -770,11 +780,11 @@ static void spi_dma_handler_rx(uint32_t id, uint32_t event_dma) static uint32_t spi_fifo_depth(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + if (spi_base == SPI0) { return 8; } - + return (spi_get_data_width(obj) <= 16) ? 8 : 4; } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c index aa21e9ee86..781bb78cda 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c @@ -37,7 +37,7 @@ void CRYPTO_IRQHandler() g_AES_done = 1; AES_CLR_INT_FLAG(); } -} +} static void trng_get(unsigned char *pConversionData) { @@ -56,13 +56,13 @@ void trng_init(trng_t *obj) { (void)obj; /* Unlock protected registers */ - SYS_UnlockReg(); + SYS_UnlockReg(); /* Enable IP clock */ CLK_EnableModuleClock(CRPT_MODULE); - + /* Lock protected registers */ SYS_LockReg(); - + NVIC_EnableIRQ(CRPT_IRQn); PRNG_ENABLE_INT(); } @@ -94,6 +94,6 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l return 0; } - + #endif diff --git a/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c b/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c index fcd32f37f3..cfcad67cc3 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "us_ticker_api.h" #include "sleep_api.h" #include "mbed_assert.h" @@ -61,16 +61,16 @@ void us_ticker_init(void) if (us_ticker_inited) { return; } - + counter_major = 0; cd_major_minor_us = 0; cd_minor_us = 0; us_ticker_inited = 1; - + // Reset IP SYS_ResetModule(timer0hires_modinit.rsetidx); SYS_ResetModule(timer1hires_modinit.rsetidx); - + // Select IP clock source CLK_SetModuleClock(timer0hires_modinit.clkidx, timer0hires_modinit.clksrc, timer0hires_modinit.clkdiv); CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv); @@ -88,13 +88,13 @@ void us_ticker_init(void) // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. ((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer0/* | TIMER_CTL_CNTDATEN_Msk*/; ((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CMP = cmp_timer0; - + NVIC_SetVector(timer0hires_modinit.irq_n, (uint32_t) timer0hires_modinit.var); NVIC_SetVector(timer1hires_modinit.irq_n, (uint32_t) timer1hires_modinit.var); - + NVIC_EnableIRQ(timer0hires_modinit.irq_n); NVIC_EnableIRQ(timer1hires_modinit.irq_n); - + TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); TIMER_Start((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); } @@ -104,9 +104,9 @@ uint32_t us_ticker_read() if (! us_ticker_inited) { us_ticker_init(); } - + TIMER_T * timer0_base = (TIMER_T *) NU_MODBASE(timer0hires_modinit.modname); - + do { uint32_t major_minor_us; uint32_t minor_us; @@ -115,25 +115,22 @@ uint32_t us_ticker_read() // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { core_util_critical_section_enter(); - + // NOTE: Order of reading minor_us/carry here is significant. minor_us = TIMER_GetCounter(timer0_base) * US_PER_TMR0HIRES_CLK; uint32_t carry = (timer0_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Hanlde carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_us > (US_PER_TMR0HIRES_INT / 2)) { major_minor_us = (counter_major + 1) * US_PER_TMR0HIRES_INT; - } - else { + } else { major_minor_us = (counter_major + carry) * US_PER_TMR0HIRES_INT + minor_us; } - + core_util_critical_section_exit(); - } - while (minor_us == 0 || minor_us == US_PER_TMR0HIRES_INT); - + } while (minor_us == 0 || minor_us == US_PER_TMR0HIRES_INT); + return (major_minor_us / US_PER_TICK); - } - while (0); + } while (0); } void us_ticker_disable_interrupt(void) @@ -149,18 +146,17 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); - + int delta = (int) (timestamp - us_ticker_read()); if (delta > 0) { cd_major_minor_us = delta * US_PER_TICK; us_ticker_arm_cd(); - } - else { + } else { cd_major_minor_us = cd_minor_us = 0; /** * This event was in the past. Set the interrupt as pending, but don't process it here. * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ + */ NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); } } @@ -178,8 +174,7 @@ static void tmr1_vec(void) if (cd_major_minor_us == 0) { // NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler(); us_ticker_irq_handler(); - } - else { + } else { us_ticker_arm_cd(); } } @@ -187,7 +182,7 @@ static void tmr1_vec(void) static void us_ticker_arm_cd(void) { TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1hires_modinit.modname); - + cd_minor_us = cd_major_minor_us; // Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit @@ -195,7 +190,7 @@ static void us_ticker_arm_cd(void) // M480 timer1_base->CNT = 0; while (timer1_base->CNT & TIMER_CNT_RSTACT_Msk); - // One-shot mode, Clock = 1 MHz + // One-shot mode, Clock = 1 MHz uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); uint32_t prescale_timer1 = clk_timer1 / TMR1HIRES_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer1 != (uint32_t) -1) && prescale_timer1 <= 127); @@ -203,11 +198,11 @@ static void us_ticker_arm_cd(void) // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. timer1_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk/* | TIMER_CTL_CNTDATEN_Msk*/); timer1_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer1/* | TIMER_CTL_CNTDATEN_Msk*/; - + uint32_t cmp_timer1 = cd_minor_us / US_PER_TMR1HIRES_CLK; cmp_timer1 = NU_CLAMP(cmp_timer1, TMR_CMP_MIN, TMR_CMP_MAX); timer1_base->CMP = cmp_timer1; - + TIMER_EnableInt(timer1_base); TIMER_Start(timer1_base); }