Merge pull request #11379 from OpenNuvoton/nuvoton_m263_fpga-ci

M263: Fix FPGA CI testing failing
pull/11410/head
Martin Kojtal 2019-09-04 14:06:19 +02:00 committed by GitHub
commit ea54f126a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 219 additions and 115 deletions

View File

@ -146,6 +146,7 @@ const PinMap PinMap_GPIO[] = {
{PH_9, GPIO_H, SYS_GPH_MFPH_PH9MFP_GPIO}, {PH_9, GPIO_H, SYS_GPH_MFPH_PH9MFP_GPIO},
{PH_10, GPIO_H, SYS_GPH_MFPH_PH10MFP_GPIO}, {PH_10, GPIO_H, SYS_GPH_MFPH_PH10MFP_GPIO},
{PH_11, GPIO_H, SYS_GPH_MFPH_PH11MFP_GPIO}, {PH_11, GPIO_H, SYS_GPH_MFPH_PH11MFP_GPIO},
{NC, NC, 0} {NC, NC, 0}
}; };
#endif #endif
@ -503,47 +504,24 @@ const PinMap PinMap_SPI_MISO[] = {
const PinMap PinMap_SPI_SCLK[] = { const PinMap PinMap_SPI_SCLK[] = {
{PA_2, SPI_0, SYS_GPA_MFPL_PA2MFP_SPI0_CLK}, {PA_2, SPI_0, SYS_GPA_MFPL_PA2MFP_SPI0_CLK},
{PA_4, SPI_0, SYS_GPA_MFPL_PA4MFP_SPI0_I2SMCLK},
{PA_5, SPI_1, SYS_GPA_MFPL_PA5MFP_SPI1_I2SMCLK},
{PA_7, SPI_1, SYS_GPA_MFPL_PA7MFP_SPI1_CLK}, {PA_7, SPI_1, SYS_GPA_MFPL_PA7MFP_SPI1_CLK},
{PA_10, SPI_2, SYS_GPA_MFPH_PA10MFP_SPI2_CLK}, {PA_10, SPI_2, SYS_GPA_MFPH_PA10MFP_SPI2_CLK},
{PA_13, SPI_2, SYS_GPA_MFPH_PA13MFP_SPI2_CLK}, {PA_13, SPI_2, SYS_GPA_MFPH_PA13MFP_SPI2_CLK},
{PB_0, SPI_0, SYS_GPB_MFPL_PB0MFP_SPI0_I2SMCLK},
{PB_1, SPI_1, SYS_GPB_MFPL_PB1MFP_SPI1_I2SMCLK},
{NU_PINNAME_BIND(PB_1, SPI_1), SPI_1, SYS_GPB_MFPL_PB1MFP_SPI1_I2SMCLK},
{PB_1, SPI_3, SYS_GPB_MFPL_PB1MFP_SPI3_I2SMCLK},
{NU_PINNAME_BIND(PB_1, SPI_3), SPI_3, SYS_GPB_MFPL_PB1MFP_SPI3_I2SMCLK},
{PB_3, SPI_1, SYS_GPB_MFPL_PB3MFP_SPI1_CLK}, {PB_3, SPI_1, SYS_GPB_MFPL_PB3MFP_SPI1_CLK},
{PB_11, SPI_0, SYS_GPB_MFPH_PB11MFP_SPI0_I2SMCLK},
{NU_PINNAME_BIND(PB_11, SPI_0), SPI_0, SYS_GPB_MFPH_PB11MFP_SPI0_I2SMCLK},
{PB_11, SPI_3, SYS_GPB_MFPH_PB11MFP_SPI3_CLK}, {PB_11, SPI_3, SYS_GPB_MFPH_PB11MFP_SPI3_CLK},
{NU_PINNAME_BIND(PB_11, SPI_3), SPI_3, SYS_GPB_MFPH_PB11MFP_SPI3_CLK}, {NU_PINNAME_BIND(PB_11, SPI_3), SPI_3, SYS_GPB_MFPH_PB11MFP_SPI3_CLK},
{PB_14, SPI_0, SYS_GPB_MFPH_PB14MFP_SPI0_CLK}, {PB_14, SPI_0, SYS_GPB_MFPH_PB14MFP_SPI0_CLK},
{PC_1, SPI_1, SYS_GPC_MFPL_PC1MFP_SPI1_CLK}, {PC_1, SPI_1, SYS_GPC_MFPL_PC1MFP_SPI1_CLK},
{PC_4, SPI_1, SYS_GPC_MFPL_PC4MFP_SPI1_I2SMCLK},
{PC_10, SPI_3, SYS_GPC_MFPH_PC10MFP_SPI3_CLK}, {PC_10, SPI_3, SYS_GPC_MFPH_PC10MFP_SPI3_CLK},
{PC_13, SPI_2, SYS_GPC_MFPH_PC13MFP_SPI2_I2SMCLK},
{PD_2, SPI_0, SYS_GPD_MFPL_PD2MFP_SPI0_CLK}, {PD_2, SPI_0, SYS_GPD_MFPL_PD2MFP_SPI0_CLK},
{PD_5, SPI_1, SYS_GPD_MFPL_PD5MFP_SPI1_CLK}, {PD_5, SPI_1, SYS_GPD_MFPL_PD5MFP_SPI1_CLK},
{PD_13, SPI_0, SYS_GPD_MFPH_PD13MFP_SPI0_I2SMCLK},
{NU_PINNAME_BIND(PD_13, SPI_0), SPI_0, SYS_GPD_MFPH_PD13MFP_SPI0_I2SMCLK},
{PD_13, SPI_1, SYS_GPD_MFPH_PD13MFP_SPI1_I2SMCLK},
{NU_PINNAME_BIND(PD_13, SPI_1), SPI_1, SYS_GPD_MFPH_PD13MFP_SPI1_I2SMCLK},
{PD_14, SPI_0, SYS_GPD_MFPH_PD14MFP_SPI0_I2SMCLK},
{NU_PINNAME_BIND(PD_14, SPI_0), SPI_0, SYS_GPD_MFPH_PD14MFP_SPI0_I2SMCLK},
{PD_14, SPI_3, SYS_GPD_MFPH_PD14MFP_SPI3_I2SMCLK},
{NU_PINNAME_BIND(PD_14, SPI_3), SPI_3, SYS_GPD_MFPH_PD14MFP_SPI3_I2SMCLK},
{PE_4, SPI_3, SYS_GPE_MFPL_PE4MFP_SPI3_CLK}, {PE_4, SPI_3, SYS_GPE_MFPL_PE4MFP_SPI3_CLK},
{NU_PINNAME_BIND(PE_4, SPI_3), SPI_3, SYS_GPE_MFPL_PE4MFP_SPI3_CLK}, {NU_PINNAME_BIND(PE_4, SPI_3), SPI_3, SYS_GPE_MFPL_PE4MFP_SPI3_CLK},
{PE_6, SPI_3, SYS_GPE_MFPL_PE6MFP_SPI3_I2SMCLK},
{PE_8, SPI_2, SYS_GPE_MFPH_PE8MFP_SPI2_CLK}, {PE_8, SPI_2, SYS_GPE_MFPH_PE8MFP_SPI2_CLK},
{PE_12, SPI_2, SYS_GPE_MFPH_PE12MFP_SPI2_I2SMCLK},
{PF_8, SPI_0, SYS_GPF_MFPH_PF8MFP_SPI0_CLK}, {PF_8, SPI_0, SYS_GPF_MFPH_PF8MFP_SPI0_CLK},
{PF_10, SPI_0, SYS_GPF_MFPH_PF10MFP_SPI0_I2SMCLK},
{PG_3, SPI_2, SYS_GPG_MFPL_PG3MFP_SPI2_CLK}, {PG_3, SPI_2, SYS_GPG_MFPL_PG3MFP_SPI2_CLK},
{PH_6, SPI_1, SYS_GPH_MFPL_PH6MFP_SPI1_CLK}, {PH_6, SPI_1, SYS_GPH_MFPL_PH6MFP_SPI1_CLK},
{PH_8, SPI_1, SYS_GPH_MFPH_PH8MFP_SPI1_CLK}, {PH_8, SPI_1, SYS_GPH_MFPH_PH8MFP_SPI1_CLK},
{PH_10, SPI_1, SYS_GPH_MFPH_PH10MFP_SPI1_I2SMCLK},
{NC, NC, 0} {NC, NC, 0}
}; };

View File

@ -135,6 +135,9 @@ typedef enum {
BUTTON1 = SW2, BUTTON1 = SW2,
BUTTON2 = SW3, BUTTON2 = SW3,
// Force PinName to 32-bit required by NU_PINNAME_BIND(...)
FORCE_ENUM_PINNAME_32BIT = 0x7FFFFFFF,
} PinName; } PinName;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -54,28 +54,30 @@ void analogin_init(analogin_t *obj, PinName pin)
MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->adc); MBED_ASSERT(modinit->modname == (int) obj->adc);
obj->pin = pin;
// Wire pinout
pinmap_pinout(pin, PinMap_ADC);
EADC_T *eadc_base = (EADC_T *) NU_MODBASE(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. // 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) { if (! eadc_modinit_mask) {
// Reset module
SYS_ResetModule(modinit->rsetidx);
// Select IP clock source // Select IP clock source
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
// Enable IP clock // Enable IP clock
CLK_EnableModuleClock(modinit->clkidx); CLK_EnableModuleClock(modinit->clkidx);
// Reset module
SYS_ResetModule(modinit->rsetidx);
// Set the ADC internal sampling time, input mode as single-end and enable the A/D converter // 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); EADC_Open(eadc_base, EADC_CTL_DIFFEN_SINGLE_END);
} }
uint32_t chn = NU_MODSUBINDEX(obj->adc); 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 // Configure the sample module Nmod for analog input channel Nch and software trigger source
EADC_ConfigSampleModule(eadc_base, chn, EADC_SOFTWARE_TRIGGER, chn); EADC_ConfigSampleModule(eadc_base, chn, EADC_SOFTWARE_TRIGGER, chn);

