41 #define DBG_vPrintf(...) 45 #include "uart-driver.h" 49 #include <AppHardwareApi.h> 51 #if UART_XONXOFF_FLOW_CTRL 55 #define TX_FIFO_SW_FLOW_LIMIT 8 56 #if TX_FIFO_SW_FLOW_LIMIT > 16 57 #undef TX_FIFO_SW_FLOW_LIMIT 58 #define TX_FIFO_SW_FLOW_LIMIT 16 59 #warning "TX_FIFO_SW_FLOW_LIMIT too big. Forced to 16." 65 extern volatile unsigned char xonxoff_state;
70 #define BUSYWAIT_UNTIL(cond, max_time) \ 74 while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) ; \ 77 #define DEBUG_UART_BUFFERED FALSE 79 #define CHAR_DEADLINE (uart_char_delay * 100) 82 static void uart_driver_isr(uint32_t device_id, uint32_t item_bitmap);
83 #if !UART_XONXOFF_FLOW_CTRL 84 static int16_t uart_driver_get_tx_fifo_available_space(uint8_t uart_dev);
86 static void uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br);
87 static void uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate);
90 #define UART_NUM_UARTS 2 91 static uint16_t tx_fifo_size[UART_NUM_UARTS] = { 0 };
92 static uint8_t active_uarts[UART_NUM_UARTS] = { 0 };
94 static int(*uart_input[UART_NUM_UARTS]) (
unsigned char) = { 0 };
96 static uint16_t uart_char_delay = 0;
97 static volatile int8_t interrupt_enabled[UART_NUM_UARTS] = { 0 };
98 static volatile int8_t interrupt_enabled_saved[UART_NUM_UARTS] = { 0 };
123 uart_driver_init(uint8_t uart_dev, uint8_t br, uint8_t *txbuf_data,
124 uint16_t txbuf_size, uint8_t *rxbuf_data, uint16_t rxbuf_size,
125 int (*uart_input_function)(
unsigned char c))
127 #if !UART_HW_FLOW_CTRL 129 vAHI_UartSetRTSCTS(uart_dev, FALSE);
132 tx_fifo_size[uart_dev] = txbuf_size;
135 uint8_t uart_enabled = bAHI_UartEnable(uart_dev, txbuf_data, txbuf_size,
136 rxbuf_data, rxbuf_size);
139 vAHI_UartEnable(uart_dev);
140 tx_fifo_size[uart_dev] = 16;
143 vAHI_UartReset(uart_dev, TRUE, TRUE);
144 vAHI_UartReset(uart_dev, FALSE, FALSE);
146 uart_driver_set_baudrate(uart_dev, br);
149 if(uart_dev == E_AHI_UART_0) {
150 vAHI_Uart0RegisterCallback((
void *)uart_driver_isr);
152 vAHI_Uart1RegisterCallback((
void *)uart_driver_isr);
155 uart_driver_enable_interrupts(uart_dev);
156 uart_input[uart_dev] = uart_input_function;
157 active_uarts[uart_dev] = 1;
159 #if UART_HW_FLOW_CTRL 161 vAHI_UartSetAutoFlowCtrl(uart_dev, E_AHI_UART_FIFO_ARTS_LEVEL_13,
167 DBG_vPrintf(
"UART %d init: using %s buffers %d\n", uart_dev,
168 uart_enabled ?
"external" :
"internal", tx_fifo_size[uart_dev]);
171 uart_driver_enable_interrupts(uint8_t uart_dev)
174 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
176 vAHI_UartSetInterrupt(uart_dev, FALSE ,
179 TRUE , E_AHI_UART_FIFO_LEVEL_14);
180 interrupt_enabled[uart_dev] = 1;
183 uart_driver_disable_interrupts(uint8_t uart_dev)
186 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
188 vAHI_UartSetInterrupt(uart_dev, FALSE ,
191 FALSE , E_AHI_UART_FIFO_LEVEL_14);
192 interrupt_enabled[uart_dev] = 0;
195 uart_driver_store_interrupts(uint8_t uart_dev)
197 interrupt_enabled_saved[uart_dev] = interrupt_enabled[uart_dev];
200 uart_driver_restore_interrupts(uint8_t uart_dev)
202 if(interrupt_enabled_saved[uart_dev]) {
203 uart_driver_enable_interrupts(uart_dev);
205 uart_driver_disable_interrupts(uart_dev);
209 uart_driver_interrupt_is_enabled(uint8_t uart_dev)
211 return interrupt_enabled[uart_dev];
214 uart_driver_set_input(uint8_t uart_dev,
int 215 (*uart_input_function)(
unsigned char c))
217 uart_input[uart_dev] = uart_input_function;
235 uart_driver_read(uint8_t uart_dev, uint8_t *data)
237 if(data && u16AHI_UartReadRxFifoLevel(uart_dev) > 0) {
238 *data = u8AHI_UartReadData(uart_dev);
244 uart_driver_write_buffered(uint8_t uart_dev, uint8_t ch)
246 uart_driver_write_with_deadline(uart_dev, ch);
264 uart_driver_write_with_deadline(uint8_t uart_dev, uint8_t ch)
266 #if UART_XONXOFF_FLOW_CTRL 269 while(xonxoff_state != XON
270 || u16AHI_UartReadTxFifoLevel(uart_dev) > TX_FIFO_SW_FLOW_LIMIT) {
274 vAHI_UartWriteData(uart_dev, ch);
276 volatile int16_t write = 0;
279 BUSYWAIT_UNTIL(write = (uart_driver_get_tx_fifo_available_space(uart_dev) > 0),
284 vAHI_UartWriteData(uart_dev, ch);
289 uart_driver_write_direct(uint8_t uart_dev, uint8_t ch)
292 vAHI_UartWriteData(uart_dev, ch);
294 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
295 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) == 0) ;
314 uart_driver_rx_handler(uint8_t uart_dev)
324 #if UART_XONXOFF_FLOW_CTRL 326 int xonxoff_state_old = xonxoff_state;
330 while(u16AHI_UartReadRxFifoLevel(uart_dev) > 0 && c++ < 32 && status == 0) {
331 if(uart_input[uart_dev] != NULL) {
334 status = (uart_input[uart_dev])(u8AHI_UartReadData(uart_dev));
336 #if UART_XONXOFF_FLOW_CTRL 338 if(xonxoff_state == XOFF) {
343 }
else if(xonxoff_state_old == XOFF && xonxoff_state == XON) {
350 u8AHI_UartReadData(uart_dev);
358 #if !UART_XONXOFF_FLOW_CTRL 361 uart_driver_get_tx_fifo_available_space(uint8_t uart_dev)
363 return tx_fifo_size[uart_dev] - u16AHI_UartReadTxFifoLevel(uart_dev);
369 uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br)
371 uint32_t high_br = 0;
376 low_br = E_AHI_UART_RATE_4800;
377 uart_char_delay = 1667;
380 low_br = E_AHI_UART_RATE_9600;
381 uart_char_delay = 834;
383 case UART_RATE_19200:
384 low_br = E_AHI_UART_RATE_19200;
385 uart_char_delay = 417;
387 case UART_RATE_38400:
388 low_br = E_AHI_UART_RATE_38400;
389 uart_char_delay = 209;
391 case UART_RATE_76800:
392 low_br = E_AHI_UART_RATE_76800;
393 uart_char_delay = 105;
395 case UART_RATE_115200:
396 low_br = E_AHI_UART_RATE_115200;
397 uart_char_delay = 69;
399 case UART_RATE_230400:
401 uart_char_delay = 35;
403 case UART_RATE_460800:
405 uart_char_delay = 18;
407 case UART_RATE_500000:
409 uart_char_delay = 16;
411 case UART_RATE_576000:
413 uart_char_delay = 14;
415 case UART_RATE_921600:
419 case UART_RATE_1000000:
429 vAHI_UartSetClockDivisor(uart_dev, low_br);
431 uart_driver_set_high_baudrate(uart_dev, high_br);
450 uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate)
452 uint16 u16Divisor = 1;
453 uint32_t u32Remainder;
454 uint8_t u8ClocksPerBit = 16;
456 #if (ENABLE_ADVANCED_BAUD_SELECTION) 461 uint32_t u32CalcBaudRate = 0;
462 int32 i32BaudError = 0x7FFFFFFF;
464 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Config uart=%d, baud=%d\n", uart_dev,
467 while(ABS(i32BaudError) > (int32)(baud_rate >> 4)) {
468 if(--u8ClocksPerBit < 3) {
469 DBG_vPrintf(DEBUG_UART_BUFFERED,
470 "Could not calculate UART settings for target baud!");
476 u16Divisor = (uint16)(16000000UL / ((u8ClocksPerBit + 1) * baud_rate));
480 (uint32_t)(16000000UL % ((u8ClocksPerBit + 1) * baud_rate));
482 if(u32Remainder >= (((u8ClocksPerBit + 1) * baud_rate) / 2)) {
485 #if (ENABLE_ADVANCED_BAUD_SELECTION) 486 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Divisor=%d, cpb=%d\n", u16Divisor,
489 u32CalcBaudRate = (16000000UL / ((u8ClocksPerBit + 1) * u16Divisor));
491 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Calculated baud=%d\n", u32CalcBaudRate);
493 i32BaudError = (int32)u32CalcBaudRate - (int32)baud_rate;
495 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Error baud=%d\n", i32BaudError);
497 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Config uart=%d: Divisor=%d, cpb=%d\n",
498 uart_dev, u16Divisor, u8ClocksPerBit);
501 vAHI_UartSetClocksPerBit(uart_dev, u8ClocksPerBit);
505 vAHI_UartSetBaudDivisor(uart_dev, u16Divisor);
526 uart_driver_isr(uint32_t device_id, uint32_t item_bitmap)
530 case E_AHI_DEVICE_UART0:
531 uart_dev = E_AHI_UART_0;
533 case E_AHI_DEVICE_UART1:
534 uart_dev = E_AHI_UART_1;
539 switch(item_bitmap) {
541 case E_AHI_UART_INT_TIMEOUT:
543 case E_AHI_UART_INT_RXDATA:
544 uart_driver_rx_handler(uart_dev);
546 case E_AHI_UART_INT_TX:
548 case E_AHI_UART_INT_RXLINE:
571 uart_driver_tx_in_progress(uint8_t uart_dev)
574 if(u16AHI_UartReadTxFifoLevel(uart_dev) == 0) {
575 if((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) != 0) {
600 uart_driver_flush(uint8_t uart_dev, bool_t reset_tx, bool_t reset_rx)
603 uart_driver_disable_interrupts(uart_dev);
606 vAHI_UartReset(uart_dev, reset_tx, reset_rx);
607 vAHI_UartReset(uart_dev, FALSE, FALSE);
610 uart_driver_enable_interrupts(uart_dev);
Header file for the dbg-io module.
Header file for the real-time timer module.
Header file for the Contiki process interface.
void watchdog_periodic(void)
Writes the WDT clear sequence.