Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Committer:
Jeej
Date:
Fri Oct 21 15:31:45 2016 +0000
Revision:
66:492b1d7ba370
Parent:
65:ac3844adfe49
Child:
69:18852c154df9
Wait after sending data to not release the resource too soon

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