View File

@ -53,6 +53,11 @@ void analogout_init(dac_t *obj, PinName pin)
uint32_t chn = NU_MODSUBINDEX(obj->dac); uint32_t chn = NU_MODSUBINDEX(obj->dac);
MBED_ASSERT(chn < NU_DACCHN_MAXNUM); MBED_ASSERT(chn < NU_DACCHN_MAXNUM);
obj->pin = pin;
/* Wire pinout */
pinmap_pinout(pin, PinMap_DAC);
DAC_T *dac_base = (DAC_T *) NU_MODBASE(obj->dac); DAC_T *dac_base = (DAC_T *) NU_MODBASE(obj->dac);
/* Module-level setup from here */ /* Module-level setup from here */
@ -66,15 +71,15 @@ void analogout_init(dac_t *obj, PinName pin)
* channels are deactivated. * channels are deactivated.
*/ */
if ((! dac_modinit_mask[0]) && (! dac_modinit_mask[1])) { if ((! dac_modinit_mask[0]) && (! dac_modinit_mask[1])) {
// Reset IP
SYS_ResetModule(modinit->rsetidx);
// Select IP clock source and clock divider // Select IP clock source and clock divider
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
// Enable IP clock // Enable IP clock
CLK_EnableModuleClock(modinit->clkidx); CLK_EnableModuleClock(modinit->clkidx);
// Reset IP
SYS_ResetModule(modinit->rsetidx);
/* The conversion settling time is 8us when 12-bit input code transition from /* The conversion settling time is 8us when 12-bit input code transition from
* lowest code (0x000) to highest code (0xFFF). */ * lowest code (0x000) to highest code (0xFFF). */
DAC_SetDelayTime(dac_base, 8); DAC_SetDelayTime(dac_base, 8);
@ -89,9 +94,6 @@ void analogout_init(dac_t *obj, PinName pin)
/* Set the software trigger, enable DAC event trigger mode and enable D/A converter */ /* Set the software trigger, enable DAC event trigger mode and enable D/A converter */
DAC_Open(dac_base, chn, DAC_SOFTWARE_TRIGGER); DAC_Open(dac_base, chn, DAC_SOFTWARE_TRIGGER);
/* Wire pinout */
pinmap_pinout(pin, PinMap_DAC);
/* Mark channel allocated */ /* Mark channel allocated */
dac_modinit_mask[modidx] |= 1 << chn; dac_modinit_mask[modidx] |= 1 << chn;
} }
@ -128,6 +130,10 @@ void analogout_free(dac_t *obj)
// Disable IP clock // Disable IP clock
CLK_DisableModuleClock(modinit->clkidx); CLK_DisableModuleClock(modinit->clkidx);
} }
// Free up pins
gpio_set(obj->pin);
obj->pin = NC;
} }
void analogout_write(dac_t *obj, float value) void analogout_write(dac_t *obj, float value)

View File

@ -54,12 +54,12 @@ void dma_init(void)
dma_chn_mask = ~NU_PDMA_CH_Msk; dma_chn_mask = ~NU_PDMA_CH_Msk;
memset(dma_chn_arr, 0x00, sizeof (dma_chn_arr)); memset(dma_chn_arr, 0x00, sizeof (dma_chn_arr));
// Reset module
SYS_ResetModule(dma_modinit.rsetidx);
// Enable IP clock // Enable IP clock
CLK_EnableModuleClock(dma_modinit.clkidx); CLK_EnableModuleClock(dma_modinit.clkidx);
// Reset module
SYS_ResetModule(dma_modinit.rsetidx);
/* Check PDMA0. */ /* Check PDMA0. */
PDMA_T *pdma_base = dma_modbase(); PDMA_T *pdma_base = dma_modbase();
if (((uint32_t) pdma_base) != PDMA0_BASE) { if (((uint32_t) pdma_base) != PDMA0_BASE) {

View File

@ -63,10 +63,23 @@ void gpio_mode(gpio_t *obj, PinMode mode)
return; return;
} }
uint32_t pin_index = NU_PININDEX(obj->pin);
uint32_t port_index = NU_PINPORT(obj->pin);
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
switch (mode) { switch (mode) {
case PullNone: case PullNone:
if (mode == PullNone) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_DISABLE);
}
case PullDown: case PullDown:
if (mode == PullDown) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_PULL_DOWN);
}
case PullUp: case PullUp:
if (mode == PullUp) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_PULL_UP);
}
/* H/W doesn't support separate configuration for input pull mode/direction. /* H/W doesn't support separate configuration for input pull mode/direction.
* We translate to input-only/push-pull output I/O mode dependent on direction. */ * We translate to input-only/push-pull output I/O mode dependent on direction. */
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput; obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
@ -111,10 +124,23 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
obj->direction = direction; obj->direction = direction;
uint32_t pin_index = NU_PININDEX(obj->pin);
uint32_t port_index = NU_PINPORT(obj->pin);
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
switch (obj->mode) { switch (obj->mode) {
case PullNone: case PullNone:
if (obj->mode == PullNone) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_DISABLE);
}
case PullDown: case PullDown:
if (obj->mode == PullDown) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_PULL_DOWN);
}
case PullUp: case PullUp:
if (obj->mode == PullUp) {
GPIO_SetPullCtl(gpio_base, 1 << pin_index, GPIO_PUSEL_PULL_UP);
}
/* H/W doesn't support separate configuration for input pull mode/direction. /* H/W doesn't support separate configuration for input pull mode/direction.
* We translate to input-only/push-pull output I/O mode dependent on direction. */ * We translate to input-only/push-pull output I/O mode dependent on direction. */
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput; obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;

