mirror of https://github.com/ARMmbed/mbed-os.git
Refine coding style
parent
abd8dee9e5
commit
592f46b382
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue