packet.c (8391B)
1 #include "packet.h" 2 #include "app/os.h" 3 #include "libopencm3/stm32/f4/nvic.h" 4 #include "shared/protocol.h" 5 #include "shared/ring-buffer.h" 6 #include "shared/drv-usart-dma.h" 7 #include <string.h> 8 #include "libopencm3/cm3/scb.h" 9 #include "shared/flash-io.h" 10 11 RingBuffer_t dbgRxRingBuf; 12 RingBuffer_t dbgTxRingBuf; 13 RingBuffer_t gsmRxRingBuf; 14 RingBuffer_t gsmTxRingBuf; 15 16 uint8_t packetBuf[DMA_RX_BUFFER_SIZE] = {0}; 17 18 typedef struct { 19 uint16_t offset; 20 uint16_t len; 21 USART_t *usart; 22 } PacketTxChunk_t; 23 24 const OS_TaskAttr_t packet_rx_taskAttr = { 25 .function = packet_rx_task, 26 .name = "packet tx task", 27 .stackSize = configMINIMAL_STACK_SIZE * 10, 28 .parameters = NULL, 29 .priority = 1, 30 }; 31 TaskHandle_t packet_rx_taskHandle = NULL; 32 33 const OS_TaskAttr_t packet_tx_taskAttr = { 34 .function = packet_tx_task, 35 .name = "packet rx task", 36 .stackSize = configMINIMAL_STACK_SIZE * 10, 37 .parameters = NULL, 38 .priority = 1, 39 }; 40 TaskHandle_t packet_tx_taskHandle = NULL; 41 42 PacketTxChunk_t packet_tx_queueStorageBuf[8]; 43 StaticQueue_t packet_tx_staticQueue; 44 OS_QueueAttr_t packet_tx_queueAttr = {.length = 8, 45 .itemSize = sizeof(PacketTxChunk_t), 46 .pxStorageBuf = (uint8_t *)packet_tx_queueStorageBuf, 47 .pxQueueBuf = &packet_tx_staticQueue}; 48 QueueHandle_t packet_tx_queueHandle = NULL; 49 50 static bool packetLineFree = true; 51 52 static void packet_send_nack(void) { 53 uint8_t packet[4] = {PROTOCOL_TAG_NACK, 0, 30, 0}; 54 packet_tx_enqueue_data(comm, packet, sizeof packet); 55 } 56 57 static void packet_send_ack(void) { 58 uint8_t packet[4] = {PROTOCOL_TAG_ACK, 0, 152, 3}; 59 packet_tx_enqueue_data(comm, packet, sizeof packet); 60 } 61 62 63 bool packet_usart_line_free(void) { return packetLineFree; } 64 65 static void packet_state_machine(ProtocolPacketAttr_t attr) { 66 uint8_t response[DMA_RX_BUFFER_SIZE] = {0}; 67 switch (attr.tag) { 68 case PROTOCOL_TAG_PR: { 69 if (flash_io_read_params(response + PACK_DATA_INDEX, attr.offset, attr.length) == attr.length) { 70 protocol_create_packet(response, PROTOCOL_TAG_ACK, attr.length); 71 packet_tx_enqueue_data(comm, response, attr.length + 4); 72 } 73 else packet_send_nack(); 74 } break; 75 case PROTOCOL_TAG_PW: { 76 vTaskEnterCritical(); 77 if (flash_io_write_params(packetBuf + PACK_DATA_INDEX, attr.offset, attr.length) == attr.length) packet_send_ack(); 78 else packet_send_nack(); 79 vTaskExitCritical(); 80 } break; 81 case PROTOCOL_TAG_FIR: { 82 if (flash_io_read_fw_info(response + PACK_DATA_INDEX, attr.offset, attr.length) == attr.length) { 83 protocol_create_packet(response, PROTOCOL_TAG_ACK, attr.length); 84 packet_tx_enqueue_data(comm, response, attr.length + 4); 85 } 86 else packet_send_nack(); 87 } break; 88 case PROTOCOL_TAG_RST: { 89 packet_send_ack(); 90 vTaskDelay(100); 91 scb_reset_core(); 92 } break; 93 case PROTOCOL_TAG_LOCK: { 94 packetLineFree = false; 95 packet_send_ack(); 96 } break; 97 case PROTOCOL_TAG_UNLOCK: { 98 packetLineFree = true; 99 packet_send_ack(); 100 } break; 101 case PROTOCOL_TAG_DIAG: { 102 uint8_t diagLength = flash_io_read_diagnostic(response + PACK_DATA_INDEX); 103 protocol_create_packet(response, PROTOCOL_TAG_ACK, diagLength); 104 packet_tx_enqueue_data(comm, response, diagLength + 4); 105 } break; 106 case PROTOCOL_TAG_ACK: { 107 } break; 108 case PROTOCOL_TAG_NACK: { 109 } break; 110 default: 111 packet_send_nack(); 112 break; 113 } 114 } 115 116 /* TODO: This can be removed probably 117 * Find a way to bond ring buffers to dma buffers other than this so 118 * that in the packet_tx_enqueue_data function there's no need to 119 * check the usart port 120 */ 121 void packet_init(void) { 122 ring_buffer_setup(&gsmRxRingBuf, gsm.dma.rxBuf, DMA_RX_BUFFER_SIZE); 123 ring_buffer_setup(&gsmTxRingBuf, gsm.dma.txBuf, DMA_TX_BUFFER_SIZE); 124 ring_buffer_setup(&dbgRxRingBuf, dbg.dma.rxBuf, DMA_RX_BUFFER_SIZE); 125 ring_buffer_setup(&dbgTxRingBuf, dbg.dma.txBuf, DMA_TX_BUFFER_SIZE); 126 usart_enable(gsm.port); 127 usart_enable(dbg.port); 128 comm = &dbg; // set serial communication port to dbg (usart1) 129 } 130 131 void packet_rx_task(void *parameters) { 132 (void)parameters; 133 uint16_t len = 0; 134 for (;;) { 135 xTaskNotifyWait(0, 0, (uint32_t *)&len, portMAX_DELAY); 136 osDoggyRegister |= OS_DOGGY_PACKET_T; 137 if (comm == &dbg) ring_buffer_read_chunk(&dbgRxRingBuf, packetBuf, len); 138 else ring_buffer_read_chunk(&gsmRxRingBuf, packetBuf, len); 139 ProtocolPacketAttr_t attr = protocol_extract_packet_attr(packetBuf, false); 140 if (attr.tag != PROTOCOL_TAG_INVALID) packet_state_machine(attr); 141 else packet_send_nack(); 142 } 143 } 144 145 void packet_tx_task(void *parameters) { 146 PacketTxChunk_t chunk; 147 uint32_t dummy = 0; 148 (void)parameters; 149 for (;;) { 150 if (xQueuePeek(packet_tx_queueHandle, &chunk, portMAX_DELAY)) { 151 xTaskNotifyWait(0, 0, &dummy, portMAX_DELAY); 152 xQueueReceive(packet_tx_queueHandle, &chunk, portMAX_DELAY); 153 res_usart_dma_write(chunk.usart, chunk.offset, chunk.len); 154 } 155 } 156 } 157 158 void packet_tx_enqueue_data(USART_t *usart, const uint8_t *data, const uint16_t len) { 159 // write data to tx ring buffer 160 PacketTxChunk_t chunk; 161 RingBuffer_t *pBuf = NULL; 162 if (usart == &gsm) pBuf = &gsmTxRingBuf; 163 else if (usart == &dbg) pBuf = &dbgTxRingBuf; 164 chunk.usart = usart; 165 ring_buffer_write_chunk(pBuf, data, len); 166 if ((DMA_TX_BUFFER_SIZE - pBuf->head) < len) { 167 chunk.offset = pBuf->head; 168 chunk.len = DMA_TX_BUFFER_SIZE - pBuf->head; 169 xQueueSend(packet_tx_queueHandle, &chunk, 2); 170 chunk.offset = 0; 171 chunk.len = len - (DMA_TX_BUFFER_SIZE - pBuf->head); 172 xQueueSend(packet_tx_queueHandle, &chunk, 2); 173 pBuf->head = pBuf->tail; 174 return; 175 } 176 chunk.offset = pBuf->head; 177 chunk.len = len; 178 pBuf->head = pBuf->tail; 179 // Enqueue whole chunk for transmit 180 xQueueSend(packet_tx_queueHandle, &chunk, 2); 181 } 182 183 void usart2_isr(void) { 184 uint16_t packetLen = 0; 185 (void)USART_SR(USART2); 186 (void)USART_DR(USART2); // This read sequence clears the idle interrupt flag 187 gsmRxRingBuf.tail = res_usart_dma_get_buffer_tail(&gsm); 188 packetLen = (DMA_RX_BUFFER_SIZE - 1) & (gsmRxRingBuf.tail - gsmRxRingBuf.head); 189 comm = &gsm; 190 BaseType_t xHigherTaskWoken = pdFALSE; 191 xTaskNotifyFromISR(packet_rx_taskHandle, packetLen, eSetValueWithOverwrite, &xHigherTaskWoken); 192 osDoggyRegister |= OS_DOGGY_UART_DATA; 193 portYIELD_FROM_ISR(xHigherTaskWoken); 194 } 195 196 void usart1_isr(void) { 197 uint16_t packetLen = 0; 198 (void)USART_SR(USART1); 199 (void)USART_DR(USART1); // This read sequence clears the idle interrupt flag 200 dbgRxRingBuf.tail = res_usart_dma_get_buffer_tail(&dbg); 201 packetLen = (DMA_RX_BUFFER_SIZE - 1) & (dbgRxRingBuf.tail - dbgRxRingBuf.head); 202 comm = &dbg; 203 BaseType_t xHigherTaskWoken = pdFALSE; 204 xTaskNotifyFromISR(packet_rx_taskHandle, packetLen, eSetValueWithOverwrite, &xHigherTaskWoken); 205 osDoggyRegister |= OS_DOGGY_UART_DATA; 206 portYIELD_FROM_ISR(xHigherTaskWoken); 207 } 208 209 void dma1_stream5_isr(void) { 210 // TODO: deactivate dma interrupt if nothing is done here 211 dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF); 212 } 213 214 void dma2_stream2_isr(void) { 215 dma_clear_interrupt_flags(DMA2, DMA_STREAM2, DMA_TCIF); 216 } 217 218 void dma2_stream7_isr(void) { 219 uint8_t dummy = 0; 220 dma_clear_interrupt_flags(DMA2, DMA_STREAM7, DMA_TCIF); 221 dma_disable_stream(DMA2, DMA_STREAM7); 222 BaseType_t xHigherTaskWoken = pdFALSE; 223 xTaskNotifyFromISR(packet_tx_taskHandle, dummy, eSetValueWithOverwrite, &xHigherTaskWoken); 224 portYIELD_FROM_ISR(xHigherTaskWoken); 225 } 226 227 void dma1_stream6_isr(void) { 228 uint8_t dummy = 0; 229 dma_clear_interrupt_flags(DMA1, DMA_STREAM6, DMA_TCIF); 230 dma_disable_stream(DMA1, DMA_STREAM6); 231 BaseType_t xHigherTaskWoken = pdFALSE; 232 xTaskNotifyFromISR(packet_tx_taskHandle, dummy, eSetValueWithOverwrite, &xHigherTaskWoken); 233 portYIELD_FROM_ISR(xHigherTaskWoken); 234 }