View File

@ -86,9 +86,10 @@ static void i2c_enable_vector_interrupt(i2c_t *obj, uint32_t handler, int enable
static void i2c_rollback_vector_interrupt(i2c_t *obj); static void i2c_rollback_vector_interrupt(i2c_t *obj);
#endif #endif
#define TRANCTRL_STARTED (1) #define TRANCTRL_STARTED (1) // Guard I2C ISR from data transfer prematurely
#define TRANCTRL_NAKLASTDATA (1 << 1) #define TRANCTRL_NAKLASTDATA (1 << 1) // Request NACK on last data
#define TRANCTRL_LASTDATANAKED (1 << 2) #define TRANCTRL_LASTDATANAKED (1 << 2) // Last data NACKed
#define TRANCTRL_RECVDATA (1 << 3) // Receive data available
uint32_t us_ticker_read(void); uint32_t us_ticker_read(void);
@ -103,14 +104,17 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c); MBED_ASSERT(modinit->modname == (int) obj->i2c.i2c);
// Reset module obj->i2c.pin_sda = sda;
SYS_ResetModule(modinit->rsetidx); obj->i2c.pin_scl = scl;
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
// Select IP clock source // Select IP clock source
CLK_EnableModuleClock(modinit->clkidx); CLK_EnableModuleClock(modinit->clkidx);
pinmap_pinout(sda, PinMap_I2C_SDA); // Reset module
pinmap_pinout(scl, PinMap_I2C_SCL); SYS_ResetModule(modinit->rsetidx);
#if DEVICE_I2C_ASYNCH #if DEVICE_I2C_ASYNCH
obj->i2c.dma_usage = DMA_USAGE_NEVER; obj->i2c.dma_usage = DMA_USAGE_NEVER;
@ -592,11 +596,17 @@ static void i2c_irq(i2c_t *obj)
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
if (obj->i2c.tran_pos < obj->i2c.tran_end) { if (obj->i2c.tran_pos < obj->i2c.tran_end) {
if (status == 0x50 || status == 0x58) { if (status == 0x50 || status == 0x58) {
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
}
} }
if (status == 0x58) { if (status == 0x58) {
i2c_fsm_tranfini(obj, 1); i2c_fsm_tranfini(obj, 1);
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
i2c_disable_int(obj);
} else { } else {
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@ -605,6 +615,7 @@ static void i2c_irq(i2c_t *obj)
i2c_ctl &= ~I2C_CTL0_AA_Msk; i2c_ctl &= ~I2C_CTL0_AA_Msk;
} }
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
} }
} else { } else {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@ -659,12 +670,18 @@ static void i2c_irq(i2c_t *obj)
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
if (obj->i2c.tran_pos < obj->i2c.tran_end) { if (obj->i2c.tran_pos < obj->i2c.tran_end) {
if (status == 0x80 || status == 0x88) { if (status == 0x80 || status == 0x88) {
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
}
} }
if (status == 0x88) { if (status == 0x88) {
obj->i2c.slaveaddr_state = NoData; obj->i2c.slaveaddr_state = NoData;
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
i2c_disable_int(obj);
} else { } else {
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@ -673,6 +690,7 @@ static void i2c_irq(i2c_t *obj)
i2c_ctl &= ~I2C_CTL0_AA_Msk; i2c_ctl &= ~I2C_CTL0_AA_Msk;
} }
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
} }
} else { } else {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
@ -695,12 +713,18 @@ static void i2c_irq(i2c_t *obj)
if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) { if ((obj->i2c.tran_ctrl & TRANCTRL_STARTED) && obj->i2c.tran_pos) {
if (obj->i2c.tran_pos < obj->i2c.tran_end) { if (obj->i2c.tran_pos < obj->i2c.tran_end) {
if (status == 0x90 || status == 0x98) { if (status == 0x90 || status == 0x98) {
if (obj->i2c.tran_ctrl & TRANCTRL_RECVDATA) {
*obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base); *obj->i2c.tran_pos ++ = I2C_GET_DATA(i2c_base);
obj->i2c.tran_ctrl &= ~TRANCTRL_RECVDATA;
}
} }
if (status == 0x98) { if (status == 0x98) {
obj->i2c.slaveaddr_state = NoData; obj->i2c.slaveaddr_state = NoData;
i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk); i2c_fsm_reset(obj, I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk);
} else if (obj->i2c.tran_pos == obj->i2c.tran_end) {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;
i2c_disable_int(obj);
} else { } else {
uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk; uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk;
if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 && if ((obj->i2c.tran_end - obj->i2c.tran_pos) == 1 &&
@ -709,6 +733,7 @@ static void i2c_irq(i2c_t *obj)
i2c_ctl &= ~I2C_CTL0_AA_Msk; i2c_ctl &= ~I2C_CTL0_AA_Msk;
} }
I2C_SET_CONTROL_REG(i2c_base, i2c_ctl); I2C_SET_CONTROL_REG(i2c_base, i2c_ctl);
obj->i2c.tran_ctrl |= TRANCTRL_RECVDATA;
} }
} else { } else {
obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED;

View File

@ -82,12 +82,6 @@ void lp_ticker_init(void)
} }
ticker_inited = 1; ticker_inited = 1;
/* Reset module
*
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
*/
SYS_ResetModule(TIMER_MODINIT.rsetidx);
/* Select IP clock source /* Select IP clock source
* *
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure. * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
@ -100,6 +94,12 @@ void lp_ticker_init(void)
*/ */
CLK_EnableModuleClock(TIMER_MODINIT.clkidx); CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
/* Reset module
*
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
*/
SYS_ResetModule(TIMER_MODINIT.rsetidx);
TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
// Configure clock // Configure clock

