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;
69 #define DEBUG_UART_BUFFERED FALSE 71 #define CHAR_DEADLINE (uart_char_delay * 100) 74 static void uart_driver_isr(uint32_t device_id, uint32_t item_bitmap);
75 #if !UART_XONXOFF_FLOW_CTRL 76 static int16_t uart_driver_get_tx_fifo_available_space(uint8_t uart_dev);
78 static void uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br);
79 static void uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate);
82 #define UART_NUM_UARTS 2 83 static uint16_t tx_fifo_size[UART_NUM_UARTS] = { 0 };
84 static uint8_t active_uarts[UART_NUM_UARTS] = { 0 };
86 static int(*uart_input[UART_NUM_UARTS]) (
unsigned char) = { 0 };
88 static uint16_t uart_char_delay = 0;
89 static volatile int8_t interrupt_enabled[UART_NUM_UARTS] = { 0 };
90 static volatile int8_t interrupt_enabled_saved[UART_NUM_UARTS] = { 0 };
115 uart_driver_init(uint8_t uart_dev, uint8_t br, uint8_t *txbuf_data,
116 uint16_t txbuf_size, uint8_t *rxbuf_data, uint16_t rxbuf_size,
117 int (*uart_input_function)(
unsigned char c))
119 #if !UART_HW_FLOW_CTRL 121 vAHI_UartSetRTSCTS(uart_dev, FALSE);
124 tx_fifo_size[uart_dev] = txbuf_size;
127 uint8_t uart_enabled = bAHI_UartEnable(uart_dev, txbuf_data, txbuf_size,
128 rxbuf_data, rxbuf_size);
131 vAHI_UartEnable(uart_dev);
132 tx_fifo_size[uart_dev] = 16;
135 vAHI_UartReset(uart_dev, TRUE, TRUE);
136 vAHI_UartReset(uart_dev, FALSE, FALSE);
138 uart_driver_set_baudrate(uart_dev, br);
141 if(uart_dev == E_AHI_UART_0) {
142 vAHI_Uart0RegisterCallback((
void *)uart_driver_isr);
144 vAHI_Uart1RegisterCallback((
void *)uart_driver_isr);
147 uart_driver_enable_interrupts(uart_dev);
148 uart_input[uart_dev] = uart_input_function;
149 active_uarts[uart_dev] = 1;
151 #if UART_HW_FLOW_CTRL 153 vAHI_UartSetAutoFlowCtrl(uart_dev, E_AHI_UART_FIFO_ARTS_LEVEL_13,
159 DBG_vPrintf(
"UART %d init: using %s buffers %d\n", uart_dev,
160 uart_enabled ?
"external" :
"internal", tx_fifo_size[uart_dev]);
163 uart_driver_enable_interrupts(uint8_t uart_dev)
166 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
168 vAHI_UartSetInterrupt(uart_dev, FALSE ,
171 TRUE , E_AHI_UART_FIFO_LEVEL_14);
172 interrupt_enabled[uart_dev] = 1;
175 uart_driver_disable_interrupts(uint8_t uart_dev)
178 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
180 vAHI_UartSetInterrupt(uart_dev, FALSE ,
183 FALSE , E_AHI_UART_FIFO_LEVEL_14);
184 interrupt_enabled[uart_dev] = 0;
187 uart_driver_store_interrupts(uint8_t uart_dev)
189 interrupt_enabled_saved[uart_dev] = interrupt_enabled[uart_dev];
192 uart_driver_restore_interrupts(uint8_t uart_dev)
194 if(interrupt_enabled_saved[uart_dev]) {
195 uart_driver_enable_interrupts(uart_dev);
197 uart_driver_disable_interrupts(uart_dev);
201 uart_driver_interrupt_is_enabled(uint8_t uart_dev)
203 return interrupt_enabled[uart_dev];
206 uart_driver_set_input(uint8_t uart_dev,
int 207 (*uart_input_function)(
unsigned char c))
209 uart_input[uart_dev] = uart_input_function;
227 uart_driver_read(uint8_t uart_dev, uint8_t *data)
229 if(data && u16AHI_UartReadRxFifoLevel(uart_dev) > 0) {
230 *data = u8AHI_UartReadData(uart_dev);
236 uart_driver_write_buffered(uint8_t uart_dev, uint8_t ch)
238 uart_driver_write_with_deadline(uart_dev, ch);
256 uart_driver_write_with_deadline(uint8_t uart_dev, uint8_t ch)
258 #if UART_XONXOFF_FLOW_CTRL 261 while(xonxoff_state != XON
262 || u16AHI_UartReadTxFifoLevel(uart_dev) > TX_FIFO_SW_FLOW_LIMIT) {
266 vAHI_UartWriteData(uart_dev, ch);
268 volatile int16_t write = 0;
276 vAHI_UartWriteData(uart_dev, ch);
281 uart_driver_write_direct(uint8_t uart_dev, uint8_t ch)
284 vAHI_UartWriteData(uart_dev, ch);
286 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
287 while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) == 0) ;
306 uart_driver_rx_handler(uint8_t uart_dev)
316 #if UART_XONXOFF_FLOW_CTRL 318 int xonxoff_state_old = xonxoff_state;
322 while(u16AHI_UartReadRxFifoLevel(uart_dev) > 0 && c++ < 32 && status == 0) {
323 if(uart_input[uart_dev] != NULL) {
326 status = (uart_input[uart_dev])(u8AHI_UartReadData(uart_dev));
328 #if UART_XONXOFF_FLOW_CTRL 330 if(xonxoff_state == XOFF) {
335 }
else if(xonxoff_state_old == XOFF && xonxoff_state == XON) {
342 u8AHI_UartReadData(uart_dev);
350 #if !UART_XONXOFF_FLOW_CTRL 353 uart_driver_get_tx_fifo_available_space(uint8_t uart_dev)
355 return tx_fifo_size[uart_dev] - u16AHI_UartReadTxFifoLevel(uart_dev);
361 uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br)
363 uint32_t high_br = 0;
368 low_br = E_AHI_UART_RATE_4800;
369 uart_char_delay = 1667;
372 low_br = E_AHI_UART_RATE_9600;
373 uart_char_delay = 834;
375 case UART_RATE_19200:
376 low_br = E_AHI_UART_RATE_19200;
377 uart_char_delay = 417;
379 case UART_RATE_38400:
380 low_br = E_AHI_UART_RATE_38400;
381 uart_char_delay = 209;
383 case UART_RATE_76800:
384 low_br = E_AHI_UART_RATE_76800;
385 uart_char_delay = 105;
387 case UART_RATE_115200:
388 low_br = E_AHI_UART_RATE_115200;
389 uart_char_delay = 69;
391 case UART_RATE_230400:
393 uart_char_delay = 35;
395 case UART_RATE_460800:
397 uart_char_delay = 18;
399 case UART_RATE_500000:
401 uart_char_delay = 16;
403 case UART_RATE_576000:
405 uart_char_delay = 14;
407 case UART_RATE_921600:
411 case UART_RATE_1000000:
421 vAHI_UartSetClockDivisor(uart_dev, low_br);
423 uart_driver_set_high_baudrate(uart_dev, high_br);
442 uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate)
444 uint16 u16Divisor = 1;
445 uint32_t u32Remainder;
446 uint8_t u8ClocksPerBit = 16;
448 #if (ENABLE_ADVANCED_BAUD_SELECTION) 453 uint32_t u32CalcBaudRate = 0;
454 int32 i32BaudError = 0x7FFFFFFF;
456 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Config uart=%d, baud=%d\n", uart_dev,
459 while(ABS(i32BaudError) > (int32)(baud_rate >> 4)) {
460 if(--u8ClocksPerBit < 3) {
461 DBG_vPrintf(DEBUG_UART_BUFFERED,
462 "Could not calculate UART settings for target baud!");
468 u16Divisor = (uint16)(16000000UL / ((u8ClocksPerBit + 1) * baud_rate));
472 (uint32_t)(16000000UL % ((u8ClocksPerBit + 1) * baud_rate));
474 if(u32Remainder >= (((u8ClocksPerBit + 1) * baud_rate) / 2)) {
477 #if (ENABLE_ADVANCED_BAUD_SELECTION) 478 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Divisor=%d, cpb=%d\n", u16Divisor,
481 u32CalcBaudRate = (16000000UL / ((u8ClocksPerBit + 1) * u16Divisor));
483 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Calculated baud=%d\n", u32CalcBaudRate);
485 i32BaudError = (int32)u32CalcBaudRate - (int32)baud_rate;
487 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Error baud=%d\n", i32BaudError);
489 DBG_vPrintf(DEBUG_UART_BUFFERED,
"Config uart=%d: Divisor=%d, cpb=%d\n",
490 uart_dev, u16Divisor, u8ClocksPerBit);
493 vAHI_UartSetClocksPerBit(uart_dev, u8ClocksPerBit);
497 vAHI_UartSetBaudDivisor(uart_dev, u16Divisor);
518 uart_driver_isr(uint32_t device_id, uint32_t item_bitmap)
522 case E_AHI_DEVICE_UART0:
523 uart_dev = E_AHI_UART_0;
525 case E_AHI_DEVICE_UART1:
526 uart_dev = E_AHI_UART_1;
531 switch(item_bitmap) {
533 case E_AHI_UART_INT_TIMEOUT:
535 case E_AHI_UART_INT_RXDATA:
536 uart_driver_rx_handler(uart_dev);
538 case E_AHI_UART_INT_TX:
540 case E_AHI_UART_INT_RXLINE:
563 uart_driver_tx_in_progress(uint8_t uart_dev)
566 if(u16AHI_UartReadTxFifoLevel(uart_dev) == 0) {
567 if((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) != 0) {
592 uart_driver_flush(uint8_t uart_dev, bool_t reset_tx, bool_t reset_rx)
595 uart_driver_disable_interrupts(uart_dev);
598 vAHI_UartReset(uart_dev, reset_tx, reset_rx);
599 vAHI_UartReset(uart_dev, FALSE, FALSE);
602 uart_driver_enable_interrupts(uart_dev);
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
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.