31
31
#endif
32
32
33
33
struct nu_uart_var {
34
+ uint32_t ref_cnt ; // Reference count of the H/W module
34
35
serial_t * obj ;
35
36
uint32_t fifo_size_tx ;
36
37
uint32_t fifo_size_rx ;
@@ -80,6 +81,7 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
80
81
#endif
81
82
82
83
static struct nu_uart_var uart0_var = {
84
+ .ref_cnt = 0 ,
83
85
.obj = NULL ,
84
86
.fifo_size_tx = 16 ,
85
87
.fifo_size_rx = 16 ,
@@ -91,6 +93,7 @@ static struct nu_uart_var uart0_var = {
91
93
#endif
92
94
};
93
95
static struct nu_uart_var uart1_var = {
96
+ .ref_cnt = 0 ,
94
97
.obj = NULL ,
95
98
.fifo_size_tx = 16 ,
96
99
.fifo_size_rx = 16 ,
@@ -102,6 +105,7 @@ static struct nu_uart_var uart1_var = {
102
105
#endif
103
106
};
104
107
static struct nu_uart_var uart2_var = {
108
+ .ref_cnt = 0 ,
105
109
.obj = NULL ,
106
110
.fifo_size_tx = 16 ,
107
111
.fifo_size_rx = 16 ,
@@ -113,6 +117,7 @@ static struct nu_uart_var uart2_var = {
113
117
#endif
114
118
};
115
119
static struct nu_uart_var uart3_var = {
120
+ .ref_cnt = 0 ,
116
121
.obj = NULL ,
117
122
.fifo_size_tx = 16 ,
118
123
.fifo_size_rx = 16 ,
@@ -142,7 +147,7 @@ extern void mbed_sdk_init(void);
142
147
143
148
void serial_init (serial_t * obj , PinName tx , PinName rx )
144
149
{
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 ().
146
151
mbed_sdk_init ();
147
152
148
153
// Determine which UART_x the pins are used for
@@ -156,32 +161,31 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
156
161
MBED_ASSERT (modinit != NULL );
157
162
MBED_ASSERT (modinit -> modname == obj -> serial .uart );
158
163
159
- // Reset this module
160
- SYS_ResetModule (modinit -> rsetidx );
164
+ struct nu_uart_var * var = (struct nu_uart_var * ) modinit -> var ;
161
165
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 );
166
174
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 ++ ;
178
182
179
183
// Configure the UART module and set its baudrate
180
184
serial_baud (obj , 9600 );
181
185
// Configure data bits, parity, and stop bits
182
186
serial_format (obj , 8 , ParityNone , 1 );
183
187
184
- obj -> serial .vec = (( struct nu_uart_var * ) modinit -> var ) -> vec ;
188
+ obj -> serial .vec = var -> vec ;
185
189
186
190
#if DEVICE_SERIAL_ASYNCH
187
191
obj -> serial .dma_usage_tx = DMA_USAGE_NEVER ;
@@ -192,51 +196,61 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
192
196
#endif
193
197
194
198
// For stdio management
195
- if (obj == & stdio_uart ) {
199
+ if (obj -> serial . uart == STDIO_UART ) {
196
200
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 ));
199
202
}
200
203
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
+ }
204
209
}
205
210
206
211
void serial_free (serial_t * obj )
207
212
{
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
-
221
213
const struct nu_modinit_s * modinit = get_modinit (obj -> serial .uart , uart_modinit_tab );
222
214
MBED_ASSERT (modinit != NULL );
223
215
MBED_ASSERT (modinit -> modname == obj -> serial .uart );
224
216
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 ;
227
218
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 ));
230
233
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 );
232
236
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 ) {
234
246
stdio_uart_inited = 0 ;
235
247
}
236
248
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
+ }
240
254
}
241
255
242
256
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)
317
331
MBED_ASSERT (modinit != NULL );
318
332
MBED_ASSERT (modinit -> modname == obj -> serial .uart );
319
333
320
- ((struct nu_uart_var * ) modinit -> var )-> obj = obj ;
321
334
obj -> serial .irq_handler = (uint32_t ) handler ;
322
335
obj -> serial .irq_id = id ;
323
336
@@ -335,6 +348,11 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
335
348
NVIC_SetVector (modinit -> irq_n , (uint32_t ) obj -> serial .vec );
336
349
NVIC_EnableIRQ (modinit -> irq_n );
337
350
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
+
338
356
switch (irq ) {
339
357
// NOTE: Setting inten_msk first to avoid race condition
340
358
case RxIrq :
@@ -634,7 +652,7 @@ int serial_irq_handler_asynch(serial_t *obj)
634
652
int event_rx = 0 ;
635
653
int event_tx = 0 ;
636
654
637
- // Necessary for both interrup way and DMA way
655
+ // Necessary for both interrupt way and DMA way
638
656
if (serial_is_irq_en (obj , RxIrq )) {
639
657
event_rx = serial_rx_event_check (obj );
640
658
if (event_rx ) {
@@ -996,9 +1014,9 @@ static void serial_tx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t
996
1014
MBED_ASSERT (modinit -> modname == obj -> serial .uart );
997
1015
998
1016
// 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 ;
1000
1018
// 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 ;
1002
1020
obj -> serial .irq_handler_tx_async = (void (* )(void )) handler ;
1003
1021
serial_irq_set (obj , TxIrq , enable );
1004
1022
}
@@ -1010,9 +1028,9 @@ static void serial_rx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t
1010
1028
MBED_ASSERT (modinit -> modname == obj -> serial .uart );
1011
1029
1012
1030
// 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 ;
1014
1032
// 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 ;
1016
1034
obj -> serial .irq_handler_rx_async = (void (* ) (void )) handler ;
1017
1035
serial_irq_set (obj , RxIrq , enable );
1018
1036
}
0 commit comments