44 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55 */
66
7- #include <stdbool.h>
87#include <nrf_rpc.h>
98#include <nrf_rpc_tr.h>
109#include <nrf_rpc/nrf_rpc_uart.h>
1110#include <nrf_rpc_errno.h>
12- #include <sys/_stdint.h>
11+
1312#include <zephyr/drivers/uart.h>
13+ #include <zephyr/logging/log.h>
1414#include <zephyr/sys/util.h>
1515#include <zephyr/sys/byteorder.h>
1616#include <zephyr/sys/crc.h>
1717
18- #include <zephyr/logging/log.h>
19-
2018LOG_MODULE_REGISTER (nrf_rpc_uart , CONFIG_NRF_RPC_TR_LOG_LEVEL );
2119
2220enum {
23- /* TODO: check if we need handle other special values like XON or XOFF */
24- hdlc_char_escape = 0x7d ,
25- hdlc_char_delimiter = 0x7e ,
21+ HDLC_CHAR_ESCAPE = 0x7d ,
22+ HDLC_CHAR_DELIMITER = 0x7e ,
23+ };
24+
25+ typedef enum {
26+ HDLC_STATE_UNSYNC ,
27+ HDLC_STATE_FRAME_START ,
28+ HDLC_STATE_FRAME_FOUND ,
29+ HDLC_STATE_ESCAPE ,
30+ } hdlc_state_t ;
31+
32+ struct nrf_rpc_uart {
33+ const struct device * uart ;
34+ nrf_rpc_tr_receive_handler_t receive_callback ;
35+ void * receive_ctx ;
36+ const struct nrf_rpc_tr * transport ;
37+
38+ /* RX ring buffer populated by UART ISR */
39+ uint8_t rx_buffer [CONFIG_NRF_RPC_UART_RX_RINGBUF_SIZE ];
40+ struct ring_buf rx_ringbuf ;
41+
42+ /* RX work to consume and decode bytes from RX ring buffer */
43+ struct k_work rx_work ;
44+ struct k_work_q rx_workq ;
45+
46+ K_KERNEL_STACK_MEMBER (rx_workq_stack , CONFIG_NRF_RPC_UART_RX_THREAD_STACK_SIZE );
47+
48+ /* HDLC frame parsing state */
49+ hdlc_state_t hdlc_state ;
50+ uint8_t rx_packet [CONFIG_NRF_RPC_UART_MAX_PACKET_SIZE ];
51+ size_t rx_packet_len ;
52+
53+ /* TX lock */
54+ struct k_mutex tx_lock ;
2655};
2756
2857#define CRC_SIZE sizeof(uint16_t)
2958
30- static int hdlc_input_byte (struct nrf_rpc_uart * uart_tr , uint8_t byte )
59+ static int hdlc_decode_byte (struct nrf_rpc_uart * uart_tr , uint8_t byte )
3160{
3261 /* TODO: handle frame buffer overflow */
3362
34- if (uart_tr -> hdlc_state == hdlc_state_escape ) {
35- uart_tr -> frame_buffer [uart_tr -> frame_len ++ ] = byte ^ 0x20 ;
36- uart_tr -> hdlc_state = hdlc_state_frame_start ;
37- } else if (byte == hdlc_char_escape ) {
38- uart_tr -> hdlc_state = hdlc_state_escape ;
39- } else if (byte == hdlc_char_delimiter ) {
40- uart_tr -> hdlc_state = (uart_tr -> hdlc_state == hdlc_state_frame_start )
41- ? hdlc_state_frame_found
42- : hdlc_state_unsync ;
63+ if (uart_tr -> hdlc_state == HDLC_STATE_ESCAPE ) {
64+ uart_tr -> rx_packet [uart_tr -> rx_packet_len ++ ] = byte ^ 0x20 ;
65+ uart_tr -> hdlc_state = HDLC_STATE_FRAME_START ;
66+ } else if (byte == HDLC_CHAR_ESCAPE ) {
67+ uart_tr -> hdlc_state = HDLC_STATE_ESCAPE ;
68+ } else if (byte == HDLC_CHAR_DELIMITER ) {
69+ uart_tr -> hdlc_state = (uart_tr -> hdlc_state == HDLC_STATE_FRAME_START )
70+ ? HDLC_STATE_FRAME_FOUND
71+ : HDLC_STATE_UNSYNC ;
4372 } else {
44- uart_tr -> frame_buffer [uart_tr -> frame_len ++ ] = byte ;
45- uart_tr -> hdlc_state = hdlc_state_frame_start ;
73+ uart_tr -> rx_packet [uart_tr -> rx_packet_len ++ ] = byte ;
74+ uart_tr -> hdlc_state = HDLC_STATE_FRAME_START ;
4675 }
4776
48- if (uart_tr -> hdlc_state == hdlc_state_frame_found ) {
49- LOG_HEXDUMP_DBG (uart_tr -> frame_buffer , uart_tr -> frame_len , "Received frame" );
50- if (uart_tr -> frame_len > CRC_SIZE ) {
51- uart_tr -> frame_len -= CRC_SIZE ;
77+ if (uart_tr -> hdlc_state == HDLC_STATE_FRAME_FOUND ) {
78+ LOG_HEXDUMP_DBG (uart_tr -> rx_packet , uart_tr -> rx_packet_len , "Received frame" );
79+ if (uart_tr -> rx_packet_len > CRC_SIZE ) {
80+ uart_tr -> rx_packet_len -= CRC_SIZE ;
5281 } else {
53- uart_tr -> frame_len = 0 ;
54- uart_tr -> hdlc_state = hdlc_state_unsync ;
82+ uart_tr -> rx_packet_len = 0 ;
83+ uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
5584 }
5685 }
5786
@@ -60,7 +89,7 @@ static int hdlc_input_byte(struct nrf_rpc_uart *uart_tr, uint8_t byte)
6089
6190static void work_handler (struct k_work * work )
6291{
63- struct nrf_rpc_uart * uart_tr = CONTAINER_OF (work , struct nrf_rpc_uart , cb_work );
92+ struct nrf_rpc_uart * uart_tr = CONTAINER_OF (work , struct nrf_rpc_uart , rx_work );
6493 const struct nrf_rpc_tr * transport = uart_tr -> transport ;
6594 uint8_t * data ;
6695 size_t len ;
@@ -69,30 +98,32 @@ static void work_handler(struct k_work *work)
6998 uint16_t crc_calculated = 0 ;
7099
71100 while (!ring_buf_is_empty (& uart_tr -> rx_ringbuf )) {
72- len = ring_buf_get_claim (& uart_tr -> rx_ringbuf , & data , NRF_RPC_MAX_FRAME_SIZE );
101+ len = ring_buf_get_claim (& uart_tr -> rx_ringbuf , & data ,
102+ CONFIG_NRF_RPC_UART_MAX_PACKET_SIZE );
73103 for (size_t i = 0 ; i < len ; i ++ ) {
74- if (hdlc_input_byte (uart_tr , data [i ]) == 0 ) {
75-
76- if (uart_tr -> hdlc_state == hdlc_state_frame_found ) {
77- crc_received = sys_get_le16 (uart_tr -> frame_buffer +
78- uart_tr -> frame_len );
79- crc_calculated = crc16_ccitt (0xffff , uart_tr -> frame_buffer ,
80- uart_tr -> frame_len );
81- if (crc_calculated != crc_received ) {
82- LOG_ERR ("Invalid CRC, calculated %x received %x" ,
83- crc_calculated , crc_received );
84- uart_tr -> frame_len = 0 ;
85- uart_tr -> hdlc_state = hdlc_state_unsync ;
86- return ;
87- }
88-
89- uart_tr -> receive_callback (transport , uart_tr -> frame_buffer ,
90- uart_tr -> frame_len ,
91- uart_tr -> receive_ctx );
92- uart_tr -> frame_len = 0 ;
93- uart_tr -> hdlc_state = hdlc_state_unsync ;
94- }
104+ if (hdlc_decode_byte (uart_tr , data [i ]) != 0 ) {
105+ continue ;
106+ }
107+
108+ if (uart_tr -> hdlc_state != HDLC_STATE_FRAME_FOUND ) {
109+ continue ;
110+ }
111+
112+ crc_received = sys_get_le16 (uart_tr -> rx_packet + uart_tr -> rx_packet_len );
113+ crc_calculated =
114+ crc16_ccitt (0xffff , uart_tr -> rx_packet , uart_tr -> rx_packet_len );
115+ if (crc_calculated != crc_received ) {
116+ LOG_ERR ("Invalid CRC, calculated %x received %x" , crc_calculated ,
117+ crc_received );
118+ uart_tr -> rx_packet_len = 0 ;
119+ uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
120+ return ;
95121 }
122+
123+ uart_tr -> receive_callback (transport , uart_tr -> rx_packet ,
124+ uart_tr -> rx_packet_len , uart_tr -> receive_ctx );
125+ uart_tr -> rx_packet_len = 0 ;
126+ uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
96127 }
97128
98129 ret = ring_buf_get_finish (& uart_tr -> rx_ringbuf , len );
@@ -133,13 +164,10 @@ static void serial_cb(const struct device *uart, void *user_data)
133164 }
134165
135166 if (new_data ) {
136- k_work_submit_to_queue (& uart_tr -> rx_workq , & uart_tr -> cb_work );
167+ k_work_submit_to_queue (& uart_tr -> rx_workq , & uart_tr -> rx_work );
137168 }
138169}
139170
140- /* TODO: for moving it to uart_tr.*/
141- K_THREAD_STACK_DEFINE (uart_tr_workq_stack_area , 4096 );
142-
143171static int init (const struct nrf_rpc_tr * transport , nrf_rpc_tr_receive_handler_t receive_cb ,
144172 void * context )
145173{
@@ -180,27 +208,26 @@ static int init(const struct nrf_rpc_tr *transport, nrf_rpc_tr_receive_handler_t
180208 return 0 ;
181209 }
182210
183- k_sem_init (& uart_tr -> uart_tx_sem , 1 , 1 );
211+ k_mutex_init (& uart_tr -> tx_lock );
184212
185213 k_work_queue_init (& uart_tr -> rx_workq );
186- k_work_queue_start (& uart_tr -> rx_workq , uart_tr_workq_stack_area ,
187- K_THREAD_STACK_SIZEOF (uart_tr_workq_stack_area ), 0 , NULL );
214+ k_work_queue_start (& uart_tr -> rx_workq , uart_tr -> rx_workq_stack ,
215+ K_THREAD_STACK_SIZEOF (uart_tr -> rx_workq_stack ), K_PRIO_PREEMPT ( 0 ) , NULL );
188216
189- k_work_init (& uart_tr -> cb_work , work_handler );
217+ k_work_init (& uart_tr -> rx_work , work_handler );
190218 ring_buf_init (& uart_tr -> rx_ringbuf , sizeof (uart_tr -> rx_buffer ), uart_tr -> rx_buffer );
191219
192- uart_tr -> hdlc_state = hdlc_state_unsync ;
193- uart_tr -> frame_len = 0 ;
220+ uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
221+ uart_tr -> rx_packet_len = 0 ;
194222 uart_irq_rx_enable (uart_tr -> uart );
195223
196224 return 0 ;
197225}
198226
199227static void send_byte (const struct device * dev , uint8_t byte )
200228{
201-
202- if (byte == hdlc_char_delimiter || byte == hdlc_char_escape ) {
203- uart_poll_out (dev , hdlc_char_escape );
229+ if (byte == HDLC_CHAR_DELIMITER || byte == HDLC_CHAR_ESCAPE ) {
230+ uart_poll_out (dev , HDLC_CHAR_ESCAPE );
204231 byte ^= 0x20 ;
205232 }
206233
@@ -214,9 +241,9 @@ static int send(const struct nrf_rpc_tr *transport, const uint8_t *data, size_t
214241
215242 LOG_HEXDUMP_DBG (data , length , "Sending frame" );
216243
217- k_sem_take (& uart_tr -> uart_tx_sem , K_FOREVER );
244+ k_mutex_lock (& uart_tr -> tx_lock , K_FOREVER );
218245
219- uart_poll_out (uart_tr -> uart , hdlc_char_delimiter );
246+ uart_poll_out (uart_tr -> uart , HDLC_CHAR_DELIMITER );
220247
221248 for (size_t i = 0 ; i < length ; i ++ ) {
222249 send_byte (uart_tr -> uart , data [i ]);
@@ -226,10 +253,11 @@ static int send(const struct nrf_rpc_tr *transport, const uint8_t *data, size_t
226253 send_byte (uart_tr -> uart , crc [0 ]);
227254 send_byte (uart_tr -> uart , crc [1 ]);
228255
229- uart_poll_out (uart_tr -> uart , hdlc_char_delimiter );
256+ uart_poll_out (uart_tr -> uart , HDLC_CHAR_DELIMITER );
230257
231258 k_free ((void * )data );
232- k_sem_give (& uart_tr -> uart_tx_sem );
259+
260+ k_mutex_unlock (& uart_tr -> tx_lock );
233261
234262 return 0 ;
235263}
@@ -255,6 +283,8 @@ static void *tx_buf_alloc(const struct nrf_rpc_tr *transport, size_t *size)
255283
256284static void tx_buf_free (const struct nrf_rpc_tr * transport , void * buf )
257285{
286+ ARG_UNUSED (transport );
287+
258288 k_free (buf );
259289}
260290
0 commit comments