Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Committer:
Jeej
Date:
Mon Aug 22 13:47:39 2016 +0000
Revision:
34:1311cc53201a
Parent:
33:f9a542d3efaa
Child:
35:1fe2975c5a63
Working version with mbed rev 120

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