Master Thesis  V1.0
Research and Design of Sensor Node for NMSD Treatment
uart.c
Go to the documentation of this file.
1 /***************************************************************************/
9 /*
10  * uart.c
11  *
12  * Created on: Mar 8, 2020
13  * Author: jonac
14  */
15 
16 #include <uart.h>
17 #include "em_usart.h"
18 #include "pinout.h"
19 #include "em_cmu.h"
20 #include "em_gpio.h"
21 #include "ble.h"
22 
23 #include <stdint.h>
24 #include "em_device.h"
25 #include "em_chip.h"
26 #include "em_emu.h"
27 #include "em_cmu.h"
28 #include "em_gpio.h"
29 #include "em_usart.h"
30 #include "bsp.h"
31 
32 #include "debug_dbprint.h"
33 
34 /* Declare a circular buffer structure to use for Rx and Tx queues */
35 #define BUFFERSIZE 256
36 
37 volatile struct circularBuffer
38 {
39  uint8_t data[BUFFERSIZE]; /* data buffer */
40  uint32_t rdI; /* read index */
41  uint32_t wrI; /* write index */
42  uint32_t pendingBytes; /* count of how many bytes are not yet handled */
43  bool overflow; /* buffer overflow indicator */
44 } rxBuf, txBuf = { {0}, 0, 0, 0, false };
45 
46 static USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
47 
48 /**************************************************************************/
57 void uart_Init()
58 {
59 
60  // Enable oscillator to GPIO and USART1 modules
61  CMU_ClockEnable(cmuClock_HFPER, true);
62  CMU_ClockEnable(cmuClock_GPIO, true);
63  CMU_ClockEnable(cmuClock_USART1, true);
64 
65  // set pin modes for UART TX and RX pins
66  GPIO_PinModeSet(BLE_PORT, BLE_PIN_RX, gpioModeInput, 0);
67  GPIO_PinModeSet(BLE_PORT, BLE_PIN_TX, gpioModePushPull, 1);
68 
69  // Initialize USART asynchronous mode and route pins
70  USART_InitAsync(BLE_USART, &init);
71 
72  /* Prepare UART Rx and Tx interrupts */
73  USART_IntClear(BLE_USART, _USART_IFC_MASK);
74  USART_IntEnable(BLE_USART, USART_IEN_RXDATAV);
75  NVIC_ClearPendingIRQ(USART1_RX_IRQn);
76  NVIC_ClearPendingIRQ(USART1_TX_IRQn);
77  NVIC_EnableIRQ(USART1_RX_IRQn);
78  NVIC_EnableIRQ(USART1_TX_IRQn);
79 
80  BLE_USART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC0;
81 
82  /* Enable UART */
83  USART_Enable(BLE_USART, usartEnable);
84 }
85 
86 
87 /****************************************************************************/
94 uint8_t uartGetChar( )
95 {
96  uint8_t ch;
97 
98  /* Check if there is a byte that is ready to be fetched. If no byte is ready, wait for incoming data */
99  if (rxBuf.pendingBytes < 1)
100  {
101  while (rxBuf.pendingBytes < 1) ;
102  }
103 
104  /* Copy data from buffer */
105  ch = rxBuf.data[rxBuf.rdI];
106  rxBuf.rdI = (rxBuf.rdI + 1) % BUFFERSIZE;
107 
108  /* Decrement pending byte counter */
110 
111  return ch;
112 }
113 
114 
115 
116 
117 /****************************************************************************/
121 void uartPutChar(uint8_t ch)
122 {
123  /* Check if Tx queue has room for new data */
124  if ((txBuf.pendingBytes + 1) > BUFFERSIZE)
125  {
126  /* Wait until there is room in queue */
127  while ((txBuf.pendingBytes + 1) > BUFFERSIZE) ;
128  }
129 
130  /* Copy ch into txBuffer */
131  txBuf.data[txBuf.wrI] = ch;
132  txBuf.wrI = (txBuf.wrI + 1) % BUFFERSIZE;
133 
134  /* Increment pending byte counter */
136 
137  /* Enable interrupt on USART TX Buffer*/
138  USART_IntEnable(BLE_USART, USART_IEN_TXBL);
139 }
140 
141 
142 
143 
144 /****************************************************************************/
148 void uartPutData(uint8_t * dataPtr, uint32_t dataLen)
149 {
150  uint32_t i = 0;
151 
152  /* Check if buffer is large enough for data */
153  if (dataLen > BUFFERSIZE)
154  {
155  /* Buffer can never fit the requested amount of data */
156  return;
157  }
158 
159  /* Check if buffer has room for new data */
160  if ((txBuf.pendingBytes + dataLen) > BUFFERSIZE)
161  {
162  /* Wait until room */
163  while ((txBuf.pendingBytes + dataLen) > BUFFERSIZE) ;
164  }
165 
166  /* Fill dataPtr[0:dataLen-1] into txBuffer */
167  while (i < dataLen)
168  {
169  txBuf.data[txBuf.wrI] = *(dataPtr + i);
170  txBuf.wrI = (txBuf.wrI + 1) % BUFFERSIZE;
171  i++;
172  }
173 
174  /* Increment pending byte counter */
175  txBuf.pendingBytes += dataLen;
176 
177  /* Enable interrupt on USART TX Buffer*/
178  USART_IntEnable(BLE_USART, USART_IEN_TXBL);
179 }
180 
181 /****************************************************************************/
185 uint32_t uartGetData(uint8_t * dataPtr, uint32_t dataLen)
186 {
187  uint32_t i = 0;
188 
189  /* Wait until the requested number of bytes are available */
190  if (rxBuf.pendingBytes < dataLen)
191  {
192  while (rxBuf.pendingBytes < dataLen) ;
193  }
194 
195  if (dataLen == 0)
196  {
197  dataLen = rxBuf.pendingBytes;
198  }
199 
200  /* Copy data from Rx buffer to dataPtr */
201  while (i < dataLen)
202  {
203  *(dataPtr + i) = rxBuf.data[rxBuf.rdI];
204  rxBuf.rdI = (rxBuf.rdI + 1) % BUFFERSIZE;
205  i++;
206  }
207 
208  /* Decrement pending byte counter */
209  rxBuf.pendingBytes -= dataLen;
210 
211  return i;
212 }
213 
214 /**************************************************************************/
222 #if DEBUG_DBPRINT == 0 /* DEBUG_DBPRINT */
224 {
225  /* Check for RX data valid interrupt */
226  if (BLE_USART->IF & USART_IF_RXDATAV)
227  {
228  /* Copy data into RX Buffer */
229  uint8_t rxData = USART_Rx(BLE_USART);
230  rxBuf.data[rxBuf.wrI] = rxData;
231  rxBuf.wrI = (rxBuf.wrI + 1) % BUFFERSIZE;
233 
234  /* Flag Rx overflow */
236  {
237  rxBuf.overflow = true;
238  }
239  }
240 }
241 #endif /* DEBUG_DBPRINT */
242 
243 /**************************************************************************/
249 #if DEBUG_DBPRINT == 0 /* DEBUG_DBPRINT */
251 {
252  /* Check TX buffer level status */
253  if (BLE_USART->IF & USART_IF_TXBL)
254  {
255  if (txBuf.pendingBytes > 0)
256  {
257  /* Transmit pending character */
258  USART_Tx(BLE_USART, txBuf.data[txBuf.rdI]);
259  txBuf.rdI = (txBuf.rdI + 1) % BUFFERSIZE;
261  }
262 
263  /* Disable Tx interrupt if no more bytes in queue */
264  if (txBuf.pendingBytes == 0)
265  {
266  USART_IntDisable(BLE_USART, USART_IEN_TXBL);
267  }
268  }
269 }
270 #endif /* DEBUG_DBPRINT */
txBuf
volatile struct circularBuffer txBuf
BLE_PIN_RX
#define BLE_PIN_RX
Definition: ble.h:34
uartPutChar
void uartPutChar(uint8_t ch)
uartPutChar function
Definition: uart.c:121
uartPutData
void uartPutData(uint8_t *dataPtr, uint32_t dataLen)
uartPutData function
Definition: uart.c:148
circularBuffer::wrI
uint32_t wrI
Definition: uart.c:41
circularBuffer::rdI
uint32_t rdI
Definition: uart.c:40
uart_Init
void uart_Init()
UART init.
Definition: uart.c:57
rxBuf
volatile struct circularBuffer rxBuf
circularBuffer::overflow
bool overflow
Definition: uart.c:43
uart.h
UART communication with BLE.
BLE_PORT
#define BLE_PORT
Definition: ble.h:35
USART1_TX_IRQHandler
void USART1_TX_IRQHandler(void)
UART1 TX IRQ Handler.
Definition: uart.c:250
BUFFERSIZE
#define BUFFERSIZE
Definition: uart.c:35
BLE_USART
#define BLE_USART
Definition: ble.h:36
circularBuffer::pendingBytes
uint32_t pendingBytes
Definition: uart.c:42
pinout.h
File to keep track of most the pins used, pins for BLE are in own file BLE.h.
circularBuffer::data
uint8_t data[BUFFERSIZE]
Definition: uart.c:39
uartGetChar
uint8_t uartGetChar()
uartGetChar function
Definition: uart.c:94
BLE_PIN_TX
#define BLE_PIN_TX
Definition: ble.h:33
circularBuffer
Definition: uart.c:37
USART1_RX_IRQHandler
void USART1_RX_IRQHandler(void)
UART1 RX IRQ Handler.
Definition: uart.c:223
debug_dbprint.h
Enable or disable printing to UART with dbprint.
ble.h
Send data via BLE wirelessly.
uartGetData
uint32_t uartGetData(uint8_t *dataPtr, uint32_t dataLen)
uartGetData function
Definition: uart.c:185