Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Committer:
Jeej
Date:
Thu Sep 01 09:35:27 2016 +0000
Revision:
45:b85384e7d825
Parent:
44:8ebe6b70f932
Child:
46:665391110051
New API working for local read/write.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 24:a8433b091764 1 #include "mbed.h"
Jeej 24:a8433b091764 2 #include "rtos.h"
Jeej 24:a8433b091764 3 #include "dbg.h"
Jeej 24:a8433b091764 4 #include "d7a_com.h"
Jeej 45:b85384e7d825 5 #include "d7a_alp.h"
Jeej 25:aac250164497 6 #include "d7a_common.h"
Jeej 25:aac250164497 7 #include "d7a_fs.h"
Jeej 25:aac250164497 8 #include "d7a_modem.h"
Jeej 25:aac250164497 9 #include "d7a_sys.h"
Jeej 24:a8433b091764 10
Jeej 34:1311cc53201a 11
Jeej 37:e04613e021f2 12 #define XON_SIGNAL (0x0001 << 0)
Jeej 37:e04613e021f2 13 #define START_SIGNAL (0x0001 << 1)
Jeej 31:ab9bfdbc6b44 14
Jeej 31:ab9bfdbc6b44 15 typedef struct {
Jeej 31:ab9bfdbc6b44 16 uint32_t len;
Jeej 45:b85384e7d825 17 uint8_t buf[1];
Jeej 31:ab9bfdbc6b44 18 } d7a_com_tx_buf_t;
Jeej 30:d775c1409849 19
Jeej 37:e04613e021f2 20 enum {
Jeej 37:e04613e021f2 21 SEARCH_HEADER,
Jeej 37:e04613e021f2 22 PARSE_HEADER,
Jeej 37:e04613e021f2 23 SEARCH_BODY,
Jeej 37:e04613e021f2 24 PARSE_BODY,
Jeej 37:e04613e021f2 25 };
Jeej 30:d775c1409849 26
Jeej 25:aac250164497 27 typedef struct {
Jeej 37:e04613e021f2 28 bool rx_started;
Jeej 37:e04613e021f2 29 bool tx_started;
Jeej 37:e04613e021f2 30
Jeej 37:e04613e021f2 31 uint8_t state;
Jeej 34:1311cc53201a 32
Jeej 25:aac250164497 33 DigitalOut* rts;
Jeej 25:aac250164497 34 InterruptIn* cts;
Jeej 25:aac250164497 35
Jeej 25:aac250164497 36 // RX buffer address
Jeej 25:aac250164497 37 uint8_t* rx_buffer;
Jeej 25:aac250164497 38 // RX buffer size
Jeej 25:aac250164497 39 uint16_t rx_buffer_size;
Jeej 25:aac250164497 40 // Write index in RX buffer
Jeej 25:aac250164497 41 volatile uint16_t write_idx;
Jeej 25:aac250164497 42 // Read index in RX buffer
Jeej 25:aac250164497 43 uint16_t read_idx;
Jeej 25:aac250164497 44 // Number of bytes available in RX buffer
Jeej 25:aac250164497 45 volatile uint16_t data_available;
Jeej 37:e04613e021f2 46 // min data in buffer before parsing body
Jeej 37:e04613e021f2 47 d7a_com_rx_msg_t msg;
Jeej 33:f9a542d3efaa 48 // Number of skipped bytes while parsing
Jeej 33:f9a542d3efaa 49 uint16_t skipped_bytes;
Jeej 33:f9a542d3efaa 50
Jeej 25:aac250164497 51 // Port TX sequence number
Jeej 25:aac250164497 52 uint8_t tx_seq;
Jeej 25:aac250164497 53 // Port RX sequence number
Jeej 25:aac250164497 54 uint8_t rx_seq;
Jeej 25:aac250164497 55 // Response to command maximum time
Jeej 25:aac250164497 56 uint32_t timeout;
Jeej 25:aac250164497 57
Jeej 25:aac250164497 58 // Waiting for data available in RX buffer
Jeej 25:aac250164497 59 Semaphore* data_parsing;
Jeej 25:aac250164497 60 // CTS management
Jeej 25:aac250164497 61 Semaphore* cts_int;
Jeej 25:aac250164497 62
Jeej 25:aac250164497 63 // Data treatment threads
Jeej 31:ab9bfdbc6b44 64 Thread* rx_thread;
Jeej 25:aac250164497 65 Serial* serial;
Jeej 25:aac250164497 66
Jeej 31:ab9bfdbc6b44 67 // Tx Thread
Jeej 31:ab9bfdbc6b44 68 Thread* tx_thread;
Jeej 31:ab9bfdbc6b44 69 Queue<d7a_com_tx_buf_t, 32> tx_queue;
Jeej 31:ab9bfdbc6b44 70
Jeej 34:1311cc53201a 71 Timer tim;
Jeej 34:1311cc53201a 72
Jeej 25:aac250164497 73 } d7a_com_ctx_t;
Jeej 24:a8433b091764 74
Jeej 31:ab9bfdbc6b44 75
Jeej 24:a8433b091764 76 static d7a_com_ctx_t g_com_ctx;
Jeej 24:a8433b091764 77
Jeej 24:a8433b091764 78 /**
Jeej 24:a8433b091764 79 Thread for parsing packets from RX buffer.
Jeej 24:a8433b091764 80
Jeej 24:a8433b091764 81 @param void
Jeej 24:a8433b091764 82 @return void
Jeej 24:a8433b091764 83 */
Jeej 31:ab9bfdbc6b44 84 void d7a_com_rx_thread( void const *p );
Jeej 31:ab9bfdbc6b44 85 void d7a_com_tx_thread( void const *p );
Jeej 31:ab9bfdbc6b44 86
Jeej 24:a8433b091764 87
Jeej 24:a8433b091764 88 /**
Jeej 24:a8433b091764 89 Serial Rx Interrupt Service Routine.
Jeej 24:a8433b091764 90 Add recevied bytes to the RX buffer.
Jeej 24:a8433b091764 91
Jeej 24:a8433b091764 92 @param void
Jeej 24:a8433b091764 93 @return void
Jeej 24:a8433b091764 94 */
Jeej 24:a8433b091764 95 void rx_isr()
Jeej 24:a8433b091764 96 {
Jeej 24:a8433b091764 97 // Loop just in case more than one character is in UART's receive FIFO buffer
Jeej 24:a8433b091764 98 // Stop if buffer full
Jeej 34:1311cc53201a 99 while (g_com_ctx.serial->readable())
Jeej 34:1311cc53201a 100 {
Jeej 34:1311cc53201a 101
Jeej 24:a8433b091764 102 g_com_ctx.rx_buffer[g_com_ctx.write_idx] = g_com_ctx.serial->getc();
Jeej 34:1311cc53201a 103 //PRINT("-");
Jeej 34:1311cc53201a 104
Jeej 42:1578f0480dcb 105 //if (g_com_ctx.rx_started)
Jeej 34:1311cc53201a 106 {
Jeej 34:1311cc53201a 107 g_com_ctx.data_available++;
Jeej 34:1311cc53201a 108
Jeej 34:1311cc53201a 109 g_com_ctx.write_idx = (g_com_ctx.write_idx >= (g_com_ctx.rx_buffer_size-1))? 0 : g_com_ctx.write_idx+1;
Jeej 34:1311cc53201a 110 //g_com_ctx.write_idx = (g_com_ctx.write_idx + 1) % g_com_ctx.rx_buffer_size;
Jeej 42:1578f0480dcb 111
Jeej 42:1578f0480dcb 112 // unlock data parsing thread
Jeej 42:1578f0480dcb 113 if (g_com_ctx.state == SEARCH_HEADER && g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 42:1578f0480dcb 114 {
Jeej 42:1578f0480dcb 115 g_com_ctx.state = PARSE_HEADER;
Jeej 42:1578f0480dcb 116 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 117 }
Jeej 42:1578f0480dcb 118 else if (g_com_ctx.state == SEARCH_BODY && g_com_ctx.data_available >= g_com_ctx.msg.blen)
Jeej 42:1578f0480dcb 119 {
Jeej 42:1578f0480dcb 120 g_com_ctx.state = PARSE_BODY;
Jeej 42:1578f0480dcb 121 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 122 }
Jeej 34:1311cc53201a 123 }
Jeej 24:a8433b091764 124 }
Jeej 33:f9a542d3efaa 125
Jeej 42:1578f0480dcb 126 ASSERT(g_com_ctx.data_available <= g_com_ctx.rx_buffer_size, "RX Buffer overflow! (%d/%d)\r\n", g_com_ctx.data_available, g_com_ctx.rx_buffer_size);
Jeej 24:a8433b091764 127 }
Jeej 24:a8433b091764 128
Jeej 24:a8433b091764 129 /**
Jeej 24:a8433b091764 130 CTS pin Interrupt Service Routine.
Jeej 24:a8433b091764 131 For flow control (not yet inplemented)
Jeej 24:a8433b091764 132
Jeej 24:a8433b091764 133 @param void
Jeej 24:a8433b091764 134 @return void
Jeej 24:a8433b091764 135 */
Jeej 24:a8433b091764 136 void cts_isr()
Jeej 24:a8433b091764 137 {
Jeej 34:1311cc53201a 138 //PRINT("CTS_INT\r\n");
Jeej 34:1311cc53201a 139 //g_com_ctx.cts_int->release();
Jeej 24:a8433b091764 140 }
Jeej 24:a8433b091764 141
Jeej 26:9f0b9833cac6 142 // D7a_com constructor.
Jeej 26:9f0b9833cac6 143 // Opens a serial port and monitors the input for ALP packets.
Jeej 26:9f0b9833cac6 144 // Pins are those of the host, not the modem:
Jeej 26:9f0b9833cac6 145 // TX-host -> RX-modem
Jeej 26:9f0b9833cac6 146 // RX-host <- TX-modem
Jeej 26:9f0b9833cac6 147 // RTS-host -> CTS-modem
Jeej 26:9f0b9833cac6 148 // CTS-host <- RTS-modem
Jeej 26:9f0b9833cac6 149 void d7a_com_open( const d7a_com_config_t* config )
Jeej 26:9f0b9833cac6 150 {
Jeej 26:9f0b9833cac6 151 FPRINT("\r\n");
Jeej 26:9f0b9833cac6 152
Jeej 37:e04613e021f2 153 g_com_ctx.rx_started = false;
Jeej 37:e04613e021f2 154 g_com_ctx.tx_started = false;
Jeej 37:e04613e021f2 155 g_com_ctx.state = SEARCH_HEADER;
Jeej 26:9f0b9833cac6 156 g_com_ctx.rx_buffer_size = config->rx_buffer_size;
Jeej 26:9f0b9833cac6 157 g_com_ctx.rx_buffer = (uint8_t*)MALLOC(g_com_ctx.rx_buffer_size);
Jeej 26:9f0b9833cac6 158 g_com_ctx.data_available = 0;
Jeej 33:f9a542d3efaa 159 g_com_ctx.skipped_bytes = 0;
Jeej 26:9f0b9833cac6 160 g_com_ctx.write_idx = 0;
Jeej 26:9f0b9833cac6 161 g_com_ctx.read_idx = 0;
Jeej 26:9f0b9833cac6 162 g_com_ctx.tx_seq = 0;
Jeej 26:9f0b9833cac6 163 g_com_ctx.rx_seq = 0;
Jeej 26:9f0b9833cac6 164
Jeej 26:9f0b9833cac6 165 g_com_ctx.serial = new Serial(config->tx, config->rx);
Jeej 26:9f0b9833cac6 166 g_com_ctx.rts = new DigitalOut(config->rts);
Jeej 26:9f0b9833cac6 167 g_com_ctx.cts = new InterruptIn(config->cts);
Jeej 34:1311cc53201a 168 g_com_ctx.data_parsing = new Semaphore(0);
Jeej 34:1311cc53201a 169 g_com_ctx.cts_int = new Semaphore(0);
Jeej 31:ab9bfdbc6b44 170
Jeej 34:1311cc53201a 171 g_com_ctx.cts->rise(&cts_isr);
Jeej 34:1311cc53201a 172
Jeej 26:9f0b9833cac6 173 /* XXX: Unknown bug:
Jeej 26:9f0b9833cac6 174 Baud rate can be found with high error rate (> 4%).
Jeej 26:9f0b9833cac6 175 It is here manualy corrected after an oscilloscope measure.
Jeej 26:9f0b9833cac6 176 Normal Baudrate should be 115200.
Jeej 26:9f0b9833cac6 177 */
Jeej 33:f9a542d3efaa 178 //g_com_ctx.serial->baud(117000); // XXX
Jeej 33:f9a542d3efaa 179 g_com_ctx.serial->baud(115200); // XXX
Jeej 34:1311cc53201a 180 //g_com_ctx.serial->baud(57600); // XXX
Jeej 26:9f0b9833cac6 181 g_com_ctx.serial->format(8, SerialBase::None, 1);
Jeej 26:9f0b9833cac6 182 g_com_ctx.serial->attach(&rx_isr, Serial::RxIrq);
Jeej 30:d775c1409849 183
Jeej 31:ab9bfdbc6b44 184 g_com_ctx.tx_thread = new Thread(d7a_com_tx_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE);
Jeej 31:ab9bfdbc6b44 185 g_com_ctx.rx_thread = new Thread(d7a_com_rx_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE);
Jeej 26:9f0b9833cac6 186 }
Jeej 26:9f0b9833cac6 187
Jeej 26:9f0b9833cac6 188 // Destructor
Jeej 26:9f0b9833cac6 189 void d7a_com_close()
Jeej 26:9f0b9833cac6 190 {
Jeej 26:9f0b9833cac6 191 FPRINT("\r\n");
Jeej 31:ab9bfdbc6b44 192 g_com_ctx.rx_thread->terminate();
Jeej 31:ab9bfdbc6b44 193 g_com_ctx.tx_thread->terminate();
Jeej 26:9f0b9833cac6 194 delete g_com_ctx.data_parsing;
Jeej 26:9f0b9833cac6 195 delete g_com_ctx.cts_int;
Jeej 26:9f0b9833cac6 196 delete g_com_ctx.serial;
Jeej 26:9f0b9833cac6 197 delete g_com_ctx.rts;
Jeej 26:9f0b9833cac6 198 delete g_com_ctx.cts;
Jeej 26:9f0b9833cac6 199 FREE(g_com_ctx.rx_buffer);
Jeej 26:9f0b9833cac6 200 }
Jeej 26:9f0b9833cac6 201
Jeej 37:e04613e021f2 202 void d7a_com_start_rx(void)
Jeej 37:e04613e021f2 203 {
Jeej 37:e04613e021f2 204 FPRINT("\r\n");
Jeej 37:e04613e021f2 205 g_com_ctx.rx_started = true;
Jeej 37:e04613e021f2 206 g_com_ctx.rx_thread->signal_set(START_SIGNAL);
Jeej 37:e04613e021f2 207 }
Jeej 37:e04613e021f2 208
Jeej 37:e04613e021f2 209 void d7a_com_stop_rx(void)
Jeej 34:1311cc53201a 210 {
Jeej 34:1311cc53201a 211 FPRINT("\r\n");
Jeej 37:e04613e021f2 212 g_com_ctx.rx_started = false;
Jeej 37:e04613e021f2 213 }
Jeej 37:e04613e021f2 214
Jeej 37:e04613e021f2 215 void d7a_com_start_tx(void)
Jeej 37:e04613e021f2 216 {
Jeej 37:e04613e021f2 217 FPRINT("\r\n");
Jeej 37:e04613e021f2 218 g_com_ctx.tx_started = true;
Jeej 37:e04613e021f2 219 g_com_ctx.tx_thread->signal_set(START_SIGNAL);
Jeej 37:e04613e021f2 220 }
Jeej 37:e04613e021f2 221
Jeej 37:e04613e021f2 222 void d7a_com_stop_tx(void)
Jeej 37:e04613e021f2 223 {
Jeej 37:e04613e021f2 224 FPRINT("\r\n");
Jeej 37:e04613e021f2 225 g_com_ctx.tx_started = false;
Jeej 34:1311cc53201a 226 }
Jeej 34:1311cc53201a 227
Jeej 34:1311cc53201a 228 void d7a_com_restart(void)
Jeej 34:1311cc53201a 229 {
Jeej 34:1311cc53201a 230 FPRINT("\r\n");
Jeej 37:e04613e021f2 231 d7a_com_stop_rx();
Jeej 37:e04613e021f2 232 d7a_com_stop_tx();
Jeej 42:1578f0480dcb 233
Jeej 42:1578f0480dcb 234 g_com_ctx.state = SEARCH_HEADER;
Jeej 34:1311cc53201a 235 g_com_ctx.data_available = 0;
Jeej 34:1311cc53201a 236 g_com_ctx.skipped_bytes = 0;
Jeej 34:1311cc53201a 237 g_com_ctx.write_idx = 0;
Jeej 34:1311cc53201a 238 g_com_ctx.read_idx = 0;
Jeej 34:1311cc53201a 239 g_com_ctx.tx_seq = 0;
Jeej 34:1311cc53201a 240 g_com_ctx.rx_seq = 0;
Jeej 34:1311cc53201a 241
Jeej 34:1311cc53201a 242 d7a_com_tx_buf_t* msg;
Jeej 34:1311cc53201a 243 d7a_com_rx_msg_t* pkt;
Jeej 34:1311cc53201a 244 osEvent evt;
Jeej 34:1311cc53201a 245
Jeej 34:1311cc53201a 246 // Flush TX queue
Jeej 34:1311cc53201a 247 do
Jeej 34:1311cc53201a 248 {
Jeej 34:1311cc53201a 249 // wait for data
Jeej 34:1311cc53201a 250 evt = g_com_ctx.tx_queue.get(1);
Jeej 34:1311cc53201a 251 msg = (evt.status == osEventMessage)? (d7a_com_tx_buf_t*)evt.value.p : NULL;
Jeej 34:1311cc53201a 252
Jeej 34:1311cc53201a 253 // free message
Jeej 34:1311cc53201a 254 if (msg != NULL)
Jeej 34:1311cc53201a 255 {
Jeej 34:1311cc53201a 256 FREE(msg->buf);
Jeej 34:1311cc53201a 257 FREE(msg);
Jeej 34:1311cc53201a 258 }
Jeej 34:1311cc53201a 259 } while (msg != NULL);
Jeej 34:1311cc53201a 260
Jeej 34:1311cc53201a 261 // Flush RX
Jeej 34:1311cc53201a 262 for (int i = 0 ; i < 3 ; i++)
Jeej 34:1311cc53201a 263 {
Jeej 34:1311cc53201a 264 do
Jeej 34:1311cc53201a 265 {
Jeej 34:1311cc53201a 266 // wait for data
Jeej 34:1311cc53201a 267 if (i == 0)
Jeej 34:1311cc53201a 268 {
Jeej 34:1311cc53201a 269 pkt = d7a_modem_wait_pkt(1);
Jeej 34:1311cc53201a 270 }
Jeej 34:1311cc53201a 271 else if (i == 1)
Jeej 34:1311cc53201a 272 {
Jeej 34:1311cc53201a 273 pkt = d7a_fs_wait_pkt(1);
Jeej 34:1311cc53201a 274 }
Jeej 34:1311cc53201a 275 else
Jeej 34:1311cc53201a 276 {
Jeej 34:1311cc53201a 277 pkt = d7a_sys_wait_pkt(1);
Jeej 34:1311cc53201a 278 }
Jeej 34:1311cc53201a 279
Jeej 34:1311cc53201a 280 // free message
Jeej 34:1311cc53201a 281 if (pkt != NULL)
Jeej 34:1311cc53201a 282 {
Jeej 34:1311cc53201a 283 FREE(pkt);
Jeej 34:1311cc53201a 284 }
Jeej 34:1311cc53201a 285 } while (pkt != NULL);
Jeej 34:1311cc53201a 286 }
Jeej 34:1311cc53201a 287
Jeej 37:e04613e021f2 288 d7a_com_start_rx();
Jeej 37:e04613e021f2 289 d7a_com_start_tx();
Jeej 34:1311cc53201a 290 }
Jeej 34:1311cc53201a 291
Jeej 42:1578f0480dcb 292
Jeej 34:1311cc53201a 293 static void d7a_com_copy_to_linear(uint8_t* linear_buffer, uint16_t read_start, uint16_t length)
Jeej 34:1311cc53201a 294 {
Jeej 34:1311cc53201a 295 uint16_t first_part_size;
Jeej 34:1311cc53201a 296 uint16_t second_part_size;
Jeej 34:1311cc53201a 297
Jeej 34:1311cc53201a 298 ASSERT(length <= g_com_ctx.rx_buffer_size, "Length too long (%d) for buffer size (%d)\r\n", length, g_com_ctx.rx_buffer_size);
Jeej 34:1311cc53201a 299
Jeej 34:1311cc53201a 300 read_start %= g_com_ctx.rx_buffer_size;
Jeej 34:1311cc53201a 301 first_part_size = (length > (g_com_ctx.rx_buffer_size - read_start))? g_com_ctx.rx_buffer_size - read_start : length;
Jeej 34:1311cc53201a 302
Jeej 34:1311cc53201a 303 memcpy((void*)&linear_buffer[0], (const void*)&g_com_ctx.rx_buffer[read_start], first_part_size);
Jeej 34:1311cc53201a 304
Jeej 34:1311cc53201a 305 // The circular buffer is wrapping
Jeej 34:1311cc53201a 306 if (length > first_part_size)
Jeej 34:1311cc53201a 307 {
Jeej 34:1311cc53201a 308 second_part_size = length - first_part_size;
Jeej 34:1311cc53201a 309 memcpy((void*)&linear_buffer[first_part_size], (const void*)&g_com_ctx.rx_buffer[0], second_part_size);
Jeej 34:1311cc53201a 310 }
Jeej 34:1311cc53201a 311 }
Jeej 42:1578f0480dcb 312
Jeej 24:a8433b091764 313 /**
Jeej 24:a8433b091764 314 Wakes-up modem and send data throught Serial.
Jeej 24:a8433b091764 315
Jeej 24:a8433b091764 316 @param const uint8_t* Pointer to data buffer
Jeej 24:a8433b091764 317 @param int Data length
Jeej 24:a8433b091764 318 @return void
Jeej 24:a8433b091764 319 */
Jeej 45:b85384e7d825 320 static void d7a_com_send(d7a_com_tx_buf_t* tx_buf)
Jeej 24:a8433b091764 321 {
Jeej 45:b85384e7d825 322 FPRINT("\r\n");
Jeej 45:b85384e7d825 323
Jeej 45:b85384e7d825 324 DPRINT("<-- (0x%02X) %d\r\n", tx_buf->buf[4], (tx_buf->len - KAL_COM_HEADER_LEN));
Jeej 34:1311cc53201a 325
Jeej 24:a8433b091764 326 *(g_com_ctx.rts) = 1;
Jeej 24:a8433b091764 327
Jeej 45:b85384e7d825 328 //dbg_print_data("", "%02X ", (uint8_t*)tx_buf->buf, tx_buf->len, "\r\n");
Jeej 45:b85384e7d825 329
Jeej 39:2101208fafb6 330 Thread::wait(2);
Jeej 24:a8433b091764 331
Jeej 45:b85384e7d825 332 for (uint32_t i=0 ; i<tx_buf->len ; i++)
Jeej 24:a8433b091764 333 {
Jeej 45:b85384e7d825 334 g_com_ctx.serial->putc(tx_buf->buf[i]);
Jeej 24:a8433b091764 335 }
Jeej 24:a8433b091764 336
Jeej 42:1578f0480dcb 337 //Thread::wait(2);
Jeej 42:1578f0480dcb 338
Jeej 24:a8433b091764 339 *(g_com_ctx.rts) = 0;
Jeej 24:a8433b091764 340 }
Jeej 24:a8433b091764 341
Jeej 26:9f0b9833cac6 342 // Formats and send packet throught Serial.
Jeej 45:b85384e7d825 343 d7a_com_tx_buf_t* d7a_com_new_msg(d7a_com_tx_msg_t* msg)
Jeej 34:1311cc53201a 344 {
Jeej 45:b85384e7d825 345 uint8_t len = KAL_COM_HEADER_LEN + msg->alen + msg->plen;
Jeej 34:1311cc53201a 346 FPRINT("(len:%d)\r\n", len);
Jeej 34:1311cc53201a 347
Jeej 45:b85384e7d825 348 d7a_com_tx_buf_t* tx_buf = (d7a_com_tx_buf_t*)MALLOC(sizeof(d7a_com_tx_buf_t) - 1 + len);
Jeej 34:1311cc53201a 349
Jeej 34:1311cc53201a 350 // construct serial header
Jeej 34:1311cc53201a 351 // concatenate and update tx_seq ID
Jeej 45:b85384e7d825 352 uint8_t* p = tx_buf->buf;
Jeej 45:b85384e7d825 353 uint8_t* t = p;
Jeej 45:b85384e7d825 354 *p++ = (uint8_t)KAL_COM_SYNC_BYTE_0;
Jeej 45:b85384e7d825 355 *p++ = (uint8_t)KAL_COM_SYNC_BYTE_1;
Jeej 45:b85384e7d825 356 *p++ = (uint8_t)msg->alen + msg->plen;
Jeej 45:b85384e7d825 357 *p++ = (uint8_t)g_com_ctx.tx_seq++;
Jeej 45:b85384e7d825 358 *p++ = (uint8_t)msg->id;
Jeej 34:1311cc53201a 359
Jeej 34:1311cc53201a 360 // copy payload and parameters
Jeej 45:b85384e7d825 361 memcpy(p, msg->pbuf, msg->plen);
Jeej 45:b85384e7d825 362 p += msg->plen;
Jeej 45:b85384e7d825 363 memcpy(p, msg->abuf, msg->alen);
Jeej 45:b85384e7d825 364 p += msg->alen;
Jeej 34:1311cc53201a 365
Jeej 45:b85384e7d825 366 tx_buf->len = (uint32_t)(p - t);
Jeej 34:1311cc53201a 367
Jeej 45:b85384e7d825 368 ASSERT(tx_buf->len == len, "New msg wrong length %d expected %d\r\n", tx_buf->len, len);
Jeej 45:b85384e7d825 369
Jeej 45:b85384e7d825 370 return tx_buf;
Jeej 34:1311cc53201a 371 }
Jeej 34:1311cc53201a 372
Jeej 34:1311cc53201a 373 void d7a_com_post_msg(d7a_com_tx_msg_t* msg)
Jeej 45:b85384e7d825 374 {
Jeej 45:b85384e7d825 375 FPRINT("\r\n");
Jeej 26:9f0b9833cac6 376
Jeej 45:b85384e7d825 377 g_com_ctx.tx_queue.put(d7a_com_new_msg(msg));
Jeej 26:9f0b9833cac6 378 }
Jeej 26:9f0b9833cac6 379
Jeej 30:d775c1409849 380 void d7a_com_dump(uint8_t* buf, uint8_t len, d7a_com_flow_t flow)
Jeej 30:d775c1409849 381 {
Jeej 30:d775c1409849 382 d7a_com_tx_msg_t msg;
Jeej 30:d775c1409849 383
Jeej 30:d775c1409849 384 msg.id = flow;
Jeej 30:d775c1409849 385 msg.pbuf = buf;
Jeej 30:d775c1409849 386 msg.plen = len;
Jeej 30:d775c1409849 387 msg.alen = 0;
Jeej 34:1311cc53201a 388 d7a_com_post_msg(&msg);
Jeej 30:d775c1409849 389 }
Jeej 30:d775c1409849 390
Jeej 25:aac250164497 391 static void d7a_com_new_pkt(d7a_com_rx_msg_t* pkt)
Jeej 25:aac250164497 392 {
Jeej 26:9f0b9833cac6 393 //FPRINT("\r\n");
Jeej 35:1fe2975c5a63 394
Jeej 35:1fe2975c5a63 395 DPRINT("--> (0x%02X) %d\r\n", pkt->id, pkt->blen);
Jeej 35:1fe2975c5a63 396
Jeej 25:aac250164497 397 // Distribute packet types to processes
Jeej 25:aac250164497 398 switch (KAL_COM_FLOWID(pkt->id))
Jeej 25:aac250164497 399 {
Jeej 25:aac250164497 400 case KAL_COM_FLOWID_FS:
Jeej 25:aac250164497 401 d7a_fs_new_pkt(pkt);
Jeej 25:aac250164497 402 break;
Jeej 25:aac250164497 403 case KAL_COM_FLOWID_CMD:
Jeej 25:aac250164497 404 d7a_modem_new_pkt(pkt);
Jeej 25:aac250164497 405 break;
Jeej 45:b85384e7d825 406 case KAL_COM_FLOWID_ALP:
Jeej 45:b85384e7d825 407 d7a_alp_new_pkt(pkt);
Jeej 45:b85384e7d825 408 break;
Jeej 25:aac250164497 409 case KAL_COM_FLOWID_SYS:
Jeej 30:d775c1409849 410 // This has to be here to avoid going to another process
Jeej 30:d775c1409849 411 if (pkt->id == KAL_COM_FLOW_SYS_XON)
Jeej 30:d775c1409849 412 {
Jeej 42:1578f0480dcb 413 DPRINT("XON\r\n");
Jeej 34:1311cc53201a 414 g_com_ctx.tx_thread->signal_set(XON_SIGNAL);
Jeej 30:d775c1409849 415 FREE(pkt);
Jeej 30:d775c1409849 416 }
Jeej 30:d775c1409849 417 else if (pkt->id == KAL_COM_FLOW_SYS_XOFF)
Jeej 30:d775c1409849 418 {
Jeej 42:1578f0480dcb 419 DPRINT("XOFF\r\n");
Jeej 34:1311cc53201a 420 d7a_sys_xack();
Jeej 30:d775c1409849 421 FREE(pkt);
Jeej 30:d775c1409849 422 }
Jeej 30:d775c1409849 423 else
Jeej 30:d775c1409849 424 {
Jeej 34:1311cc53201a 425 if (KAL_COM_FLOW_SYS_PONG == pkt->id)
Jeej 34:1311cc53201a 426 {
Jeej 34:1311cc53201a 427 g_com_ctx.tim.stop();
Jeej 34:1311cc53201a 428 uint32_t time_us = g_com_ctx.tim.read_us();
Jeej 34:1311cc53201a 429 IPRINT("Ping in %d.%03dms\r\n", time_us/1000, time_us%1000);
Jeej 34:1311cc53201a 430 }
Jeej 30:d775c1409849 431 d7a_sys_new_pkt(pkt);
Jeej 30:d775c1409849 432 }
Jeej 30:d775c1409849 433 break;
Jeej 25:aac250164497 434 default:
Jeej 25:aac250164497 435 EPRINT("Untreated pkt type 0x%02X\r\n", pkt->id);
Jeej 25:aac250164497 436 FREE(pkt);
Jeej 25:aac250164497 437 break;
Jeej 25:aac250164497 438 }
Jeej 25:aac250164497 439 }
Jeej 24:a8433b091764 440
Jeej 37:e04613e021f2 441 void d7a_com_forward_buffer(uint8_t size)
Jeej 37:e04613e021f2 442 {
Jeej 37:e04613e021f2 443 g_com_ctx.read_idx = (g_com_ctx.read_idx + size) % g_com_ctx.rx_buffer_size;
Jeej 37:e04613e021f2 444 g_com_ctx.data_available -= size;
Jeej 37:e04613e021f2 445 }
Jeej 33:f9a542d3efaa 446
Jeej 24:a8433b091764 447 /**
Jeej 34:1311cc53201a 448 Reads the Rx buffer, parses the packets
Jeej 24:a8433b091764 449
Jeej 24:a8433b091764 450 @param void
Jeej 24:a8433b091764 451 @return void
Jeej 24:a8433b091764 452 */
Jeej 37:e04613e021f2 453 static void parse_packet_header(void)
Jeej 24:a8433b091764 454 {
Jeej 37:e04613e021f2 455 uint8_t header[KAL_COM_HEADER_LEN];
Jeej 37:e04613e021f2 456 uint8_t seqnum;
Jeej 33:f9a542d3efaa 457
Jeej 42:1578f0480dcb 458 ASSERT(g_com_ctx.data_available >= KAL_COM_HEADER_LEN, "Not enough data for header\r\n");
Jeej 42:1578f0480dcb 459
Jeej 37:e04613e021f2 460 g_com_ctx.skipped_bytes = 0;
Jeej 33:f9a542d3efaa 461
Jeej 37:e04613e021f2 462 // Lookup fist sync byte
Jeej 37:e04613e021f2 463 while (g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 24:a8433b091764 464 {
Jeej 37:e04613e021f2 465 if(KAL_COM_SYNC_BYTE_0 == g_com_ctx.rx_buffer[g_com_ctx.read_idx])
Jeej 24:a8433b091764 466 {
Jeej 37:e04613e021f2 467 // copy following data
Jeej 37:e04613e021f2 468 d7a_com_copy_to_linear(header, g_com_ctx.read_idx, KAL_COM_HEADER_LEN);
Jeej 37:e04613e021f2 469 if (KAL_COM_SYNC_BYTE_1 == header[1])
Jeej 33:f9a542d3efaa 470 {
Jeej 37:e04613e021f2 471 // Fill temp header
Jeej 37:e04613e021f2 472 g_com_ctx.msg.blen = header[2];
Jeej 37:e04613e021f2 473 seqnum = header[3];
Jeej 37:e04613e021f2 474 g_com_ctx.msg.id = header[4];
Jeej 37:e04613e021f2 475
Jeej 37:e04613e021f2 476 // Update seqnum
Jeej 37:e04613e021f2 477 WARNING(g_com_ctx.rx_seq == seqnum, "COM Bad seqnum expected:%d got:%d\r\n", g_com_ctx.rx_seq, seqnum);
Jeej 37:e04613e021f2 478 g_com_ctx.rx_seq = seqnum + 1;
Jeej 37:e04613e021f2 479
Jeej 37:e04613e021f2 480 // search for body
Jeej 37:e04613e021f2 481 d7a_com_forward_buffer(KAL_COM_HEADER_LEN);
Jeej 37:e04613e021f2 482 g_com_ctx.state = SEARCH_BODY;
Jeej 42:1578f0480dcb 483
Jeej 42:1578f0480dcb 484 // Start parsing if data is already available
Jeej 42:1578f0480dcb 485 if (g_com_ctx.data_available >= g_com_ctx.msg.blen)
Jeej 42:1578f0480dcb 486 {
Jeej 42:1578f0480dcb 487 g_com_ctx.state = PARSE_BODY;
Jeej 42:1578f0480dcb 488 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 489 }
Jeej 42:1578f0480dcb 490
Jeej 45:b85384e7d825 491 //DPRINT("COM header found (body %d/%d bytes)\r\n", g_com_ctx.data_available, g_com_ctx.msg.blen);
Jeej 33:f9a542d3efaa 492 break;
Jeej 33:f9a542d3efaa 493 }
Jeej 24:a8433b091764 494 }
Jeej 37:e04613e021f2 495
Jeej 37:e04613e021f2 496 // byte skipped
Jeej 37:e04613e021f2 497 WARNING(g_com_ctx.skipped_bytes != 1, "COM not sync. Searching for header.\r\n");
Jeej 37:e04613e021f2 498 d7a_com_forward_buffer(1);
Jeej 37:e04613e021f2 499 }
Jeej 37:e04613e021f2 500
Jeej 37:e04613e021f2 501 if (g_com_ctx.skipped_bytes)
Jeej 37:e04613e021f2 502 {
Jeej 45:b85384e7d825 503 WARNING(false, "COM Skipped %d bytes.\r\n", g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 504 #if 0
Jeej 37:e04613e021f2 505 uint8_t* temp = (uint8_t*)MALLOC(g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 506 d7a_com_copy_to_linear(temp, g_com_ctx.read_idx - g_com_ctx.skipped_bytes, g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 507 PRINT_DATA("", "%02X ", temp, g_com_ctx.skipped_bytes, "\r\n");
Jeej 37:e04613e021f2 508 FREE(temp);
Jeej 34:1311cc53201a 509 #endif
Jeej 37:e04613e021f2 510 g_com_ctx.skipped_bytes = 0;
Jeej 37:e04613e021f2 511 }
Jeej 37:e04613e021f2 512 }
Jeej 37:e04613e021f2 513
Jeej 37:e04613e021f2 514 /**
Jeej 37:e04613e021f2 515 Reads the Rx buffer, parses the packets
Jeej 37:e04613e021f2 516
Jeej 37:e04613e021f2 517 @param void
Jeej 37:e04613e021f2 518 @return void
Jeej 37:e04613e021f2 519 */
Jeej 37:e04613e021f2 520 static void parse_packet_body(void)
Jeej 37:e04613e021f2 521 {
Jeej 42:1578f0480dcb 522 ASSERT(g_com_ctx.data_available >= g_com_ctx.msg.blen, "Not enough data for body\r\n");
Jeej 42:1578f0480dcb 523
Jeej 37:e04613e021f2 524 if (KAL_COM_FLOWID(g_com_ctx.msg.id) != KAL_COM_FLOWID_TRC)
Jeej 37:e04613e021f2 525 {
Jeej 37:e04613e021f2 526 //DPRINT("Got packet id 0x%02X len %d\r\n", id, len);
Jeej 37:e04613e021f2 527
Jeej 37:e04613e021f2 528 d7a_com_rx_msg_t* pkt = NULL;
Jeej 37:e04613e021f2 529 pkt = (d7a_com_rx_msg_t*)MALLOC(sizeof(d7a_com_rx_msg_t) - 1 + g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 530
Jeej 37:e04613e021f2 531 // copy data to buffer
Jeej 37:e04613e021f2 532 pkt->blen = g_com_ctx.msg.blen;
Jeej 37:e04613e021f2 533 pkt->id = g_com_ctx.msg.id;
Jeej 37:e04613e021f2 534 d7a_com_copy_to_linear(pkt->buffer, g_com_ctx.read_idx, g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 535
Jeej 37:e04613e021f2 536 // add packet to queue
Jeej 37:e04613e021f2 537 d7a_com_new_pkt(pkt);
Jeej 37:e04613e021f2 538 }
Jeej 37:e04613e021f2 539 else
Jeej 37:e04613e021f2 540 {
Jeej 37:e04613e021f2 541 // Ignore packet
Jeej 24:a8433b091764 542 }
Jeej 33:f9a542d3efaa 543
Jeej 33:f9a542d3efaa 544 // update buffer indexes
Jeej 37:e04613e021f2 545 d7a_com_forward_buffer(g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 546 g_com_ctx.state = SEARCH_HEADER;
Jeej 42:1578f0480dcb 547
Jeej 42:1578f0480dcb 548 // Start parsing if data is already available
Jeej 42:1578f0480dcb 549 if (g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 42:1578f0480dcb 550 {
Jeej 42:1578f0480dcb 551 g_com_ctx.state = PARSE_HEADER;
Jeej 42:1578f0480dcb 552 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 553 }
Jeej 24:a8433b091764 554 }
Jeej 24:a8433b091764 555
Jeej 24:a8433b091764 556
Jeej 24:a8433b091764 557 // Thread for parsing packets from RX buffer.
Jeej 31:ab9bfdbc6b44 558 void d7a_com_rx_thread( void const *p )
Jeej 24:a8433b091764 559 {
Jeej 25:aac250164497 560 FPRINT("\r\n");
Jeej 24:a8433b091764 561 while (true)
Jeej 24:a8433b091764 562 {
Jeej 37:e04613e021f2 563 if (!g_com_ctx.rx_started)
Jeej 37:e04613e021f2 564 {
Jeej 37:e04613e021f2 565 g_com_ctx.rx_thread->signal_wait(START_SIGNAL);
Jeej 37:e04613e021f2 566 }
Jeej 37:e04613e021f2 567
Jeej 24:a8433b091764 568 // wait for data available
Jeej 24:a8433b091764 569 g_com_ctx.data_parsing->wait();
Jeej 37:e04613e021f2 570
Jeej 37:e04613e021f2 571 if (g_com_ctx.state == PARSE_HEADER)
Jeej 33:f9a542d3efaa 572 {
Jeej 37:e04613e021f2 573 parse_packet_header();
Jeej 37:e04613e021f2 574 }
Jeej 37:e04613e021f2 575 else if (g_com_ctx.state == PARSE_BODY)
Jeej 37:e04613e021f2 576 {
Jeej 37:e04613e021f2 577 parse_packet_body();
Jeej 33:f9a542d3efaa 578 }
Jeej 24:a8433b091764 579 }
Jeej 24:a8433b091764 580 }
Jeej 31:ab9bfdbc6b44 581
Jeej 31:ab9bfdbc6b44 582 void d7a_com_tx_thread( void const *p )
Jeej 31:ab9bfdbc6b44 583 {
Jeej 31:ab9bfdbc6b44 584 FPRINT("\r\n");
Jeej 31:ab9bfdbc6b44 585
Jeej 31:ab9bfdbc6b44 586 d7a_com_tx_buf_t* msg;
Jeej 31:ab9bfdbc6b44 587 osEvent evt;
Jeej 34:1311cc53201a 588 uint8_t flow_id;
Jeej 34:1311cc53201a 589
Jeej 31:ab9bfdbc6b44 590 while (true)
Jeej 31:ab9bfdbc6b44 591 {
Jeej 37:e04613e021f2 592 if (!g_com_ctx.tx_started)
Jeej 37:e04613e021f2 593 {
Jeej 37:e04613e021f2 594 g_com_ctx.tx_thread->signal_wait(START_SIGNAL);
Jeej 37:e04613e021f2 595 }
Jeej 37:e04613e021f2 596
Jeej 31:ab9bfdbc6b44 597 // wait for data to send
Jeej 31:ab9bfdbc6b44 598 evt = g_com_ctx.tx_queue.get();
Jeej 31:ab9bfdbc6b44 599 msg = (evt.status == osEventMessage)? (d7a_com_tx_buf_t*)evt.value.p : NULL;
Jeej 37:e04613e021f2 600
Jeej 31:ab9bfdbc6b44 601
Jeej 31:ab9bfdbc6b44 602 // send message
Jeej 31:ab9bfdbc6b44 603 if (msg != NULL)
Jeej 31:ab9bfdbc6b44 604 {
Jeej 34:1311cc53201a 605 flow_id = msg->buf[4];
Jeej 34:1311cc53201a 606
Jeej 45:b85384e7d825 607 d7a_com_send(msg);
Jeej 31:ab9bfdbc6b44 608 FREE(msg);
Jeej 34:1311cc53201a 609
Jeej 34:1311cc53201a 610 if (KAL_COM_FLOW_SYS_PING == flow_id)
Jeej 34:1311cc53201a 611 {
Jeej 34:1311cc53201a 612 g_com_ctx.tim.reset();
Jeej 34:1311cc53201a 613 g_com_ctx.tim.start();
Jeej 34:1311cc53201a 614 }
Jeej 34:1311cc53201a 615
Jeej 34:1311cc53201a 616 if (KAL_COM_FLOW_SYS_XACK == flow_id)
Jeej 34:1311cc53201a 617 {
Jeej 42:1578f0480dcb 618 DPRINT("XACK\r\n");
Jeej 34:1311cc53201a 619 g_com_ctx.tx_thread->signal_wait(XON_SIGNAL);
Jeej 34:1311cc53201a 620 }
Jeej 31:ab9bfdbc6b44 621 }
Jeej 31:ab9bfdbc6b44 622 }
Jeej 31:ab9bfdbc6b44 623 }