@@ -33,12 +33,24 @@ struct trx_flips {
3333 uint16_t last_rx_crc ;
3434};
3535
36- typedef enum {
36+ enum hdlc_state {
37+ /* Ignore incoming bytes until the delimiter is found. */
3738 HDLC_STATE_UNSYNC ,
38- HDLC_STATE_FRAME_START ,
39+ /* Append incoming bytes to the output buffer. */
40+ HDLC_STATE_FRAME ,
41+ /* Found the delimeter when the output buffer was non-empty. */
3942 HDLC_STATE_FRAME_FOUND ,
43+ /* Found the escape byte. Append the following byte XORed with 0x20 to the output buffer. */
4044 HDLC_STATE_ESCAPE ,
41- } hdlc_state_t ;
45+ };
46+
47+ struct hdlc_decode_ctx {
48+ enum hdlc_state state ;
49+ /* The number of bytes of the current packet that have been decoded so far. */
50+ uint16_t len ;
51+ /* The capacity of the buffer to store a decoded packet. */
52+ uint16_t capacity ;
53+ };
4254
4355struct nrf_rpc_uart {
4456 const struct device * uart ;
@@ -56,10 +68,9 @@ struct nrf_rpc_uart {
5668
5769 K_KERNEL_STACK_MEMBER (rx_workq_stack , CONFIG_NRF_RPC_UART_RX_THREAD_STACK_SIZE );
5870
59- /* HDLC frame parsing state */
60- hdlc_state_t hdlc_state ;
61- uint8_t rx_packet [CONFIG_NRF_RPC_UART_MAX_PACKET_SIZE ];
62- size_t rx_packet_len ;
71+ /* HDLC packet decoding state */
72+ struct hdlc_decode_ctx rx_pkt_ctx ;
73+ uint8_t rx_pkt [CONFIG_NRF_RPC_UART_MAX_PACKET_SIZE ];
6374
6475 /* Ack waiting semaphore */
6576 struct k_sem ack_sem ;
@@ -91,12 +102,12 @@ static void send_byte(const struct device *dev, uint8_t byte);
91102
92103static void ack_rx (struct nrf_rpc_uart * uart_tr )
93104{
94- if (!IS_ENABLED (CONFIG_NRF_RPC_UART_RELIABLE ) || uart_tr -> rx_packet_len != CRC_SIZE ) {
95- log_hexdump_dbg (uart_tr -> rx_packet , uart_tr -> rx_packet_len , ">>> RX invalid frame" );
105+ if (!IS_ENABLED (CONFIG_NRF_RPC_UART_RELIABLE ) || uart_tr -> rx_pkt_ctx . len != CRC_SIZE ) {
106+ log_hexdump_dbg (uart_tr -> rx_pkt , uart_tr -> rx_pkt_ctx . len , ">>> RX invalid frame" );
96107 return ;
97108 }
98109
99- uint16_t rx_ack = sys_get_le16 (uart_tr -> rx_packet );
110+ uint16_t rx_ack = sys_get_le16 (uart_tr -> rx_pkt );
100111
101112 LOG_DBG (">>> RX ack %04x" , rx_ack );
102113
@@ -176,39 +187,48 @@ static bool crc_compare(uint16_t rx_crc, uint16_t calc_crc)
176187 return rx_crc == calc_crc ;
177188}
178189
179- static void hdlc_decode_byte (struct nrf_rpc_uart * uart_tr , uint8_t byte )
190+ static void hdlc_decode_byte (struct hdlc_decode_ctx * ctx , uint8_t * out , uint8_t in )
180191{
181- /* TODO: handle frame buffer overflow */
182-
183- if (uart_tr -> hdlc_state == HDLC_STATE_ESCAPE ) {
184- uart_tr -> rx_packet [uart_tr -> rx_packet_len ++ ] = byte ^ 0x20 ;
185- uart_tr -> hdlc_state = HDLC_STATE_FRAME_START ;
186- } else if (byte == HDLC_CHAR_ESCAPE ) {
187- uart_tr -> hdlc_state = HDLC_STATE_ESCAPE ;
188- } else if (byte == HDLC_CHAR_DELIMITER ) {
189- uart_tr -> hdlc_state = (uart_tr -> hdlc_state == HDLC_STATE_FRAME_START )
190- ? HDLC_STATE_FRAME_FOUND
191- : HDLC_STATE_UNSYNC ;
192- } else {
193- uart_tr -> rx_packet [uart_tr -> rx_packet_len ++ ] = byte ;
194- uart_tr -> hdlc_state = HDLC_STATE_FRAME_START ;
192+ switch (ctx -> state ) {
193+ case HDLC_STATE_UNSYNC :
194+ if (in == HDLC_CHAR_DELIMITER ) {
195+ ctx -> len = 0 ;
196+ ctx -> state = HDLC_STATE_FRAME ;
197+ }
198+ return ;
199+ case HDLC_STATE_FRAME_FOUND :
200+ ctx -> len = 0 ;
201+ ctx -> state = HDLC_STATE_FRAME ;
202+ __fallthrough ;
203+ case HDLC_STATE_FRAME :
204+ if (in == HDLC_CHAR_DELIMITER ) {
205+ if (ctx -> len > 0 ) {
206+ ctx -> state = HDLC_STATE_FRAME_FOUND ;
207+ }
208+ return ;
209+ } else if (in == HDLC_CHAR_ESCAPE ) {
210+ ctx -> state = HDLC_STATE_ESCAPE ;
211+ return ;
212+ }
213+ break ;
214+ case HDLC_STATE_ESCAPE :
215+ in ^= 0x20 ;
216+ ctx -> state = HDLC_STATE_FRAME ;
217+ break ;
195218 }
196219
197- if (uart_tr -> hdlc_state == HDLC_STATE_FRAME_FOUND ) {
198- if (uart_tr -> rx_packet_len > CRC_SIZE ) {
199- uart_tr -> rx_packet_len -= CRC_SIZE ;
200- } else {
201- ack_rx (uart_tr );
202- uart_tr -> rx_packet_len = 0 ;
203- uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
204- }
220+ if (ctx -> len >= ctx -> capacity ) {
221+ /* Ignore too long frame */
222+ ctx -> state = HDLC_STATE_UNSYNC ;
223+ return ;
205224 }
225+
226+ out [ctx -> len ++ ] = in ;
206227}
207228
208229static void work_handler (struct k_work * work )
209230{
210231 struct nrf_rpc_uart * uart_tr = CONTAINER_OF (work , struct nrf_rpc_uart , rx_work );
211- const struct nrf_rpc_tr * transport = uart_tr -> transport ;
212232 uint8_t * data ;
213233 size_t len ;
214234 int ret ;
@@ -219,24 +239,28 @@ static void work_handler(struct k_work *work)
219239 len = ring_buf_get_claim (& uart_tr -> rx_ringbuf , & data ,
220240 CONFIG_NRF_RPC_UART_MAX_PACKET_SIZE );
221241 for (size_t i = 0 ; i < len ; i ++ ) {
222- hdlc_decode_byte (uart_tr , data [i ]);
242+ hdlc_decode_byte (& uart_tr -> rx_pkt_ctx , uart_tr -> rx_pkt , data [i ]);
223243
224- if (uart_tr -> hdlc_state != HDLC_STATE_FRAME_FOUND ) {
244+ if (uart_tr -> rx_pkt_ctx . state != HDLC_STATE_FRAME_FOUND ) {
225245 continue ;
226246 }
227247
228- crc_received = sys_get_le16 (uart_tr -> rx_packet + uart_tr -> rx_packet_len );
248+ if (uart_tr -> rx_pkt_ctx .len <= CRC_SIZE ) {
249+ ack_rx (uart_tr );
250+ continue ;
251+ }
252+
253+ uart_tr -> rx_pkt_ctx .len -= CRC_SIZE ;
254+ crc_received = sys_get_le16 (uart_tr -> rx_pkt + uart_tr -> rx_pkt_ctx .len );
229255 crc_calculated =
230- crc16_ccitt (0xffff , uart_tr -> rx_packet , uart_tr -> rx_packet_len );
256+ crc16_ccitt (0xffff , uart_tr -> rx_pkt , uart_tr -> rx_pkt_ctx . len );
231257
232- log_hexdump_dbg (uart_tr -> rx_packet , uart_tr -> rx_packet_len ,
258+ log_hexdump_dbg (uart_tr -> rx_pkt , uart_tr -> rx_pkt_ctx . len ,
233259 ">>> RX packet %04x" , crc_received );
234260
235261 if (!crc_compare (crc_received , crc_calculated )) {
236262 LOG_ERR ("Invalid packet CRC: calculated %04x but received %04x" ,
237263 crc_calculated , crc_received );
238- uart_tr -> rx_packet_len = 0 ;
239- uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
240264 continue ;
241265 }
242266
@@ -245,13 +269,10 @@ static void work_handler(struct k_work *work)
245269 if (rx_flip_check (uart_tr , crc_received )) {
246270 LOG_WRN ("Duplicate packet %04x" , crc_received );
247271 } else {
248- uart_tr -> receive_callback (transport , uart_tr -> rx_packet ,
249- uart_tr -> rx_packet_len ,
272+ uart_tr -> receive_callback (uart_tr -> transport , uart_tr -> rx_pkt ,
273+ uart_tr -> rx_pkt_ctx . len ,
250274 uart_tr -> receive_ctx );
251275 }
252-
253- uart_tr -> rx_packet_len = 0 ;
254- uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
255276 }
256277
257278 ret = ring_buf_get_finish (& uart_tr -> rx_ringbuf , len );
@@ -350,8 +371,8 @@ static int init(const struct nrf_rpc_tr *transport, nrf_rpc_tr_receive_handler_t
350371 k_work_init (& uart_tr -> rx_work , work_handler );
351372 ring_buf_init (& uart_tr -> rx_ringbuf , sizeof (uart_tr -> rx_buffer ), uart_tr -> rx_buffer );
352373
353- uart_tr -> hdlc_state = HDLC_STATE_UNSYNC ;
354- uart_tr -> rx_packet_len = 0 ;
374+ uart_tr -> rx_pkt_ctx . state = HDLC_STATE_UNSYNC ;
375+ uart_tr -> rx_pkt_ctx . capacity = sizeof ( uart_tr -> rx_pkt ) ;
355376 uart_irq_rx_enable (uart_tr -> uart );
356377 nrf_rpc_uart_initialized_hook (uart_tr -> uart );
357378
0 commit comments