1 /**
2 * \file
3 *
4 * \brief SAM UART Driver for SAMB11
5 *
6 * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #include "uart.h"
47
48 /**
49 * \internal
50 * Internal driver device instance struct.
51 */
52 struct uart_module *_uart_instances[UART_INST_NUM];
53
54 /**
55 * \internal
56 * Writes a character from the TX buffer to the Data register.
57 *
58 * \param[in,out] module Pointer to UART software instance struct
59 */
_uart_write(struct uart_module * const module)60 static void _uart_write(struct uart_module *const module)
61 {
62 /* Pointer to the hardware module instance */
63 Uart *const uart_hw = module->hw;
64
65 /* Write value will be at least 8-bits long */
66 uint8_t data_to_send = *(module->tx_buffer_ptr);
67 /* Increment 8-bit pointer */
68 (module->tx_buffer_ptr)++;
69
70 /* Write the data to send*/
71 uart_hw->TRANSMIT_DATA.reg = data_to_send & UART_TRANSMIT_DATA_MASK;
72
73 /* Decrement remaining buffer length */
74 (module->remaining_tx_buffer_length)--;
75 }
76
77 /**
78 * \internal
79 * Reads a character from the Data register to the RX buffer.
80 *
81 * \param[in,out] module Pointer to UART software instance struct
82 */
_uart_read(struct uart_module * const module)83 static void _uart_read(
84 struct uart_module *const module)
85 {
86 /* Pointer to the hardware module instance */
87 Uart *const uart_hw = module->hw;
88
89 uint16_t received_data = (uart_hw->RECEIVE_DATA.reg & UART_RECEIVE_DATA_MASK);
90
91 /* Read value will be at least 8-bits long */
92 *(module->rx_buffer_ptr) = received_data;
93 /* Increment 8-bit pointer */
94 module->rx_buffer_ptr += 1;
95
96 /* Decrement length of the remaining buffer */
97 module->remaining_rx_buffer_length--;
98 }
99
uart_rx0_isr_handler(void)100 static void uart_rx0_isr_handler(void)
101 {
102 struct uart_module *module = _uart_instances[0];
103 /* get interrupt flags and mask out enabled callbacks */
104 uint32_t flags = module->hw->RECEIVE_STATUS.reg;
105 if (flags & UART_RECEIVE_STATUS_FIFO_OVERRUN) {
106 /* Store the error code */
107 module->status = STATUS_ERR_OVERFLOW;
108 /* Disable interrupt */
109 module->hw->RX_INTERRUPT_MASK.reg &=
110 ~(UART_RX_INTERRUPT_MASK_FIFO_OVERRUN_MASK |
111 SPI_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK);
112 if ((module->callback_enable_mask & (1 << UART_RX_FIFO_OVERRUN)) &&
113 (module->callback_reg_mask & (1 << UART_RX_FIFO_OVERRUN))) {
114 (module->callback[UART_RX_FIFO_OVERRUN])(module);
115 }
116 /* Flush */
117 uint8_t flush = module->hw->RECEIVE_DATA.reg;
118 UNUSED(flush);
119 }
120 if (flags & UART_RECEIVE_STATUS_RX_FIFO_NOT_EMPTY) {
121 _uart_read(module);
122 if (module->remaining_rx_buffer_length == 0) {
123 if ((module->callback_enable_mask & (1 << UART_RX_COMPLETE)) &&
124 (module->callback_reg_mask & (1 << UART_RX_COMPLETE))) {
125 module->status = STATUS_OK;
126 module->hw->RX_INTERRUPT_MASK.reg &=
127 ~(UART_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK);
128 (module->callback[UART_RX_COMPLETE])(module);
129 }
130 }
131 }
132 }
133
uart_tx0_isr_handler(void)134 static void uart_tx0_isr_handler(void)
135 {
136 struct uart_module *module = _uart_instances[0];
137 /* get interrupt flags and mask out enabled callbacks */
138 uint32_t flags = module->hw->TRANSMIT_STATUS.reg;
139 if (flags & UART_TRANSMIT_STATUS_TX_FIFO_NOT_FULL) {
140 _uart_write(module);
141 if (module->remaining_tx_buffer_length == 0) {
142 module->hw->TX_INTERRUPT_MASK.reg &=
143 ~UART_TX_INTERRUPT_MASK_TX_FIFO_NOT_FULL_MASK;
144 module->hw->TX_INTERRUPT_MASK.reg |=
145 UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
146 }
147 }
148 if (flags & UART_TRANSMIT_STATUS_TX_FIFO_EMPTY) {
149 if ((module->callback_enable_mask & (1 << UART_TX_COMPLETE)) &&
150 (module->callback_reg_mask & (1 << UART_TX_COMPLETE))) {
151 module->status = STATUS_OK;
152 /* Disable interrupt */
153 module->hw->TX_INTERRUPT_MASK.reg &=
154 ~UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
155 (module->callback[UART_TX_COMPLETE])(module);
156 }
157
158 }
159 if (flags & UART_TRANSMIT_STATUS_CTS_ACTIVE) {
160 if ((module->callback_enable_mask & (1 << UART_CTS_ACTIVE)) &&
161 (module->callback_reg_mask & (1 << UART_CTS_ACTIVE))) {
162 (module->callback[UART_CTS_ACTIVE])(module);
163 }
164
165 }
166 }
167
uart_rx1_isr_handler(void)168 static void uart_rx1_isr_handler(void)
169 {
170 struct uart_module *module = _uart_instances[1];
171 /* get interrupt flags and mask out enabled callbacks */
172 uint32_t flags = module->hw->RECEIVE_STATUS.reg;
173 if (flags & UART_RECEIVE_STATUS_FIFO_OVERRUN) {
174 /* Store the error code */
175 module->status = STATUS_ERR_OVERFLOW;
176 /* Disable interrupt */
177 module->hw->RX_INTERRUPT_MASK.reg &=
178 ~(UART_RX_INTERRUPT_MASK_FIFO_OVERRUN_MASK |
179 SPI_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK);
180 if ((module->callback_enable_mask & (1 << UART_RX_FIFO_OVERRUN)) &&
181 (module->callback_reg_mask & (1 << UART_RX_FIFO_OVERRUN))) {
182 (module->callback[UART_RX_FIFO_OVERRUN])(module);
183 }
184 /* Flush */
185 uint8_t flush = module->hw->RECEIVE_DATA.reg;
186 UNUSED(flush);
187 }
188 if (flags & UART_RECEIVE_STATUS_RX_FIFO_NOT_EMPTY) {
189 _uart_read(module);
190 if (module->remaining_rx_buffer_length == 0) {
191 if ((module->callback_enable_mask & (1 << UART_RX_COMPLETE)) &&
192 (module->callback_reg_mask & (1 << UART_RX_COMPLETE))) {
193 module->status = STATUS_OK;
194 module->hw->RX_INTERRUPT_MASK.reg &=
195 ~(UART_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK);
196 (module->callback[UART_RX_COMPLETE])(module);
197 }
198 }
199 }
200 }
201
uart_tx1_isr_handler(void)202 static void uart_tx1_isr_handler(void)
203 {
204 struct uart_module *module = _uart_instances[1];
205 /* get interrupt flags and mask out enabled callbacks */
206 uint32_t flags = module->hw->TRANSMIT_STATUS.reg;
207 if (flags & UART_TRANSMIT_STATUS_TX_FIFO_NOT_FULL) {
208 _uart_write(module);
209 if (module->remaining_tx_buffer_length == 0) {
210 module->hw->TX_INTERRUPT_MASK.reg &=
211 ~UART_TX_INTERRUPT_MASK_TX_FIFO_NOT_FULL_MASK;
212 module->hw->TX_INTERRUPT_MASK.reg |=
213 UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
214 }
215 }
216 if (flags & UART_TRANSMIT_STATUS_TX_FIFO_EMPTY) {
217 if ((module->callback_enable_mask & (1 << UART_TX_COMPLETE)) &&
218 (module->callback_reg_mask & (1 << UART_TX_COMPLETE))) {
219 module->status = STATUS_OK;
220 /* Disable interrupt */
221 module->hw->TX_INTERRUPT_MASK.reg &=
222 ~UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
223 (module->callback[UART_TX_COMPLETE])(module);
224 }
225
226 }
227 if (flags & UART_TRANSMIT_STATUS_CTS_ACTIVE) {
228 if ((module->callback_enable_mask & (1 << UART_CTS_ACTIVE)) &&
229 (module->callback_reg_mask & (1 << UART_CTS_ACTIVE))) {
230 (module->callback[UART_CTS_ACTIVE])(module);
231 }
232
233 }
234 }
235
uart_set_baudrate(struct uart_module * const module,const uint32_t baud_rate)236 static void uart_set_baudrate(struct uart_module *const module,
237 const uint32_t baud_rate)
238 {
239 uint32_t clock;
240 uint16_t integerpart = 0;
241 uint8_t fractionalpart = 0;
242 uint32_t diff;
243 uint8_t i = 0;
244
245 clock = system_clock_get_value();
246 integerpart = clock / baud_rate;
247 diff = clock - (baud_rate * integerpart);
248 i = 0;
249 while(diff > (baud_rate / 16)) {
250 i++;
251 diff -= (baud_rate / 16);
252 }
253 fractionalpart = (i + 1) / 2;
254
255 module->hw->UART_CLOCK_SOURCE.reg = UART_CLOCK_SOURCE_CLOCK_SELECT_0;
256 module->hw->UART_BAUD_RATE.reg =
257 UART_BAUD_RATE_INTEGER_DIVISION(integerpart) |
258 UART_BAUD_RATE_FRACTIONAL_DIVISION(fractionalpart);
259 }
260
261 /**
262 * \brief Gets the UART default configurations
263 *
264 * Use to initialize the configuration structure to known default values.
265 *
266 * The default configuration is as follows:
267 * - Baudrate 115200
268 * - parity UART_NO_PARITY
269 * - flow_control 0 - No Flow control
270 * - stop_bits 1 - 1 stop bit
271 * - pinmux_pad[] - Pinmux default are UART0.
272 *
273 * \param[out] config Pointer to configuration structure to be initiated
274 */
uart_get_config_defaults(struct uart_config * const config)275 void uart_get_config_defaults(
276 struct uart_config *const config)
277 {
278 config->baud_rate = 115200;
279 config->data_bits = UART_8_BITS;
280 config->stop_bits = UART_1_STOP_BIT;
281 config->parity = UART_NO_PARITY;
282 config->flow_control = false;
283
284 config->pin_number_pad[0] = PIN_LP_GPIO_2;
285 config->pin_number_pad[1] = PIN_LP_GPIO_3;
286 config->pin_number_pad[2] = PIN_LP_GPIO_4;
287 config->pin_number_pad[3] = PIN_LP_GPIO_5;
288
289 config->pinmux_sel_pad[0] = MUX_LP_GPIO_2_UART0_RXD;
290 config->pinmux_sel_pad[1] = MUX_LP_GPIO_3_UART0_TXD;
291 config->pinmux_sel_pad[2] = MUX_LP_GPIO_4_UART0_CTS;
292 config->pinmux_sel_pad[3] = MUX_LP_GPIO_5_UART0_RTS;
293 }
294
295 /**
296 * \brief Initializes the device
297 *
298 * Initializes the UART device based on the setting specified in the
299 * configuration struct.
300 *
301 * \param[in] module enumeration UART hw module
302 * \param[in] hw Pointer to USART hardware instance
303 * \param[in] config Pointer to configuration struct
304 *
305 * \return Status of the initialization.
306 *
307 * \retval STATUS_OK The initialization was successful
308 */
uart_init(struct uart_module * const module,Uart * const hw,const struct uart_config * const config)309 enum status_code uart_init(struct uart_module *const module, Uart * const hw,
310 const struct uart_config *const config)
311 {
312 /* Sanity check arguments */
313 Assert(module);
314 Assert(hw);
315 Assert(config);
316
317 uint8_t config_temp = 0;
318 uint8_t i,index;
319
320 /* Assign module pointer to software instance struct */
321 module->hw = hw;
322
323 for (i = 0; i < UART_CALLBACK_N; i++) {
324 module->callback[i] = NULL;
325 }
326 module->rx_buffer_ptr = NULL;
327 module->tx_buffer_ptr = NULL;
328 module->remaining_rx_buffer_length = 0;
329 module->remaining_tx_buffer_length = 0;
330 module->callback_reg_mask = 0;
331 module->callback_enable_mask = 0;
332 module->status = STATUS_OK;
333
334 if (hw == UART0) {
335 system_peripheral_reset(PERIPHERAL_UART0_CORE);
336 system_peripheral_reset(PERIPHERAL_UART0_IF);
337 system_clock_peripheral_enable(PERIPHERAL_UART0_CORE);
338 system_clock_peripheral_enable(PERIPHERAL_UART0_IF);
339 _uart_instances[0] = module;
340 system_register_isr(RAM_ISR_TABLE_UARTRX0_INDEX, (uint32_t)uart_rx0_isr_handler);
341 system_register_isr(RAM_ISR_TABLE_UARTTX0_INDEX, (uint32_t)uart_tx0_isr_handler);
342 NVIC_EnableIRQ(UART0_RX_IRQn);
343 NVIC_EnableIRQ(UART0_TX_IRQn);
344 } else if (hw == UART1) {
345 system_peripheral_reset(PERIPHERAL_UART1_CORE);
346 system_peripheral_reset(PERIPHERAL_UART1_IF);
347 system_clock_peripheral_enable(PERIPHERAL_UART1_CORE);
348 system_clock_peripheral_enable(PERIPHERAL_UART1_IF);
349 _uart_instances[1] = module;
350 system_register_isr(RAM_ISR_TABLE_UARTRX1_INDEX, (uint32_t)uart_rx1_isr_handler);
351 system_register_isr(RAM_ISR_TABLE_UARTTX1_INDEX, (uint32_t)uart_tx1_isr_handler);
352 NVIC_EnableIRQ(UART1_RX_IRQn);
353 NVIC_EnableIRQ(UART1_TX_IRQn);
354 }
355
356 /* Set the pinmux for this UART module. */
357 if(config->flow_control) {
358 index = 4;
359 } else {
360 index = 2;
361 }
362
363 #if (BTLC1000)
364 index = 2; /* BTLC1000 has no flow control function. */
365 #endif
366
367 for(i = 0; i < index; i++) {
368 gpio_pinmux_cofiguration(config->pin_number_pad[i], \
369 (uint16_t)(config->pinmux_sel_pad[i]));
370 }
371
372 /* empty UART FIFO */
373 while (module->hw->RECEIVE_STATUS.reg & UART_RECEIVE_STATUS_RX_FIFO_NOT_EMPTY) {
374 i = module->hw->RECEIVE_DATA.reg;
375 }
376
377 /* reset configuration register */
378 module->hw->UART_CONFIGURATION.reg = 0;
379
380 /* program the uart configuration. */
381 if(config->flow_control) {
382 config_temp |= UART_CONFIGURATION_CTS_ENABLE_1;
383 }
384 config_temp |= config->data_bits;
385 config_temp |= config->stop_bits;
386 switch(config->parity) {
387 case UART_NO_PARITY:
388 config_temp |= UART_CONFIGURATION_PARITY_ENABLE_0;
389 break;
390
391 case UART_EVEN_PARITY:
392 config_temp |= UART_CONFIGURATION_PARITY_ENABLE_1;
393 config_temp |= UART_CONFIGURATION_PARITY_MODE_0;
394 break;
395
396 case UART_ODD_PARITY:
397 config_temp |= UART_CONFIGURATION_PARITY_ENABLE_1;
398 config_temp |= UART_CONFIGURATION_PARITY_MODE_1;
399 break;
400
401 case UART_SPACE_PARITY:
402 config_temp |= UART_CONFIGURATION_PARITY_ENABLE_1;
403 config_temp |= UART_CONFIGURATION_PARITY_MODE_2;
404 break;
405
406 case UART_MARK_PARITY:
407 config_temp |= UART_CONFIGURATION_PARITY_ENABLE_1;
408 config_temp |= UART_CONFIGURATION_PARITY_MODE_3;
409 break;
410
411 default:
412 break;
413 }
414 module->hw->UART_CONFIGURATION.reg = config_temp;
415
416 /* Calculate the baud rate. */
417 uart_set_baudrate(module, config->baud_rate);
418
419 module->hw->RX_INTERRUPT_MASK.reg = 0; // disable int at initialization, enable it at read time
420 module->hw->TX_INTERRUPT_MASK.reg = 0; // disable int at initialization, enable it at write time
421
422 return STATUS_OK;
423 }
424
425 /**
426 * \brief Transmit a character via the UART
427 *
428 * This blocking function will transmit a single character via the
429 * UART.
430 *
431 * \param[in] module enumeration UART hw module
432 * \param[in] tx_data Data to transfer
433 *
434 * \return Status of the operation.
435 * \retval STATUS_OK If the operation was completed
436 */
uart_write_wait(struct uart_module * const module,const uint8_t tx_data)437 enum status_code uart_write_wait(struct uart_module *const module,
438 const uint8_t tx_data)
439 {
440 while (!(module->hw->TRANSMIT_STATUS.reg & UART_TRANSMIT_STATUS_TX_FIFO_NOT_FULL));
441
442 module->hw->TRANSMIT_DATA.reg = tx_data;
443
444 return STATUS_OK;
445 }
446
447 /**
448 * \brief Receive a character via the UART
449 *
450 * This blocking function will receive a character via the UART.
451 *
452 * \param[in] module enumeration UART hw module
453 * \param[out] rx_data Pointer to received data
454 *
455 * \return Status of the operation.
456 * \retval STATUS_OK If the operation was completed
457 */
uart_read_wait(struct uart_module * const module,uint8_t * const rx_data)458 enum status_code uart_read_wait(struct uart_module *const module,
459 uint8_t *const rx_data)
460 {
461 while (!(module->hw->RECEIVE_STATUS.reg & UART_RECEIVE_STATUS_RX_FIFO_NOT_EMPTY));
462
463 *rx_data = module->hw->RECEIVE_DATA.reg;
464
465 return STATUS_OK;
466 }
467
468 /**
469 * \brief Transmit a buffer of characters via the UART
470 *
471 * This blocking function will transmit a block of \c length characters
472 * via the UART.
473 *
474 * \note Using this function in combination with the interrupt (\c _job) functions is
475 * not recommended as it has no functionality to check if there is an
476 * ongoing interrupt driven operation running or not.
477 *
478 * \param[in] module enumeration UART hw module
479 * \param[in] tx_data Pointer to data to transmit
480 * \param[in] length Number of characters to transmit
481 *
482 * \return Status of the operation.
483 * \retval STATUS_OK If operation was completed
484 */
uart_write_buffer_wait(struct uart_module * const module,const uint8_t * tx_data,uint32_t length)485 enum status_code uart_write_buffer_wait(struct uart_module *const module,
486 const uint8_t *tx_data, uint32_t length)
487 {
488 while(length--)
489 uart_write_wait(module, *tx_data++);
490
491 return STATUS_OK;
492 }
493
494 /**
495 * \brief Receive a buffer of \c length characters via the UART
496 *
497 * This blocking function will receive a block of \c length characters
498 * via the UART.
499 *
500 * \note Using this function in combination with the interrupt (\c *_job)
501 * functions is not recommended as it has no functionality to check if
502 * there is an ongoing interrupt driven operation running or not.
503 *
504 * \param[in] module enumeration UART hw module
505 * \param[out] rx_data Pointer to receive buffer
506 * \param[in] length Number of characters to receive
507 *
508 * \return Status of the operation.
509 * \retval STATUS_OK If operation was completed
510 */
uart_read_buffer_wait(struct uart_module * const module,uint8_t * rx_data,uint16_t length)511 enum status_code uart_read_buffer_wait(struct uart_module *const module,
512 uint8_t *rx_data, uint16_t length)
513 {
514 while(length--)
515 uart_read_wait(module, rx_data++);
516
517 return STATUS_OK;
518 }
519
520 /**
521 * \internal
522 * Starts write of a buffer with a given length
523 *
524 * \param[in] module Pointer to UART software instance struct
525 * \param[in] tx_data Pointer to data to be transmitted
526 * \param[in] length Length of data buffer
527 *
528 */
_uart_write_buffer(struct uart_module * const module,uint8_t * tx_data,uint16_t length)529 static void _uart_write_buffer(
530 struct uart_module *const module,
531 uint8_t *tx_data,
532 uint16_t length)
533 {
534 Assert(module);
535 Assert(tx_data);
536
537 /* Write parameters to the device instance */
538 module->remaining_tx_buffer_length = length;
539 module->tx_buffer_ptr = tx_data;
540 module->status = STATUS_BUSY;
541
542 module->hw->TX_INTERRUPT_MASK.reg = UART_TX_INTERRUPT_MASK_TX_FIFO_NOT_FULL_MASK;
543 }
544
545 /**
546 * \internal
547 * Setup UART to read a buffer with a given length
548 *
549 * \param[in] module Pointer to UART software instance struct
550 * \param[in] rx_data Pointer to data to be received
551 * \param[in] length Length of data buffer
552 *
553 */
_uart_read_buffer(struct uart_module * const module,uint8_t * rx_data,uint16_t length)554 static void _uart_read_buffer(
555 struct uart_module *const module,
556 uint8_t *rx_data,
557 uint16_t length)
558 {
559 Assert(module);
560 Assert(rx_data);
561
562 /* Set length for the buffer and the pointer, and let
563 * the interrupt handler do the rest */
564 module->remaining_rx_buffer_length = length;
565 module->rx_buffer_ptr = rx_data;
566 module->status = STATUS_BUSY;
567
568 module->hw->RX_INTERRUPT_MASK.reg = UART_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK;
569 }
570
571 /**
572 * \brief Asynchronous buffer write
573 *
574 * Sets up the driver to write to the UART from a given buffer. If registered
575 * and enabled, a callback function will be called when the write is finished.
576 *
577 * \param[in] module Pointer to UART software instance struct
578 * \param[out] tx_data Pointer to data buffer to receive
579 * \param[in] length Data buffer length
580 *
581 * \returns Status of the write request operation.
582 * \retval STATUS_OK If the operation completed successfully
583 * \retval STATUS_ERR_BUSY If the UART was already busy with a write
584 * operation
585 * \retval STATUS_ERR_INVALID_ARG If requested write length was zero
586 */
uart_write_buffer_job(struct uart_module * const module,uint8_t * tx_data,uint32_t length)587 enum status_code uart_write_buffer_job(struct uart_module *const module,
588 uint8_t *tx_data, uint32_t length)
589 {
590 Assert(module);
591 Assert(tx_data);
592
593 if (length == 0) {
594 return STATUS_ERR_INVALID_ARG;
595 }
596
597 /* Check if the UART is busy transmitting or slave waiting for TXC*/
598 if (module->status == STATUS_BUSY) {
599 return STATUS_BUSY;
600 }
601
602 /* Issue internal write */
603 _uart_write_buffer(module, tx_data, length);
604
605 return STATUS_OK;
606 }
607
608 /**
609 * \brief Asynchronous buffer read
610 *
611 * Sets up the driver to read from the UART to a given buffer. If registered
612 * and enabled, a callback function will be called when the read is finished.
613 *
614 * \note If address matching is enabled for the slave, the first character
615 * received and placed in the RX buffer will be the address.
616 *
617 * \param[in] module Pointer to UART software instance struct
618 * \param[out] rx_data Pointer to data buffer to receive
619 * \param[in] length Data buffer length
620 * \param[in] dummy Dummy character to send when reading in master mode
621 *
622 * \returns Status of the operation.
623 * \retval STATUS_OK If the operation completed successfully
624 * \retval STATUS_ERR_BUSY If the UART was already busy with a read
625 * operation
626 * \retval STATUS_ERR_DENIED If the receiver is not enabled
627 * \retval STATUS_ERR_INVALID_ARG If requested read length was zero
628 */
uart_read_buffer_job(struct uart_module * const module,uint8_t * rx_data,uint16_t length)629 enum status_code uart_read_buffer_job(struct uart_module *const module,
630 uint8_t *rx_data, uint16_t length)
631 {
632 /* Sanity check arguments */
633 Assert(module);
634 Assert(rx_data);
635
636 if (length == 0) {
637 return STATUS_ERR_INVALID_ARG;
638 }
639
640 /* Check if the UART is busy transmitting or slave waiting for TXC*/
641 if (module->status == STATUS_BUSY) {
642 return STATUS_BUSY;
643 }
644
645 /* Issue internal read */
646 _uart_read_buffer(module, rx_data, length);
647 return STATUS_OK;
648 }
649
650 /**
651 * \brief Registers a callback
652 *
653 * Registers a callback function which is implemented by the user.
654 *
655 * \note The callback must be enabled by \ref uart_enable_callback,
656 * in order for the interrupt handler to call it when the conditions for
657 * the callback type are met.
658 *
659 * \param[in] module Pointer to UART software instance struct
660 * \param[in] callback_func Pointer to callback function
661 * \param[in] callback_type Callback type given by an enum
662 *
663 */
uart_register_callback(struct uart_module * const module,uart_callback_t callback_func,enum uart_callback callback_type)664 void uart_register_callback(struct uart_module *const module,
665 uart_callback_t callback_func,
666 enum uart_callback callback_type)
667 {
668 /* Sanity check arguments */
669 Assert(module);
670 Assert(callback_func);
671
672 /* Register callback function */
673 module->callback[callback_type] = callback_func;
674 /* Set the bit corresponding to the callback_type */
675 module->callback_reg_mask |= (1 << callback_type);
676 }
677
678 /**
679 * \brief Unregisters a callback
680 *
681 * Unregisters a callback function which is implemented by the user.
682 *
683 * \param[in,out] module Pointer to UART software instance struct
684 * \param[in] callback_type Callback type given by an enum
685 *
686 */
uart_unregister_callback(struct uart_module * module,enum uart_callback callback_type)687 void uart_unregister_callback(struct uart_module *module,
688 enum uart_callback callback_type)
689 {
690 /* Sanity check arguments */
691 Assert(module);
692
693 /* Unregister callback function */
694 module->callback[callback_type] = NULL;
695 /* Clear the bit corresponding to the callback_type */
696 module->callback_reg_mask &= ~(1 << callback_type);
697 }
698
699 /**
700 * \brief Enables callback
701 *
702 * Enables the callback function registered by the \ref usart_register_callback.
703 * The callback function will be called from the interrupt handler when the
704 * conditions for the callback type are met.
705 *
706 * \param[in] module Pointer to UART software instance struct
707 * \param[in] callback_type Callback type given by an enum
708 */
uart_enable_callback(struct uart_module * const module,enum uart_callback callback_type)709 void uart_enable_callback(struct uart_module *const module,
710 enum uart_callback callback_type)
711 {
712 /* Sanity check arguments */
713 Assert(module);
714
715 /* Enable callback */
716 module->callback_enable_mask |= (1 << callback_type);
717
718 if (callback_type == UART_CTS_ACTIVE) {
719 module->hw->TX_INTERRUPT_MASK.reg |= UART_TX_INTERRUPT_MASK_CTS_ACTIVE_MASK;
720 }
721 }
722
723 /**
724 * \brief Disable callback
725 *
726 * Disables the callback function registered by the \ref usart_register_callback,
727 * and the callback will not be called from the interrupt routine.
728 *
729 * \param[in] module Pointer to UART software instance struct
730 * \param[in] callback_type Callback type given by an enum
731 */
uart_disable_callback(struct uart_module * const module,enum uart_callback callback_type)732 void uart_disable_callback(struct uart_module *const module,
733 enum uart_callback callback_type)
734 {
735 /* Sanity check arguments */
736 Assert(module);
737
738 /* Disable callback */
739 module->callback_enable_mask &= ~(1 << callback_type);
740
741 if (callback_type == UART_CTS_ACTIVE) {
742 module->hw->TX_INTERRUPT_MASK.reg &= ~UART_TX_INTERRUPT_MASK_CTS_ACTIVE_MASK;
743 }
744
745 }
746
747 /**
748 * \brief Enables UART transmit DMA
749 *
750 * \param[in] module Pointer to UART software instance struct
751 */
uart_enable_transmit_dma(struct uart_module * const module)752 void uart_enable_transmit_dma(struct uart_module *const module)
753 {
754 /* Sanity check arguments */
755 Assert(module);
756
757 /* DMA need the interrupt signal to trigger */
758 module->hw->TX_INTERRUPT_MASK.reg |= UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
759
760 /* Disable NVIC to avoid trigger the CPU interrupt */
761 if (module->hw == UART0) {
762 NVIC_DisableIRQ(UART0_TX_IRQn);
763 } else if (module->hw == UART1) {
764 NVIC_DisableIRQ(UART1_TX_IRQn);
765 }
766 }
767
768 /**
769 * \brief Disables UART transmit DMA
770 *
771 * \param[in] module Pointer to UART software instance struct
772 */
uart_disable_transmit_dma(struct uart_module * const module)773 void uart_disable_transmit_dma(struct uart_module *const module)
774 {
775 /* Sanity check arguments */
776 Assert(module);
777
778 module->hw->TX_INTERRUPT_MASK.reg &= ~UART_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
779
780 /* Enable NVIC to restore the callback functions */
781 if (module->hw == UART0) {
782 NVIC_EnableIRQ(UART0_TX_IRQn);
783 } else if (module->hw == UART1) {
784 NVIC_EnableIRQ(UART1_TX_IRQn);
785 }
786 }
787
788 /**
789 * \brief Enables UART receive DMA
790 *
791 * \param[in] module Pointer to UART software instance struct
792 */
uart_enable_receive_dma(struct uart_module * const module)793 void uart_enable_receive_dma(struct uart_module *const module)
794 {
795 /* Sanity check arguments */
796 Assert(module);
797
798 /* DMA need the interrupt signal to trigger */
799 module->hw->RX_INTERRUPT_MASK.reg |= UART_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK;
800
801 /* Disable NVIC to avoid trigger the CPU interrupt */
802 if (module->hw == UART0) {
803 NVIC_DisableIRQ(UART0_TX_IRQn);
804 } else if (module->hw == UART1) {
805 NVIC_DisableIRQ(UART1_TX_IRQn);
806 }
807 }
808
809 /**
810 * \brief Disables UART receive DMA
811 *
812 * \param[in] module Pointer to UART software instance struct
813 */
uart_disable_receive_dma(struct uart_module * const module)814 void uart_disable_receive_dma(struct uart_module *const module)
815 {
816 /* Sanity check arguments */
817 Assert(module);
818
819 module->hw->RX_INTERRUPT_MASK.reg &= ~UART_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK;
820
821 /* Enable NVIC to restore the callback functions */
822 if (module->hw == UART0) {
823 NVIC_EnableIRQ(UART0_TX_IRQn);
824 } else if (module->hw == UART1) {
825 NVIC_EnableIRQ(UART1_TX_IRQn);
826 }
827 }
828
829