View File

@ -43,14 +43,20 @@ struct port_s {
struct analogin_s { struct analogin_s {
ADCName adc; ADCName adc;
PinName pin;
}; };
struct dac_s { struct dac_s {
DACName dac; DACName dac;
PinName pin;
}; };
struct serial_s { struct serial_s {
UARTName uart; UARTName uart;
PinName pin_tx;
PinName pin_rx;
PinName pin_rts;
PinName pin_cts;
uint32_t baudrate; uint32_t baudrate;
uint32_t databits; uint32_t databits;
@ -85,11 +91,13 @@ struct spi_s {
int dma_chn_id_tx; int dma_chn_id_tx;
int dma_chn_id_rx; int dma_chn_id_rx;
uint32_t event; uint32_t event;
uint32_t hdlr_async; uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
}; };
struct i2c_s { struct i2c_s {
I2CName i2c; I2CName i2c;
PinName pin_sda;
PinName pin_scl;
int slaveaddr_state; int slaveaddr_state;
uint32_t tran_ctrl; uint32_t tran_ctrl;
@ -108,6 +116,7 @@ struct i2c_s {
struct pwmout_s { struct pwmout_s {
PWMName pwm; PWMName pwm;
PinName pin;
uint32_t period_us; uint32_t period_us;
uint32_t pulsewidth_us; uint32_t pulsewidth_us;
}; };

View File

@ -18,6 +18,7 @@
#include "mbed_assert.h" #include "mbed_assert.h"
#include "pinmap.h" #include "pinmap.h"
#include "PortNames.h" #include "PortNames.h"
#include "PeripheralNames.h"
#include "mbed_error.h" #include "mbed_error.h"
/** /**
@ -83,3 +84,17 @@ void pin_mode(PinName pin, PinMode mode)
*/ */
} }
/* List of peripherals excluded from testing */
const PeripheralList *pinmap_restricted_peripherals()
{
static const int perifs[] = {
STDIO_UART // Dedicated to USB VCOM
};
static const PeripheralList peripheral_list = {
sizeof(perifs) / sizeof(perifs[0]),
perifs
};
return &peripheral_list;
}

View File

@ -69,11 +69,10 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->pwm); MBED_ASSERT(modinit->modname == (int) obj->pwm);
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module. obj->pin = pin;
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled // Wire pinout
SYS_ResetModule(modinit->rsetidx); pinmap_pinout(pin, PinMap_PWM);
}
uint32_t chn = NU_MODSUBINDEX(obj->pwm); uint32_t chn = NU_MODSUBINDEX(obj->pwm);
@ -85,8 +84,11 @@ void pwmout_init(pwmout_t* obj, PinName pin)
CLK_EnableModuleClock(modinit->clkidx); CLK_EnableModuleClock(modinit->clkidx);
} }
// Wire pinout // NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
pinmap_pinout(pin, PinMap_PWM); if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
// Default: period = 10 ms, pulse width = 0 ms // Default: period = 10 ms, pulse width = 0 ms
obj->period_us = 1000 * 10; obj->period_us = 1000 * 10;
@ -119,6 +121,10 @@ void pwmout_free(pwmout_t* obj)
// Mark this module to be deinited. // Mark this module to be deinited.
int i = modinit - pwm_modinit_tab; int i = modinit - pwm_modinit_tab;
pwm_modinit_mask &= ~(1 << i); pwm_modinit_mask &= ~(1 << i);
// Free up pins
gpio_set(obj->pin);
obj->pin = NC;
} }
void pwmout_write(pwmout_t* obj, float value) void pwmout_write(pwmout_t* obj, float value)

