Skip to content

Commit 67e03ee

Browse files
authored
Merge pull request #3211 from OpenNuvoton/nuvoton
[NUC472/M453] Support single UART shared by multiple serial objects and other updates
2 parents a553b23 + 4ae76be commit 67e03ee

File tree

13 files changed

+158
-199
lines changed

13 files changed

+158
-199
lines changed

targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/device.h

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,8 @@
1717
#ifndef MBED_DEVICE_H
1818
#define MBED_DEVICE_H
1919

20-
#define DEVICE_PORTIN 1
21-
#define DEVICE_PORTOUT 1
22-
#define DEVICE_PORTINOUT 1
23-
24-
#define DEVICE_INTERRUPTIN 1
25-
26-
#define DEVICE_ANALOGIN 1
27-
#define DEVICE_ANALOGOUT 0
28-
29-
#define DEVICE_SERIAL 1
30-
#define DEVICE_SERIAL_FC 1
31-
#define DEVICE_SERIAL_ASYNCH 1
32-
33-
#define DEVICE_I2C 1
34-
#define DEVICE_I2CSLAVE 1
35-
#define DEVICE_I2C_ASYNCH 1
36-
37-
#define DEVICE_SPI 1
38-
#define DEVICE_SPI_ASYNCH 1
39-
#define DEVICE_SPISLAVE 1
40-
41-
#define DEVICE_RTC 1
42-
43-
#define DEVICE_ETHERNET 0
44-
45-
#define DEVICE_PWMOUT 1
46-
47-
#define DEVICE_SEMIHOST 0
48-
#define DEVICE_LOCALFILESYSTEM 0
4920
#define DEVICE_ID_LENGTH 24
5021

51-
#define DEVICE_SLEEP 1
52-
53-
#define DEVICE_DEBUG_AWARENESS 0
54-
55-
#define DEVICE_STDIO_MESSAGES 1
56-
57-
#define DEVICE_ERROR_RED 0
58-
59-
#define DEVICE_LOWPOWERTIMER 1
60-
6122
#include "objects.h"
6223

6324
#endif

targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_ARM_MICRO/M453.sct

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ LR_IROM1 0x00000000 {
1010
; uvisor-lib.a (+RW +ZI)
1111
;}
1212

