Refine coding style

pull/4974/head
ccli8 2017-07-05 17:40:55 +08:00 committed by adbridge
parent abd8dee9e5
commit 592f46b382
18 changed files with 1037 additions and 1073 deletions

View File

@ -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;
}

View File

@ -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 <string.h>
#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 <string.h>
#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

View File

@ -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)) {

View File

@ -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 = {

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}