ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_nrf5_sdk15_communication_uart.c
Go to the documentation of this file.
3 #if RUUVI_NRF5_SDK15_UART_ENABLED
4 #include "ruuvi_driver_error.h"
6 #include "ruuvi_interface_log.h"
10 #include "nrf_serial.h"
11 
12 #ifndef RUUVI_NRF5_SDK15_UART_LOG_LEVEL
13 #define LOG_LEVEL RI_LOG_LEVEL_INFO
14 #else
15 #define LOG_LEVEL RUUVI_NRF5_SDK15_UART_LOG_LEVEL
16 #endif
17 #define LOG(msg) (ri_log(LOG_LEVEL, msg))
18 #define LOGD(msg) (ri_log(RI_LOG_LEVEL_DEBUG, msg))
19 
20 static const ri_comm_channel_t * m_channel;
21 static uint16_t m_rxcnt = 0;
22 static uint16_t m_txcnt = 0;
23 
24 static void sleep_handler (void)
25 {
26  ri_yield();
27 }
28 
29 // Handle UART events
30 static void uart_handler (struct nrf_serial_s const * p_serial, nrf_serial_event_t event)
31 {
32  if (m_channel && m_channel->on_evt)
33  {
34  switch (event)
35  {
36  case NRF_SERIAL_EVENT_TX_DONE:
37  LOGD ("TX\r\n");
38 
39  if (0 == (--m_txcnt))
40  {
41  m_channel->on_evt (RI_COMM_SENT, NULL, 0);
42  }
43 
44  break;
45 
46  case NRF_SERIAL_EVENT_RX_DATA:
47  LOGD ("RX\r\n");
48 
49  if ( ( ( (char *) (p_serial->p_ctx->p_config->p_buffers->p_rxb)) [0] == '\n')
50  || ++m_rxcnt >= RI_COMM_MESSAGE_MAX_LENGTH)
51  {
52  ri_comm_message_t msg = {0};
54  m_channel->read (&msg);
55  m_channel->on_evt (RI_COMM_RECEIVED, (void *) &msg.data[0], msg.data_length);
56  }
57 
58  break;
59 
60  case NRF_SERIAL_EVENT_DRV_ERR:
61  LOGD ("UART Error\r\n");
62  break;
63 
64  case NRF_SERIAL_EVENT_FIFO_ERR:
65  LOGD ("FIFO Error\r\n");
66  break;
67 
68  default:
69  LOGD ("UART unknown event\r\n");
70  break;
71  }
72  }
73 }
74 
75 static nrf_drv_uart_config_t m_uart0_drv_config;
76 
77 // FIFOs have a guard byte
78 #define GUARD_SIZE (1U)
79 #define SERIAL_FIFO_TX_SIZE (RI_COMM_MESSAGE_MAX_LENGTH + GUARD_SIZE)
80 #define SERIAL_FIFO_RX_SIZE (RI_COMM_MESSAGE_MAX_LENGTH + GUARD_SIZE)
81 
82 NRF_SERIAL_QUEUES_DEF (serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);
83 
84 
85 #define SERIAL_BUFF_TX_SIZE (1U)
86 #define SERIAL_BUFF_RX_SIZE (1U)
87 
88 NRF_SERIAL_BUFFERS_DEF (serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);
89 
90 NRF_SERIAL_CONFIG_DEF (serial_config, NRF_SERIAL_MODE_DMA,
91  &serial_queues, &serial_buffs, uart_handler, sleep_handler);
92 
93 
94 NRF_SERIAL_UART_DEF (serial_uart, 0);
95 
96 // Convert constants from Ruuvi to nRF52 SDK
97 static nrf_uarte_baudrate_t ruuvi_to_nrf_baudrate (const ri_uart_baudrate_t baud)
98 {
99  switch (baud)
100  {
101  case RI_UART_BAUD_9600:
102  return NRF_UARTE_BAUDRATE_9600;
103 
104  case RI_UART_BAUD_115200:
105  default:
106  return NRF_UARTE_BAUDRATE_115200;
107  }
108 }
109 
110 static rd_status_t ri_uart_send_async (ri_comm_message_t * const msg)
111 {
112  rd_status_t err_code = RD_SUCCESS;
113 
114  if (NULL == msg)
115  {
116  err_code |= RD_ERROR_NULL;
117  }
118 
119  if (1 < msg->repeat_count)
120  {
121  err_code |= RD_ERROR_NOT_SUPPORTED;
122  }
123  else if (0 != m_txcnt)
124  {
125  if (NRF_MTX_LOCKED == serial_uart.p_ctx->write_lock)
126  {
127  err_code |= RD_ERROR_BUSY;
128  }
129  else
130  {
131  m_txcnt = 0;
132  m_channel->on_evt (RI_COMM_SENT, NULL, 0);
133  }
134  }
135  else
136  {
137  nrfx_err_t status = NRF_SUCCESS;
138  size_t written = 0;
139  status |= nrf_serial_write (&serial_uart, msg->data, msg->data_length, &written, 0);
140  m_txcnt = written;
141  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (status);
142 
143  if (written != msg->data_length)
144  {
145  err_code |= RD_ERROR_NO_MEM;
146  }
147  }
148 
149  return err_code;
150 }
151 
152 static rd_status_t ri_uart_read_buf (ri_comm_message_t * const msg)
153 {
154  rd_status_t err_code = RD_SUCCESS;
155 
156  if (NULL == msg)
157  {
158  err_code |= RD_ERROR_NULL;
159  }
160 
161  if (1 < msg->repeat_count)
162  {
163  err_code |= RD_ERROR_NOT_SUPPORTED;
164  }
165  else
166  {
167  nrfx_err_t status = NRF_SUCCESS;
168  size_t bytes_read = nrf_queue_utilization_get (&serial_queues_rxq);
169 
170  if (msg->data_length < bytes_read)
171  {
172  bytes_read = msg->data_length;
173  }
174 
175  status |= nrf_queue_read (&serial_queues_rxq, msg->data, bytes_read);
176  msg->data_length = bytes_read;
177  msg->repeat_count = 1;
178  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (status);
179  m_rxcnt = 0;
180  }
181 
182  return err_code;
183 }
184 
186 {
187  rd_status_t err_code = RD_SUCCESS;
188 
189  if (NULL == channel)
190  {
191  err_code |= RD_ERROR_NULL;
192  }
193  else if (NULL != m_channel)
194  {
195  err_code |= RD_ERROR_INVALID_STATE;
196  }
197  else
198  {
199  channel->send = ri_uart_send_async;
200  channel->read = ri_uart_read_buf;
201  channel->init = ri_uart_init;
202  channel->uninit = ri_uart_uninit;
203  m_channel = channel;
204  }
205 
206  return err_code;
207 }
208 
209 rd_status_t ri_uart_config (const ri_uart_init_t * const config)
210 {
211  rd_status_t err_code = RD_SUCCESS;
212 
213  if (NULL == config)
214  {
215  err_code |= RD_ERROR_NULL;
216  }
217  else
218  {
219  nrfx_err_t nrf_status = NRF_SUCCESS;
220  m_uart0_drv_config.baudrate = ruuvi_to_nrf_baudrate (config->baud);
221  m_uart0_drv_config.pseltxd = ruuvi_to_nrf_pin_map (config->tx);
222  m_uart0_drv_config.pselrxd = ruuvi_to_nrf_pin_map (config->rx);
223 
224  if (config->hwfc_enabled)
225  {
226  m_uart0_drv_config.pselcts = ruuvi_to_nrf_pin_map (config->cts);
227  m_uart0_drv_config.pselrts = ruuvi_to_nrf_pin_map (config->rts);
228  }
229  else
230  {
231  m_uart0_drv_config.pselcts = NRF_UARTE_PSEL_DISCONNECTED;
232  m_uart0_drv_config.pselrts = NRF_UARTE_PSEL_DISCONNECTED;
233  }
234 
235  m_uart0_drv_config.parity = config->parity_enabled ? NRF_UARTE_PARITY_INCLUDED :
236  NRF_UARTE_PARITY_EXCLUDED;
237  m_uart0_drv_config.hwfc = config->hwfc_enabled ? NRF_UARTE_HWFC_ENABLED :
238  NRF_UARTE_HWFC_DISABLED;
239  m_uart0_drv_config.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
240  nrf_status |= nrf_serial_init (&serial_uart, &m_uart0_drv_config, &serial_config);
241  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (nrf_status);
242  }
243 
244  return err_code;
245 }
246 
248 {
249  m_channel = NULL;
250  return nrf_serial_uninit (&serial_uart);
251 }
252 
253 #endif
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
rd_status_t ruuvi_nrf5_sdk15_to_ruuvi_error(const ret_code_t error)
convert nrf5 sdk15 error code into Ruuvi error code.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_NO_MEM
No Memory for operation.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_BUSY
Busy.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
#define RI_COMM_MESSAGE_MAX_LENGTH
The maximum length for the application message for sending over BLE, which depends on whether extende...
@ RI_COMM_RECEIVED
New data received, available to read with read function.
@ RI_COMM_SENT
One queued message was sent with all repetitions.
ri_uart_baudrate_t
Supported baudrates.
@ RI_UART_BAUD_115200
Run at 115200 baud.
@ RI_UART_BAUD_9600
Run at 9600 baud.
rd_status_t ri_uart_uninit(ri_comm_channel_t *const channel)
rd_status_t ri_uart_config(const ri_uart_init_t *const config)
Configure UART.
rd_status_t ri_uart_init(ri_comm_channel_t *const channel)
Initialize UART.
#define LOGD(fmt,...)
rd_status_t ri_yield(void)
Function which will release execution.
control API for communication via outside world
ri_comm_evt_handler_fp_t on_evt
Callback to application-level event handler, must be set in application.
ri_comm_xfer_fp_t send
Asynchronous send function.
ri_comm_init_fp_t init
Initialize and populate channel api control.
ri_comm_init_fp_t uninit
Uninitialize and depopulate channel api control.
ri_comm_xfer_fp_t read
Asynchronous read function.
Application message structure used for communication.
uint8_t data[RI_COMM_MESSAGE_MAX_LENGTH]
Data payload.
uint8_t repeat_count
Number of times to repeat the message,.
uint8_t data_length
Length of data.
UART initialization data.
ri_gpio_id_t rts
RTS pin. Can be RI_GPIO_UNUSED if not using HWFC.
bool hwfc_enabled
True to enable hardware flow control.
bool parity_enabled
True to enable parity.
ri_uart_baudrate_t baud
ri_uart_baudrate_t.
ri_gpio_id_t cts
CTS pin. Can be RI_GPIO_UNUSED if not using HWFC.