Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Nucleo_F103RB_RTC_battery_bkup_pwr_off_okay
Fork of mbed-dev by
Diff: targets/TARGET_NUVOTON/TARGET_NUC472/serial_api.c
- Revision:
- 151:5eaa88a5bcc7
- Parent:
- 149:156823d33999
- Child:
- 153:fa9ff456f731
--- a/targets/TARGET_NUVOTON/TARGET_NUC472/serial_api.c Tue Nov 08 17:45:16 2016 +0000
+++ b/targets/TARGET_NUVOTON/TARGET_NUC472/serial_api.c Thu Nov 24 17:03:03 2016 +0000
@@ -31,6 +31,7 @@
#endif
struct nu_uart_var {
+ uint32_t ref_cnt; // Reference count of the H/W module
serial_t * obj;
uint32_t fifo_size_tx;
uint32_t fifo_size_rx;
@@ -84,6 +85,7 @@
#endif
static struct nu_uart_var uart0_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 64,
.fifo_size_rx = 64,
@@ -95,6 +97,7 @@
#endif
};
static struct nu_uart_var uart1_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 16,
.fifo_size_rx = 16,
@@ -106,6 +109,7 @@
#endif
};
static struct nu_uart_var uart2_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 16,
.fifo_size_rx = 16,
@@ -117,6 +121,7 @@
#endif
};
static struct nu_uart_var uart3_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 16,
.fifo_size_rx = 16,
@@ -128,6 +133,7 @@
#endif
};
static struct nu_uart_var uart4_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 16,
.fifo_size_rx = 16,
@@ -139,6 +145,7 @@
#endif
};
static struct nu_uart_var uart5_var = {
+ .ref_cnt = 0,
.obj = NULL,
.fifo_size_tx = 16,
.fifo_size_rx = 16,
@@ -170,7 +177,7 @@
void serial_init(serial_t *obj, PinName tx, PinName rx)
{
- // NOTE: serial_init() gets called from _sys_open() timing of which is before main()/mbed_sdk_init().
+ // 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
@@ -184,32 +191,31 @@
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == obj->serial.uart);
- // Reset this module
- SYS_ResetModule(modinit->rsetidx);
+ struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
- // Select IP clock source
- CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
- // Enable IP clock
- CLK_EnableModuleClock(modinit->clkidx);
+ if (! var->ref_cnt) {
+ // 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(tx, PinMap_UART_TX);
- pinmap_pinout(rx, PinMap_UART_RX);
- // FIXME: Why PullUp?
- //if (tx != NC) {
- // pin_mode(tx, PullUp);
- //}
- //if (rx != NC) {
- // pin_mode(rx, PullUp);
- //}
- obj->serial.pin_tx = tx;
- obj->serial.pin_rx = rx;
+ pinmap_pinout(tx, PinMap_UART_TX);
+ pinmap_pinout(rx, PinMap_UART_RX);
+
+ 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 = ((struct nu_uart_var *) modinit->var)->vec;
+ obj->serial.vec = var->vec;
#if DEVICE_SERIAL_ASYNCH
obj->serial.dma_usage_tx = DMA_USAGE_NEVER;
@@ -220,51 +226,61 @@
#endif
// For stdio management
- if (obj == &stdio_uart) {
+ if (obj->serial.uart == STDIO_UART) {
stdio_uart_inited = 1;
- /* NOTE: Not required anymore because stdio_uart will be manually initialized in mbed-drivers/source/retarget.cpp from mbed beta */
- //memcpy(&stdio_uart, obj, sizeof(serial_t));
+ memcpy(&stdio_uart, obj, sizeof(serial_t));
}
- // Mark this module to be inited.
- int i = modinit - uart_modinit_tab;
- uart_modinit_mask |= 1 << i;
+ if (var->ref_cnt) {
+ // Mark this module to be inited.
+ int i = modinit - uart_modinit_tab;
+ uart_modinit_mask |= 1 << i;
+ }
}
void serial_free(serial_t *obj)
{
-#if DEVICE_SERIAL_ASYNCH
- if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
- dma_channel_free(obj->serial.dma_chn_id_tx);
- obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
- }
- if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
- dma_channel_free(obj->serial.dma_chn_id_rx);
- obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
- }
-#endif
-
- UART_Close((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 == 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);
+ struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
- // Disable IP clock
- CLK_DisableModuleClock(modinit->clkidx);
+ var->ref_cnt --;
+ if (! var->ref_cnt) {
+#if DEVICE_SERIAL_ASYNCH
+ if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
+ dma_channel_free(obj->serial.dma_chn_id_tx);
+ obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
+ }
+ if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
+ dma_channel_free(obj->serial.dma_chn_id_rx);
+ obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
+ }
+#endif
+
+ UART_Close((UART_T *) NU_MODBASE(obj->serial.uart));
- ((struct nu_uart_var *) modinit->var)->obj = NULL;
+ 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);
- if (obj == &stdio_uart) {
+ // Disable IP clock
+ CLK_DisableModuleClock(modinit->clkidx);
+ }
+
+ if (var->obj == obj) {
+ var->obj = NULL;
+ }
+
+ if (obj->serial.uart == STDIO_UART) {
stdio_uart_inited = 0;
}
- // Mark this module to be deinited.
- int i = modinit - uart_modinit_tab;
- uart_modinit_mask &= ~(1 << i);
+ if (! var->ref_cnt) {
+ // Mark this module to be deinited.
+ int i = modinit - uart_modinit_tab;
+ uart_modinit_mask &= ~(1 << i);
+ }
}
void serial_baud(serial_t *obj, int baudrate) {
@@ -345,7 +361,6 @@
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == obj->serial.uart);
- ((struct nu_uart_var *) modinit->var)->obj = obj;
obj->serial.irq_handler = (uint32_t) handler;
obj->serial.irq_id = id;
@@ -363,6 +378,11 @@
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:
@@ -668,7 +688,7 @@
int event_rx = 0;
int event_tx = 0;
- // Necessary for both interrup way and DMA way
+ // Necessary for both interrupt way and DMA way
if (serial_is_irq_en(obj, RxIrq)) {
event_rx = serial_rx_event_check(obj);
if (event_rx) {
@@ -1040,9 +1060,9 @@
MBED_ASSERT(modinit->modname == obj->serial.uart);
// Necessary for both interrupt way and DMA way
- ((struct nu_uart_var *) modinit->var)->obj = obj;
+ struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
// With our own async vector, tx/rx handlers can be different.
- obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec_async;
+ obj->serial.vec = var->vec_async;
obj->serial.irq_handler_tx_async = (void (*)(void)) handler;
serial_irq_set(obj, TxIrq, enable);
}
@@ -1054,9 +1074,9 @@
MBED_ASSERT(modinit->modname == obj->serial.uart);
// Necessary for both interrupt way and DMA way
- ((struct nu_uart_var *) modinit->var)->obj = obj;
+ struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
// With our own async vector, tx/rx handlers can be different.
- obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec_async;
+ obj->serial.vec = var->vec_async;
obj->serial.irq_handler_rx_async = (void (*) (void)) handler;
serial_irq_set(obj, RxIrq, enable);
}