View File

@ -86,9 +86,10 @@ static void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable);
static int serial_is_rx_complete(serial_t *obj); static int serial_is_rx_complete(serial_t *obj);
static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch); static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif #endif
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
bool serial_can_deep_sleep(void); bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = { static struct nu_uart_var uart0_var = {
@ -200,17 +201,22 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var; struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
if (! var->ref_cnt) { obj->serial.pin_tx = tx;
// Reset this module obj->serial.pin_rx = rx;
SYS_ResetModule(modinit->rsetidx); obj->serial.pin_rts = NC;
obj->serial.pin_cts = NC;
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
if (! var->ref_cnt) {
// Select IP clock source // Select IP clock source
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
// Enable IP clock // Enable IP clock
CLK_EnableModuleClock(modinit->clkidx); CLK_EnableModuleClock(modinit->clkidx);
pinmap_pinout(tx, PinMap_UART_TX); // Reset this module
pinmap_pinout(rx, PinMap_UART_RX); SYS_ResetModule(modinit->rsetidx);
// Configure baudrate // Configure baudrate
int baudrate = 9600; int baudrate = 9600;
@ -303,6 +309,16 @@ void serial_free(serial_t *obj)
int i = modinit - uart_modinit_tab; int i = modinit - uart_modinit_tab;
uart_modinit_mask &= ~(1 << i); uart_modinit_mask &= ~(1 << i);
} }
// Free up pins
gpio_set(obj->serial.pin_tx);
gpio_set(obj->serial.pin_rx);
gpio_set(obj->serial.pin_rts);
gpio_set(obj->serial.pin_cts);
obj->serial.pin_tx = NC;
obj->serial.pin_rx = NC;
obj->serial.pin_rts = NC;
obj->serial.pin_cts = NC;
} }
void serial_baud(serial_t *obj, int baudrate) void serial_baud(serial_t *obj, int baudrate)
@ -349,6 +365,16 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
{ {
UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart); UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
// Free up old rts/cts pins when they are different from new ones
if (obj->serial.pin_rts != rxflow) {
gpio_set(obj->serial.pin_rts);
obj->serial.pin_rts = rxflow;
}
if (obj->serial.pin_cts != txflow) {
gpio_set(obj->serial.pin_cts);
obj->serial.pin_cts = txflow;
}
if (rxflow != NC) { if (rxflow != NC) {
// Check if RTS pin matches. // Check if RTS pin matches.
uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS); uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
@ -519,7 +545,8 @@ static void uart_irq(serial_t *obj)
if (uart_base->INTSTS & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) { 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. // 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)); UART_DISABLE_INT(uart_base, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
if (obj->serial.irq_handler) { if (obj->serial.irq_handler && serial_is_irq_en(obj, RxIrq)) {
// Call irq_handler() only when RxIrq is enabled
((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, RxIrq); ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, RxIrq);
} }
} }
@ -527,7 +554,8 @@ static void uart_irq(serial_t *obj)
if (uart_base->INTSTS & UART_INTSTS_THREINT_Msk) { 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. // 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); UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
if (obj->serial.irq_handler) { if (obj->serial.irq_handler && serial_is_irq_en(obj, TxIrq)) {
// Call irq_handler() only when TxIrq is enabled
((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, TxIrq); ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, TxIrq);
} }
} }
@ -1167,6 +1195,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch)
} }
} }
#endif // #if DEVICE_SERIAL_ASYNCH
static int serial_is_irq_en(serial_t *obj, SerialIrq irq) static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
{ {
int inten_msk = 0; int inten_msk = 0;
@ -1183,8 +1213,6 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
return !! inten_msk; return !! inten_msk;
} }
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void) bool serial_can_deep_sleep(void)
{ {
bool sleep_allowed = 1; bool sleep_allowed = 1;

View File

@ -141,24 +141,23 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->spi.spi); MBED_ASSERT(modinit->modname == (int) obj->spi.spi);
// Reset this module obj->spi.pin_mosi = mosi;
SYS_ResetModule(modinit->rsetidx); obj->spi.pin_miso = miso;
obj->spi.pin_sclk = sclk;
// Select IP clock source obj->spi.pin_ssel = ssel;
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
// Enable IP clock
CLK_EnableModuleClock(modinit->clkidx);
pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK); pinmap_pinout(sclk, PinMap_SPI_SCLK);
pinmap_pinout(ssel, PinMap_SPI_SSEL); pinmap_pinout(ssel, PinMap_SPI_SSEL);
obj->spi.pin_mosi = mosi; // Select IP clock source
obj->spi.pin_miso = miso; CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
obj->spi.pin_sclk = sclk; // Enable IP clock
obj->spi.pin_ssel = ssel; CLK_EnableModuleClock(modinit->clkidx);
// Reset this module
SYS_ResetModule(modinit->rsetidx);
#if DEVICE_SPI_ASYNCH #if DEVICE_SPI_ASYNCH
obj->spi.dma_usage = DMA_USAGE_NEVER; obj->spi.dma_usage = DMA_USAGE_NEVER;
@ -205,6 +204,16 @@ void spi_free(spi_t *obj)
// Mark this module to be deinited. // Mark this module to be deinited.
int i = modinit - spi_modinit_tab; int i = modinit - spi_modinit_tab;
spi_modinit_mask &= ~(1 << i); spi_modinit_mask &= ~(1 << i);
// Free up pins
gpio_set(obj->spi.pin_mosi);
gpio_set(obj->spi.pin_miso);
gpio_set(obj->spi.pin_sclk);
gpio_set(obj->spi.pin_ssel);
obj->spi.pin_mosi = NC;
obj->spi.pin_miso = NC;
obj->spi.pin_sclk = NC;
obj->spi.pin_ssel = NC;
} }
void spi_format(spi_t *obj, int bits, int mode, int slave) void spi_format(spi_t *obj, int bits, int mode, int slave)
@ -388,6 +397,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base); SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) { if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way // Interrupt way
spi_master_write_asynch(obj, spi_fifo_depth(obj) / 2); spi_master_write_asynch(obj, spi_fifo_depth(obj) / 2);
@ -658,16 +670,12 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit) static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{ {
uint32_t n_words = 0; uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj); uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8; 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; 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); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_tx) && spi_writeable(obj)) { while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) { if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty // Transmit dummy as transmit buffer is empty
SPI_WRITE_TX(spi_base, 0); SPI_WRITE_TX(spi_base, 0);
@ -690,6 +698,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++; obj->tx_buff.pos ++;
} }
n_words ++; n_words ++;
obj->spi.txrx_rmn --;
} }
//Return the number of words that have been sent //Return the number of words that have been sent
@ -710,15 +719,12 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj) static uint32_t spi_master_read_asynch(spi_t *obj)
{ {
uint32_t n_words = 0; uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj); uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8; 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; 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); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_rx) && spi_readable(obj)) { while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) { if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full // Disregard as receive buffer is full
SPI_READ_RX(spi_base); SPI_READ_RX(spi_base);

View File

@ -57,15 +57,15 @@ void us_ticker_init(void)
} }
ticker_inited = 1; ticker_inited = 1;
// Reset IP
SYS_ResetModule(TIMER_MODINIT.rsetidx);
// Select IP clock source // Select IP clock source
CLK_SetModuleClock(TIMER_MODINIT.clkidx, TIMER_MODINIT.clksrc, TIMER_MODINIT.clkdiv); CLK_SetModuleClock(TIMER_MODINIT.clkidx, TIMER_MODINIT.clksrc, TIMER_MODINIT.clkdiv);
// Enable IP clock // Enable IP clock
CLK_EnableModuleClock(TIMER_MODINIT.clkidx); CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
// Reset IP
SYS_ResetModule(TIMER_MODINIT.rsetidx);
TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
// Timer for normal counter // Timer for normal counter