13-
ARM_LIB_STACK 0x20000000 EMPTY 0x1000 {
13+
ARM_LIB_STACK 0x20000000 EMPTY 0x800 {
1414
}
1515

16-
ER_IRAMVEC 0x20001000 EMPTY (4*(16 + 64)) { ; Reserve for vectors
16+
ER_IRAMVEC 0x20000800 EMPTY (4*(16 + 64)) { ; Reserve for vectors
1717
}
1818

1919
RW_IRAM1 AlignExpr(+0, 16) { ; 16 byte-aligned

targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_ARM_STD/M453.sct

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ LR_IROM1 0x00000000 {
1010
; uvisor-lib.a (+RW +ZI)
1111
;}
1212

13-
ARM_LIB_STACK 0x20000000 EMPTY 0x1000 {
13+
ARM_LIB_STACK 0x20000000 EMPTY 0x800 {
1414
}
1515

16-
ER_IRAMVEC 0x20001000 EMPTY (4*(16 + 64)) { ; Reserve for vectors
16+
ER_IRAMVEC 0x20000800 EMPTY (4*(16 + 64)) { ; Reserve for vectors
1717
}
1818

1919
RW_IRAM1 AlignExpr(+0, 16) { ; 16 byte-aligned

targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_GCC_ARM/M453.ld

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Nuvoton M453 GCC linker script file
33
*/
44

5-
StackSize = 0x1000;
5+
StackSize = 0x800;
66

77
MEMORY
88
{

targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_IAR/M453.icf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ define symbol __ICFEDIT_region_ROM_end__ = 0x00040000;
99
define symbol __ICFEDIT_region_IRAM_start__ = 0x20000000;
1010
define symbol __ICFEDIT_region_IRAM_end__ = 0x20008000;
1111
/*-Sizes-*/
12-
define symbol __ICFEDIT_size_cstack__ = 0x1000;
12+
define symbol __ICFEDIT_size_cstack__ = 0x800;
1313
define symbol __ICFEDIT_size_heap__ = 0x4000;
1414
/**** End of ICF editor section. ###ICF###*/
1515

targets/TARGET_NUVOTON/TARGET_M451/serial_api.c

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#endif
3232

3333
struct nu_uart_var {
34+
uint32_t ref_cnt; // Reference count of the H/W module
3435
serial_t * obj;
3536
uint32_t fifo_size_tx;
3637
uint32_t fifo_size_rx;
@@ -80,6 +81,7 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
8081
#endif
8182

8283
static struct nu_uart_var uart0_var = {
84+
.ref_cnt = 0,
8385
.obj = NULL,
8486
.fifo_size_tx = 16,
8587
.fifo_size_rx = 16,
@@ -91,6 +93,7 @@ static struct nu_uart_var uart0_var = {
9193
#endif
9294
};
9395
static struct nu_uart_var uart1_var = {
96+
.ref_cnt = 0,
9497
.obj = NULL,
9598
.fifo_size_tx = 16,
9699
.fifo_size_rx = 16,
@@ -102,6 +105,7 @@ static struct nu_uart_var uart1_var = {
102105
#endif
103106
};
104107
static struct nu_uart_var uart2_var = {
108+
.ref_cnt = 0,
105109
.obj = NULL,
106110
.fifo_size_tx = 16,
107111
.fifo_size_rx = 16,
@@ -113,6 +117,7 @@ static struct nu_uart_var uart2_var = {
113117
#endif
114118
};
115119
static struct nu_uart_var uart3_var = {
120+
.ref_cnt = 0,
116121
.obj = NULL,
117122
.fifo_size_tx = 16,
118123
.fifo_size_rx = 16,
@@ -142,7 +147,7 @@ extern void mbed_sdk_init(void);
142147

143148
void serial_init(serial_t *obj, PinName tx, PinName rx)
144149
{
145-
// NOTE: serial_init() gets called from _sys_open() timing of which is before main()/mbed_hal_init().
150+
// NOTE: With armcc, serial_init() gets called from _sys_open() timing of which is before main()/mbed_sdk_init().
146151
mbed_sdk_init();
147152

148153
// Determine which UART_x the pins are used for
@@ -156,32 +161,31 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
156161
MBED_ASSERT(modinit != NULL);
157162
MBED_ASSERT(modinit->modname == obj->serial.uart);
158163

159-
// Reset this module
160-
SYS_ResetModule(modinit->rsetidx);
164+
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
161165

162-
// Select IP clock source
163-
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
164-
// Enable IP clock
165-
CLK_EnableModuleClock(modinit->clkidx);
166+
if (! var->ref_cnt) {
167+
// Reset this module
168+
SYS_ResetModule(modinit->rsetidx);
169+
170+
// Select IP clock source
171+
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
172+
// Enable IP clock
173+
CLK_EnableModuleClock(modinit->clkidx);
166174

167-
pinmap_pinout(tx, PinMap_UART_TX);
168-
pinmap_pinout(rx, PinMap_UART_RX);
169-
// FIXME: Why PullUp?
170-
//if (tx != NC) {
171-
// pin_mode(tx, PullUp);
172-
//}
173-
//if (rx != NC) {
174-
// pin_mode(rx, PullUp);
175-
//}
176-
obj->serial.pin_tx = tx;
177-
obj->serial.pin_rx = rx;
175+
pinmap_pinout(tx, PinMap_UART_TX);
176+
pinmap_pinout(rx, PinMap_UART_RX);
177+
178+
obj->serial.pin_tx = tx;
179+
obj->serial.pin_rx = rx;
180+
}
181+
var->ref_cnt ++;
178182

179183
// Configure the UART module and set its baudrate
180184
serial_baud(obj, 9600);
181185
// Configure data bits, parity, and stop bits
182186
serial_format(obj, 8, ParityNone, 1);
183187

184-
obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec;
188+
obj->serial.vec = var->vec;
185189

186190
#if DEVICE_SERIAL_ASYNCH
187191
obj->serial.dma_usage_tx = DMA_USAGE_NEVER;
@@ -192,51 +196,61 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
192196
#endif
193197

194198
// For stdio management
195-
if (obj == &stdio_uart) {
199+
if (obj->serial.uart == STDIO_UART) {
196200
stdio_uart_inited = 1;
197-
/* NOTE: Not required anymore because stdio_uart will be manually initialized in mbed-drivers/source/retarget.cpp from mbed beta */
198-
//memcpy(&stdio_uart, obj, sizeof(serial_t));
201+
memcpy(&stdio_uart, obj, sizeof(serial_t));
199202
}
200203

201-
// Mark this module to be inited.
202-
int i = modinit - uart_modinit_tab;
203-
uart_modinit_mask |= 1 << i;
204+
if (var->ref_cnt) {
205+
// Mark this module to be inited.
206+
int i = modinit - uart_modinit_tab;
207+
uart_modinit_mask |= 1 << i;
208+
}
204209
}
205210

206211
void serial_free(serial_t *obj)
207212
{
208-
#if DEVICE_SERIAL_ASYNCH
209-
if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
210-
dma_channel_free(obj->serial.dma_chn_id_tx);
211-
obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
212-
}
213-
if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
214-
dma_channel_free(obj->serial.dma_chn_id_rx);
215-
obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
216-
}
217-
#endif
218-
219-
UART_Close((UART_T *) NU_MODBASE(obj->serial.uart));
220-
221213
const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
222214
MBED_ASSERT(modinit != NULL);
223215
MBED_ASSERT(modinit->modname == obj->serial.uart);
224216

225-
UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk));
226-
NVIC_DisableIRQ(modinit->irq_n);
217+
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
227218

228-
// Disable IP clock
229-
CLK_DisableModuleClock(modinit->clkidx);
219+
var->ref_cnt --;
220+
if (! var->ref_cnt) {
221+
#if DEVICE_SERIAL_ASYNCH
222+
if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
223+
dma_channel_free(obj->serial.dma_chn_id_tx);
224+
obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
225+
}
226+
if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
227+
dma_channel_free(obj->serial.dma_chn_id_rx);
228+
obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
229+
}
230+
#endif
231+
232+
UART_Close((UART_T *) NU_MODBASE(obj->serial.uart));
230233

231-
((struct nu_uart_var *) modinit->var)->obj = NULL;
234+
UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk));
235+
NVIC_DisableIRQ(modinit->irq_n);
232236

233-
if (obj == &stdio_uart) {
237+
// Disable IP clock
238+
CLK_DisableModuleClock(modinit->clkidx);
239+
}
240+
241+
if (var->obj == obj) {
242+
var->obj = NULL;
243+
}
244+
245+
if (obj->serial.uart == STDIO_UART) {
234246
stdio_uart_inited = 0;
235247
}
236248

237-
// Mark this module to be deinited.
238-
int i = modinit - uart_modinit_tab;
239-
uart_modinit_mask &= ~(1 << i);
249+
if (! var->ref_cnt) {
250+
// Mark this module to be deinited.
251+
int i = modinit - uart_modinit_tab;
252+
uart_modinit_mask &= ~(1 << i);
253+
}
240254
}
241255

242256
void serial_baud(serial_t *obj, int baudrate) {
@@ -317,7 +331,6 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
317331
MBED_ASSERT(modinit != NULL);
318332
MBED_ASSERT(modinit->modname == obj->serial.uart);
319333

320-
((struct nu_uart_var *) modinit->var)->obj = obj;
321334
obj->serial.irq_handler = (uint32_t) handler;
322335
obj->serial.irq_id = id;
323336

@@ -335,6 +348,11 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
335348
NVIC_SetVector(modinit->irq_n, (uint32_t) obj->serial.vec);
336349
NVIC_EnableIRQ(modinit->irq_n);
337350

351+
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
352+
// Multiple serial S/W objects for single UART H/W module possibly.
353+
// Bind serial S/W object to UART H/W module as interrupt is enabled.
354+
var->obj = obj;
355+
338356
switch (irq) {
339357
// NOTE: Setting inten_msk first to avoid race condition
340358
case RxIrq:
@@ -634,7 +652,7 @@ int serial_irq_handler_asynch(serial_t *obj)
634652
int event_rx = 0;
635653
int event_tx = 0;
636654

637-
// Necessary for both interrup way and DMA way
655+
// Necessary for both interrupt way and DMA way
638656
if (serial_is_irq_en(obj, RxIrq)) {
639657
event_rx = serial_rx_event_check(obj);
640658
if (event_rx) {
@@ -996,9 +1014,9 @@ static void serial_tx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t
9961014
MBED_ASSERT(modinit->modname == obj->serial.uart);
9971015

9981016
// Necessary for both interrupt way and DMA way
999-
((struct nu_uart_var *) modinit->var)->obj = obj;
1017+
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
10001018
// With our own async vector, tx/rx handlers can be different.
1001-
obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec_async;
1019+
obj->serial.vec = var->vec_async;
10021020
obj->serial.irq_handler_tx_async = (void (*)(void)) handler;
10031021
serial_irq_set(obj, TxIrq, enable);
10041022
}
@@ -1010,9 +1028,9 @@ static void serial_rx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t
10101028
MBED_ASSERT(modinit->modname == obj->serial.uart);
10111029

10121030
// Necessary for both interrupt way and DMA way
1013-
((struct nu_uart_var *) modinit->var)->obj = obj;
1031+
struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
10141032
// With our own async vector, tx/rx handlers can be different.
1015-
obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec_async;
1033+
obj->serial.vec = var->vec_async;
10161034
obj->serial.irq_handler_rx_async = (void (*) (void)) handler;
10171035
serial_irq_set(obj, RxIrq, enable);
10181036
}

targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/device.h

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,8 @@
1717
#ifndef MBED_DEVICE_H
1818
#define MBED_DEVICE_H
1919

20-
#define DEVICE_PORTIN 1
21-
#define DEVICE_PORTOUT 1
22-
#define DEVICE_PORTINOUT 1
23-
24-
#define DEVICE_INTERRUPTIN 1
25-
26-
#define DEVICE_ANALOGIN 1
27-
#define DEVICE_ANALOGOUT 0
28-
29-
#define DEVICE_SERIAL 1
30-
#define DEVICE_SERIAL_FC 1
31-
#define DEVICE_SERIAL_ASYNCH 1
32-
33-
#define DEVICE_I2C 1
34-
#define DEVICE_I2CSLAVE 1
35-
#define DEVICE_I2C_ASYNCH 1
36-
37-
#define DEVICE_SPI 1
38-
#define DEVICE_SPI_ASYNCH 1
39-
#define DEVICE_SPISLAVE 1
40-
41-
42-
#define DEVICE_RTC 1
43-
44-
#define DEVICE_ETHERNET 0
45-
46-
#define DEVICE_PWMOUT 1
47-
48-
#define DEVICE_SEMIHOST 0
49-
#define DEVICE_LOCALFILESYSTEM 0
5020
#define DEVICE_ID_LENGTH 24
5121

52-
#define DEVICE_SLEEP 1
53-
54-
#define DEVICE_DEBUG_AWARENESS 0
55-
56-
#define DEVICE_STDIO_MESSAGES 1
57-
58-
#define DEVICE_ERROR_RED 0
59-
60-
#define DEVICE_LOWPOWERTIMER 1
61-
6222
#include "objects.h"
6323

6424
#endif

targets/TARGET_NUVOTON/TARGET_NUC472/device/TOOLCHAIN_ARM_MICRO/NUC472.sct

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ LR_IROM1 0x00000000 {
1010
; uvisor-lib.a (+RW +ZI)
1111
;}
1212

13-
ARM_LIB_STACK 0x20000000 EMPTY 0x3000 {
13+
ARM_LIB_STACK 0x20000000 EMPTY 0x800 {
1414
}
1515

16-
ER_IRAMVEC 0x20003000 EMPTY (4*(16 + 142)) { ; Reserve for vectors
16+
ER_IRAMVEC 0x20000800 EMPTY (4*(16 + 142)) { ; Reserve for vectors
1717
}
1818

1919
RW_IRAM1 AlignExpr(+0, 16) { ; 16 byte-aligned

0 commit comments

Comments
 (0)