Appiko
uart_printf.c
1 
19 #include "nrf.h"
20 #include "uart_printf.h"
21 #include "hal_gpio.h"
22 #include "boards.h"
23 #include "nrf_util.h"
24 #include "tinyprintf.h"
25 #include <stdbool.h>
26 
27 #if ISR_MANAGER == 1
28 #include "isr_manager.h"
29 #endif
30 
31 #define UARTE_ID CONCAT_2(NRF_UARTE,UARTE_USED_UART_PRINTF)
32 
34 #define BUFFER_SIZE 128
35 
36 typedef enum
37 {
38  PING,
39  PONG
40 } uart_buffers;
41 
42 typedef enum
43 {
44  PING_DONE,
45  PING_TX,
46  PONG_DONE,
47  PONG_TX,
48 } uart_tx_states;
49 
50 typedef enum
51 {
52  EMPTY,
53  FILLING,
54  FILLED
55 } uart_buffer_states;
56 
57 static const struct buffer_state
58 {
59  uart_tx_states DONE;
60  uart_tx_states TX;
61 } BUF_STATE[2] = {{ PING_DONE, PING_TX },
62  { PONG_DONE, PONG_TX } };
63 
64 struct uart_tx_buffer
65 {
66  uint8_t __attribute__((aligned(32))) buf[BUFFER_SIZE];
67  uint32_t count;
68  uart_buffer_states state;
69 };
70 
71 static struct uart_context
72 {
73  volatile struct uart_tx_buffer tx_buf[2];
74  volatile uart_tx_states tx_state;
75 } uart_ctx = { { { { 0 }, 0, EMPTY }, { { 0 }, 0, EMPTY } }, PING_DONE };
76 
77 static void stop_uart(void)
78 {
79  UARTE_ID->TASKS_STOPTX = 1;
80 }
81 
82 static void start_uart_tx(uart_buffers tx_buf)
83 {
84  UARTE_ID->EVENTS_ENDTX = 0;
85 
86  UARTE_ID->TXD.PTR = (uint32_t) uart_ctx.tx_buf[tx_buf].buf;
87  UARTE_ID->TXD.MAXCNT = uart_ctx.tx_buf[tx_buf].count;
88 
89  UARTE_ID->TASKS_STARTTX = 1;
90 }
91 
95 #if ISR_MANAGER == 1
96 void uart_printf_uart_Handler (void)
97 #else
98 void UARTE0_UART0_IRQHandler(void)
99 #endif
100 {
101  if (1 == UARTE_ID->EVENTS_ENDTX)
102  {
103 #if ISR_MANAGER == 0
104  UARTE_ID->EVENTS_ENDTX = 0;
105  (void) UARTE_ID->EVENTS_ENDTX;
106 #endif
107  uart_buffers current_buf = PONG, other_buf = PING;
108  if (BUF_STATE[PING].TX == uart_ctx.tx_state)
109  {
110  current_buf = PING;
111  other_buf = PONG;
112  } // Else state of PONG_TX is taken care of in initialization
113 
114  uart_ctx.tx_buf[current_buf].state = EMPTY;
115  uart_ctx.tx_buf[current_buf].count = 0;
116 
117  if (FILLED == uart_ctx.tx_buf[other_buf].state)
118  {
119  start_uart_tx(other_buf);
120  uart_ctx.tx_state = BUF_STATE[other_buf].TX;
121  }
122  else
123  {
124  uart_ctx.tx_state = BUF_STATE[current_buf].DONE;
125  stop_uart(); //So that UARTE doesn't consume power
126  }
127  }
128 }
129 
132 void printf_callback(void* str_end, char ch)
133 {
134  uart_buffers current_buf = PONG, other_buf = PING;
135  if ((BUF_STATE[PING].TX == uart_ctx.tx_state) || (BUF_STATE[PING].DONE == uart_ctx.tx_state))
136  {
137  current_buf = PING;
138  other_buf = PONG;
139  }
140 
141  //Callback informing the end of the printf string
142  if (START_TX == ((uint32_t) str_end))
143  {
144  if (PING_DONE == uart_ctx.tx_state)
145  {
146  start_uart_tx(PONG);
147  uart_ctx.tx_state = PONG_TX;
148  }
149  if (PONG_DONE == uart_ctx.tx_state)
150  {
151  start_uart_tx(PING);
152  uart_ctx.tx_state = PING_TX;
153  }
154  uart_ctx.tx_buf[other_buf].state = FILLED;
155 
156  }
157  else
158  {
159  // Check for exceeding the buffer size
160  if (uart_ctx.tx_buf[other_buf].count < BUFFER_SIZE)
161  {
162  uart_ctx.tx_buf[other_buf].buf[uart_ctx.tx_buf[other_buf].count] = ch;
163  uart_ctx.tx_buf[other_buf].count++;
164  uart_ctx.tx_buf[other_buf].state = FILLING;
165  }
166  else
167  {
168  while (BUF_STATE[current_buf].TX == uart_ctx.tx_state)
169  {
170  //__WFI();
171  }
172  start_uart_tx(other_buf);
173  uart_ctx.tx_buf[other_buf].state = FILLED; // Not required, but just for completeness
174  uart_ctx.tx_state = BUF_STATE[other_buf].TX;
175  }
176  }
177 }
178 
180 {
181  /* Configure TX and RX pins from board.h */
182  hal_gpio_cfg_output(TX_PIN_NUMBER, 0);
183  hal_gpio_cfg_input(RX_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
184  UARTE_ID->PSEL.TXD = TX_PIN_NUMBER;
185  UARTE_ID->PSEL.RXD = RX_PIN_NUMBER;
186 
187  /* Configure CTS and RTS pins if HWFC is true in board.h */
188 
189 #if HWFC
190  {
191  hal_gpio_cfg_output(RTS_PIN_NUMBER, 0);
192  hal_gpio_cfg_input(CTS_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
193  UARTE_ID->PSEL.RTS = RTS_PIN_NUMBER;
194  UARTE_ID->PSEL.CTS = CTS_PIN_NUMBER;
195  UARTE_ID->CONFIG = (UARTE_CONFIG_HWFC_Enabled << UARTE_CONFIG_HWFC_Pos);
196  }
197 #endif
198 
199  /* Configure other UART parameters, BAUD rate is defined in nrf52-uart.h */
200  UARTE_ID->BAUDRATE = (baud_rate << UARTE_BAUDRATE_BAUDRATE_Pos);
201  UARTE_ID->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos);
202 
203  //Send in any other value other than START_TX in first argument
204  init_printf((void *) !(START_TX), printf_callback);
205 
206  // Enable UART TX End interrupt only
207  UARTE_ID->INTENSET = (UARTE_INTENSET_ENDTX_Set << UARTE_INTENSET_ENDTX_Pos);
208 
209  NVIC_SetPriority(UARTE0_UART0_IRQn, APP_IRQ_PRIORITY_LOW);
210  NVIC_EnableIRQ(UARTE0_UART0_IRQn);
211 
212 }
uart_printf_baud_t
Definition: uart_printf.h:51
Strcture for Operation time.
Definition: sensepi_ble.h:38
void uart_printf_init(uart_printf_baud_t baud_rate)
Function to initialize the parameters of UART based on the configurations in boards....
Definition: uart_printf.c:179