Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of d7a_1x by
src/d7a_com.cpp@76:fda2e34ff19d, 2016-12-20 (annotated)
- Committer:
- Jeej
- Date:
- Tue Dec 20 09:30:14 2016 +0000
- Revision:
- 76:fda2e34ff19d
- Parent:
- 71:f03727ff0f99
- Child:
- 77:8c792719a1fc
Updated for mbed OS 5
Who changed what in which revision?
| User | Revision | Line number | New 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 | 76:fda2e34ff19d | 11 | #include "cbuffer.h" |
| Jeej | 24:a8433b091764 | 12 | |
| Jeej | 76:fda2e34ff19d | 13 | #define LocalCBuffer CBuffer<uint8_t, 1024> |
| Jeej | 34:1311cc53201a | 14 | |
| Jeej | 37:e04613e021f2 | 15 | #define XON_SIGNAL (0x0001 << 0) |
| Jeej | 37:e04613e021f2 | 16 | #define START_SIGNAL (0x0001 << 1) |
| Jeej | 31:ab9bfdbc6b44 | 17 | |
| Jeej | 31:ab9bfdbc6b44 | 18 | typedef struct { |
| Jeej | 31:ab9bfdbc6b44 | 19 | uint32_t len; |
| Jeej | 45:b85384e7d825 | 20 | uint8_t buf[1]; |
| Jeej | 31:ab9bfdbc6b44 | 21 | } d7a_com_tx_buf_t; |
| Jeej | 30:d775c1409849 | 22 | |
| Jeej | 37:e04613e021f2 | 23 | enum { |
| Jeej | 37:e04613e021f2 | 24 | SEARCH_HEADER, |
| Jeej | 37:e04613e021f2 | 25 | PARSE_HEADER, |
| Jeej | 37:e04613e021f2 | 26 | SEARCH_BODY, |
| Jeej | 37:e04613e021f2 | 27 | PARSE_BODY, |
| Jeej | 37:e04613e021f2 | 28 | }; |
| Jeej | 30:d775c1409849 | 29 | |
| Jeej | 25:aac250164497 | 30 | typedef struct { |
| Jeej | 37:e04613e021f2 | 31 | bool rx_started; |
| Jeej | 37:e04613e021f2 | 32 | bool tx_started; |
| Jeej | 37:e04613e021f2 | 33 | |
| Jeej | 37:e04613e021f2 | 34 | uint8_t state; |
| Jeej | 34:1311cc53201a | 35 | |
| Jeej | 25:aac250164497 | 36 | DigitalOut* rts; |
| Jeej | 25:aac250164497 | 37 | InterruptIn* cts; |
| Jeej | 69:18852c154df9 | 38 | |
| Jeej | 76:fda2e34ff19d | 39 | LocalCBuffer* rx_buf; |
| Jeej | 69:18852c154df9 | 40 | |
| Jeej | 37:e04613e021f2 | 41 | // min data in buffer before parsing body |
| Jeej | 37:e04613e021f2 | 42 | d7a_com_rx_msg_t msg; |
| Jeej | 33:f9a542d3efaa | 43 | // Number of skipped bytes while parsing |
| Jeej | 33:f9a542d3efaa | 44 | uint16_t skipped_bytes; |
| Jeej | 33:f9a542d3efaa | 45 | |
| Jeej | 25:aac250164497 | 46 | // Port TX sequence number |
| Jeej | 25:aac250164497 | 47 | uint8_t tx_seq; |
| Jeej | 25:aac250164497 | 48 | // Port RX sequence number |
| Jeej | 25:aac250164497 | 49 | uint8_t rx_seq; |
| Jeej | 25:aac250164497 | 50 | // Response to command maximum time |
| Jeej | 25:aac250164497 | 51 | uint32_t timeout; |
| Jeej | 25:aac250164497 | 52 | |
| Jeej | 25:aac250164497 | 53 | // Waiting for data available in RX buffer |
| Jeej | 25:aac250164497 | 54 | Semaphore* data_parsing; |
| Jeej | 25:aac250164497 | 55 | // CTS management |
| Jeej | 25:aac250164497 | 56 | Semaphore* cts_int; |
| Jeej | 25:aac250164497 | 57 | |
| Jeej | 25:aac250164497 | 58 | // Data treatment threads |
| Jeej | 31:ab9bfdbc6b44 | 59 | Thread* rx_thread; |
| Jeej | 76:fda2e34ff19d | 60 | RawSerial* serial; |
| Jeej | 25:aac250164497 | 61 | |
| Jeej | 31:ab9bfdbc6b44 | 62 | // Tx Thread |
| Jeej | 31:ab9bfdbc6b44 | 63 | Thread* tx_thread; |
| Jeej | 31:ab9bfdbc6b44 | 64 | Queue<d7a_com_tx_buf_t, 32> tx_queue; |
| Jeej | 31:ab9bfdbc6b44 | 65 | |
| Jeej | 34:1311cc53201a | 66 | Timer tim; |
| Jeej | 34:1311cc53201a | 67 | |
| Jeej | 25:aac250164497 | 68 | } d7a_com_ctx_t; |
| Jeej | 24:a8433b091764 | 69 | |
| Jeej | 31:ab9bfdbc6b44 | 70 | |
| Jeej | 24:a8433b091764 | 71 | static d7a_com_ctx_t g_com_ctx; |
| Jeej | 24:a8433b091764 | 72 | |
| Jeej | 24:a8433b091764 | 73 | /** |
| Jeej | 24:a8433b091764 | 74 | Thread for parsing packets from RX buffer. |
| Jeej | 24:a8433b091764 | 75 | |
| Jeej | 24:a8433b091764 | 76 | @param void |
| Jeej | 24:a8433b091764 | 77 | @return void |
| Jeej | 24:a8433b091764 | 78 | */ |
| Jeej | 76:fda2e34ff19d | 79 | void d7a_com_rx_thread(); |
| Jeej | 76:fda2e34ff19d | 80 | void d7a_com_tx_thread(); |
| Jeej | 31:ab9bfdbc6b44 | 81 | |
| Jeej | 24:a8433b091764 | 82 | |
| Jeej | 24:a8433b091764 | 83 | /** |
| Jeej | 24:a8433b091764 | 84 | Serial Rx Interrupt Service Routine. |
| Jeej | 24:a8433b091764 | 85 | Add recevied bytes to the RX buffer. |
| Jeej | 24:a8433b091764 | 86 | |
| Jeej | 24:a8433b091764 | 87 | @param void |
| Jeej | 24:a8433b091764 | 88 | @return void |
| Jeej | 24:a8433b091764 | 89 | */ |
| Jeej | 24:a8433b091764 | 90 | void rx_isr() |
| Jeej | 24:a8433b091764 | 91 | { |
| Jeej | 24:a8433b091764 | 92 | // Loop just in case more than one character is in UART's receive FIFO buffer |
| Jeej | 24:a8433b091764 | 93 | // Stop if buffer full |
| Jeej | 34:1311cc53201a | 94 | while (g_com_ctx.serial->readable()) |
| Jeej | 34:1311cc53201a | 95 | { |
| Jeej | 34:1311cc53201a | 96 | |
| Jeej | 69:18852c154df9 | 97 | g_com_ctx.rx_buf->push(g_com_ctx.serial->getc()); |
| Jeej | 34:1311cc53201a | 98 | //PRINT("-"); |
| Jeej | 34:1311cc53201a | 99 | |
| Jeej | 42:1578f0480dcb | 100 | //if (g_com_ctx.rx_started) |
| Jeej | 34:1311cc53201a | 101 | { |
| Jeej | 42:1578f0480dcb | 102 | // unlock data parsing thread |
| Jeej | 76:fda2e34ff19d | 103 | if (g_com_ctx.state == SEARCH_HEADER && g_com_ctx.rx_buf->available_data() >= KAL_COM_HEADER_LEN) |
| Jeej | 42:1578f0480dcb | 104 | { |
| Jeej | 42:1578f0480dcb | 105 | g_com_ctx.state = PARSE_HEADER; |
| Jeej | 42:1578f0480dcb | 106 | g_com_ctx.data_parsing->release(); |
| Jeej | 42:1578f0480dcb | 107 | } |
| Jeej | 76:fda2e34ff19d | 108 | else if (g_com_ctx.state == SEARCH_BODY && g_com_ctx.rx_buf->available_data() >= g_com_ctx.msg.blen) |
| Jeej | 42:1578f0480dcb | 109 | { |
| Jeej | 42:1578f0480dcb | 110 | g_com_ctx.state = PARSE_BODY; |
| Jeej | 42:1578f0480dcb | 111 | g_com_ctx.data_parsing->release(); |
| Jeej | 42:1578f0480dcb | 112 | } |
| Jeej | 34:1311cc53201a | 113 | } |
| Jeej | 24:a8433b091764 | 114 | } |
| Jeej | 24:a8433b091764 | 115 | } |
| Jeej | 24:a8433b091764 | 116 | |
| Jeej | 24:a8433b091764 | 117 | /** |
| Jeej | 24:a8433b091764 | 118 | CTS pin Interrupt Service Routine. |
| Jeej | 24:a8433b091764 | 119 | For flow control (not yet inplemented) |
| Jeej | 24:a8433b091764 | 120 | |
| Jeej | 24:a8433b091764 | 121 | @param void |
| Jeej | 24:a8433b091764 | 122 | @return void |
| Jeej | 24:a8433b091764 | 123 | */ |
| Jeej | 24:a8433b091764 | 124 | void cts_isr() |
| Jeej | 24:a8433b091764 | 125 | { |
| Jeej | 34:1311cc53201a | 126 | //PRINT("CTS_INT\r\n"); |
| Jeej | 34:1311cc53201a | 127 | //g_com_ctx.cts_int->release(); |
| Jeej | 24:a8433b091764 | 128 | } |
| Jeej | 24:a8433b091764 | 129 | |
| Jeej | 26:9f0b9833cac6 | 130 | // D7a_com constructor. |
| Jeej | 26:9f0b9833cac6 | 131 | // Opens a serial port and monitors the input for ALP packets. |
| Jeej | 26:9f0b9833cac6 | 132 | // Pins are those of the host, not the modem: |
| Jeej | 26:9f0b9833cac6 | 133 | // TX-host -> RX-modem |
| Jeej | 26:9f0b9833cac6 | 134 | // RX-host <- TX-modem |
| Jeej | 26:9f0b9833cac6 | 135 | // RTS-host -> CTS-modem |
| Jeej | 26:9f0b9833cac6 | 136 | // CTS-host <- RTS-modem |
| Jeej | 49:81d5bddb02f0 | 137 | d7a_errors_t d7a_com_open( const d7a_com_config_t* config ) |
| Jeej | 26:9f0b9833cac6 | 138 | { |
| Jeej | 26:9f0b9833cac6 | 139 | FPRINT("\r\n"); |
| Jeej | 26:9f0b9833cac6 | 140 | |
| Jeej | 37:e04613e021f2 | 141 | g_com_ctx.state = SEARCH_HEADER; |
| Jeej | 33:f9a542d3efaa | 142 | g_com_ctx.skipped_bytes = 0; |
| Jeej | 26:9f0b9833cac6 | 143 | g_com_ctx.tx_seq = 0; |
| Jeej | 26:9f0b9833cac6 | 144 | g_com_ctx.rx_seq = 0; |
| Jeej | 26:9f0b9833cac6 | 145 | |
| Jeej | 76:fda2e34ff19d | 146 | g_com_ctx.serial = new RawSerial(config->tx, config->rx); |
| Jeej | 26:9f0b9833cac6 | 147 | g_com_ctx.rts = new DigitalOut(config->rts); |
| Jeej | 26:9f0b9833cac6 | 148 | g_com_ctx.cts = new InterruptIn(config->cts); |
| Jeej | 34:1311cc53201a | 149 | g_com_ctx.data_parsing = new Semaphore(0); |
| Jeej | 34:1311cc53201a | 150 | g_com_ctx.cts_int = new Semaphore(0); |
| Jeej | 31:ab9bfdbc6b44 | 151 | |
| Jeej | 34:1311cc53201a | 152 | g_com_ctx.cts->rise(&cts_isr); |
| Jeej | 69:18852c154df9 | 153 | |
| Jeej | 76:fda2e34ff19d | 154 | g_com_ctx.rx_buf = new LocalCBuffer; |
| Jeej | 34:1311cc53201a | 155 | |
| Jeej | 76:fda2e34ff19d | 156 | g_com_ctx.serial->baud(115200); |
| Jeej | 26:9f0b9833cac6 | 157 | g_com_ctx.serial->format(8, SerialBase::None, 1); |
| Jeej | 26:9f0b9833cac6 | 158 | g_com_ctx.serial->attach(&rx_isr, Serial::RxIrq); |
| Jeej | 30:d775c1409849 | 159 | |
| Jeej | 76:fda2e34ff19d | 160 | g_com_ctx.tx_thread = new Thread(osPriorityHigh, DEFAULT_STACK_SIZE*2, NULL); |
| Jeej | 76:fda2e34ff19d | 161 | g_com_ctx.rx_thread = new Thread(osPriorityHigh, DEFAULT_STACK_SIZE*2, NULL); |
| Jeej | 76:fda2e34ff19d | 162 | |
| Jeej | 76:fda2e34ff19d | 163 | osStatus err = g_com_ctx.rx_thread->start(d7a_com_rx_thread); |
| Jeej | 76:fda2e34ff19d | 164 | ASSERT(err == osOK, "Failed to start d7a_com_rx_thread (err: %d)\r\n", err); |
| Jeej | 76:fda2e34ff19d | 165 | |
| Jeej | 76:fda2e34ff19d | 166 | err = g_com_ctx.tx_thread->start(d7a_com_tx_thread); |
| Jeej | 76:fda2e34ff19d | 167 | ASSERT(err == osOK, "Failed to start d7a_com_tx_thread (err: %d)\r\n", err); |
| Jeej | 49:81d5bddb02f0 | 168 | |
| Jeej | 49:81d5bddb02f0 | 169 | return D7A_ERR_NONE; |
| Jeej | 26:9f0b9833cac6 | 170 | } |
| Jeej | 26:9f0b9833cac6 | 171 | |
| Jeej | 26:9f0b9833cac6 | 172 | // Destructor |
| Jeej | 56:da34fc11e760 | 173 | d7a_errors_t d7a_com_close(void) |
| Jeej | 26:9f0b9833cac6 | 174 | { |
| Jeej | 26:9f0b9833cac6 | 175 | FPRINT("\r\n"); |
| Jeej | 31:ab9bfdbc6b44 | 176 | g_com_ctx.rx_thread->terminate(); |
| Jeej | 31:ab9bfdbc6b44 | 177 | g_com_ctx.tx_thread->terminate(); |
| Jeej | 26:9f0b9833cac6 | 178 | delete g_com_ctx.data_parsing; |
| Jeej | 26:9f0b9833cac6 | 179 | delete g_com_ctx.cts_int; |
| Jeej | 26:9f0b9833cac6 | 180 | delete g_com_ctx.serial; |
| Jeej | 26:9f0b9833cac6 | 181 | delete g_com_ctx.rts; |
| Jeej | 26:9f0b9833cac6 | 182 | delete g_com_ctx.cts; |
| Jeej | 69:18852c154df9 | 183 | delete g_com_ctx.rx_buf; |
| Jeej | 49:81d5bddb02f0 | 184 | |
| Jeej | 49:81d5bddb02f0 | 185 | return D7A_ERR_NONE; |
| Jeej | 26:9f0b9833cac6 | 186 | } |
| Jeej | 26:9f0b9833cac6 | 187 | |
| Jeej | 37:e04613e021f2 | 188 | void d7a_com_start_rx(void) |
| Jeej | 37:e04613e021f2 | 189 | { |
| Jeej | 37:e04613e021f2 | 190 | FPRINT("\r\n"); |
| Jeej | 37:e04613e021f2 | 191 | g_com_ctx.rx_started = true; |
| Jeej | 37:e04613e021f2 | 192 | g_com_ctx.rx_thread->signal_set(START_SIGNAL); |
| Jeej | 37:e04613e021f2 | 193 | } |
| Jeej | 37:e04613e021f2 | 194 | |
| Jeej | 37:e04613e021f2 | 195 | void d7a_com_stop_rx(void) |
| Jeej | 34:1311cc53201a | 196 | { |
| Jeej | 34:1311cc53201a | 197 | FPRINT("\r\n"); |
| Jeej | 37:e04613e021f2 | 198 | g_com_ctx.rx_started = false; |
| Jeej | 37:e04613e021f2 | 199 | } |
| Jeej | 37:e04613e021f2 | 200 | |
| Jeej | 37:e04613e021f2 | 201 | void d7a_com_start_tx(void) |
| Jeej | 37:e04613e021f2 | 202 | { |
| Jeej | 37:e04613e021f2 | 203 | FPRINT("\r\n"); |
| Jeej | 37:e04613e021f2 | 204 | g_com_ctx.tx_started = true; |
| Jeej | 37:e04613e021f2 | 205 | g_com_ctx.tx_thread->signal_set(START_SIGNAL); |
| Jeej | 37:e04613e021f2 | 206 | } |
| Jeej | 37:e04613e021f2 | 207 | |
| Jeej | 37:e04613e021f2 | 208 | void d7a_com_stop_tx(void) |
| Jeej | 37:e04613e021f2 | 209 | { |
| Jeej | 37:e04613e021f2 | 210 | FPRINT("\r\n"); |
| Jeej | 37:e04613e021f2 | 211 | g_com_ctx.tx_started = false; |
| Jeej | 34:1311cc53201a | 212 | } |
| Jeej | 34:1311cc53201a | 213 | |
| Jeej | 34:1311cc53201a | 214 | void d7a_com_restart(void) |
| Jeej | 34:1311cc53201a | 215 | { |
| Jeej | 34:1311cc53201a | 216 | FPRINT("\r\n"); |
| Jeej | 69:18852c154df9 | 217 | |
| Jeej | 69:18852c154df9 | 218 | g_com_ctx.serial->attach(NULL, Serial::RxIrq); |
| Jeej | 42:1578f0480dcb | 219 | |
| Jeej | 42:1578f0480dcb | 220 | g_com_ctx.state = SEARCH_HEADER; |
| Jeej | 34:1311cc53201a | 221 | g_com_ctx.skipped_bytes = 0; |
| Jeej | 34:1311cc53201a | 222 | g_com_ctx.tx_seq = 0; |
| Jeej | 34:1311cc53201a | 223 | g_com_ctx.rx_seq = 0; |
| Jeej | 34:1311cc53201a | 224 | |
| Jeej | 69:18852c154df9 | 225 | g_com_ctx.rx_buf->reset(); |
| Jeej | 34:1311cc53201a | 226 | |
| Jeej | 69:18852c154df9 | 227 | g_com_ctx.serial->attach(&rx_isr, Serial::RxIrq); |
| Jeej | 34:1311cc53201a | 228 | } |
| Jeej | 34:1311cc53201a | 229 | |
| Jeej | 42:1578f0480dcb | 230 | |
| Jeej | 24:a8433b091764 | 231 | /** |
| Jeej | 24:a8433b091764 | 232 | Wakes-up modem and send data throught Serial. |
| Jeej | 24:a8433b091764 | 233 | |
| Jeej | 24:a8433b091764 | 234 | @param const uint8_t* Pointer to data buffer |
| Jeej | 24:a8433b091764 | 235 | @param int Data length |
| Jeej | 24:a8433b091764 | 236 | @return void |
| Jeej | 24:a8433b091764 | 237 | */ |
| Jeej | 45:b85384e7d825 | 238 | static void d7a_com_send(d7a_com_tx_buf_t* tx_buf) |
| Jeej | 69:18852c154df9 | 239 | { |
| Jeej | 45:b85384e7d825 | 240 | FPRINT("\r\n"); |
| Jeej | 45:b85384e7d825 | 241 | |
| Jeej | 45:b85384e7d825 | 242 | DPRINT("<-- (0x%02X) %d\r\n", tx_buf->buf[4], (tx_buf->len - KAL_COM_HEADER_LEN)); |
| Jeej | 34:1311cc53201a | 243 | |
| Jeej | 24:a8433b091764 | 244 | *(g_com_ctx.rts) = 1; |
| Jeej | 24:a8433b091764 | 245 | |
| Jeej | 47:19f22e1a448a | 246 | //dbg_print_data("", "%02X ", (uint8_t*)tx_buf->buf, tx_buf->len, "\r\n"); |
| Jeej | 45:b85384e7d825 | 247 | |
| Jeej | 70:07b378285c95 | 248 | Thread::wait(3); |
| Jeej | 24:a8433b091764 | 249 | |
| Jeej | 45:b85384e7d825 | 250 | for (uint32_t i=0 ; i<tx_buf->len ; i++) |
| Jeej | 24:a8433b091764 | 251 | { |
| Jeej | 45:b85384e7d825 | 252 | g_com_ctx.serial->putc(tx_buf->buf[i]); |
| Jeej | 24:a8433b091764 | 253 | } |
| Jeej | 24:a8433b091764 | 254 | |
| Jeej | 66:492b1d7ba370 | 255 | // Important to not release the ressource too soon |
| Jeej | 70:07b378285c95 | 256 | Thread::wait(2); |
| Jeej | 42:1578f0480dcb | 257 | |
| Jeej | 24:a8433b091764 | 258 | *(g_com_ctx.rts) = 0; |
| Jeej | 24:a8433b091764 | 259 | } |
| Jeej | 24:a8433b091764 | 260 | |
| Jeej | 26:9f0b9833cac6 | 261 | // Formats and send packet throught Serial. |
| Jeej | 45:b85384e7d825 | 262 | d7a_com_tx_buf_t* d7a_com_new_msg(d7a_com_tx_msg_t* msg) |
| Jeej | 34:1311cc53201a | 263 | { |
| Jeej | 45:b85384e7d825 | 264 | uint8_t len = KAL_COM_HEADER_LEN + msg->alen + msg->plen; |
| Jeej | 34:1311cc53201a | 265 | FPRINT("(len:%d)\r\n", len); |
| Jeej | 34:1311cc53201a | 266 | |
| Jeej | 45:b85384e7d825 | 267 | d7a_com_tx_buf_t* tx_buf = (d7a_com_tx_buf_t*)MALLOC(sizeof(d7a_com_tx_buf_t) - 1 + len); |
| Jeej | 34:1311cc53201a | 268 | |
| Jeej | 34:1311cc53201a | 269 | // construct serial header |
| Jeej | 34:1311cc53201a | 270 | // concatenate and update tx_seq ID |
| Jeej | 45:b85384e7d825 | 271 | uint8_t* p = tx_buf->buf; |
| Jeej | 45:b85384e7d825 | 272 | uint8_t* t = p; |
| Jeej | 45:b85384e7d825 | 273 | *p++ = (uint8_t)KAL_COM_SYNC_BYTE_0; |
| Jeej | 45:b85384e7d825 | 274 | *p++ = (uint8_t)KAL_COM_SYNC_BYTE_1; |
| Jeej | 45:b85384e7d825 | 275 | *p++ = (uint8_t)msg->alen + msg->plen; |
| Jeej | 45:b85384e7d825 | 276 | *p++ = (uint8_t)g_com_ctx.tx_seq++; |
| Jeej | 45:b85384e7d825 | 277 | *p++ = (uint8_t)msg->id; |
| Jeej | 34:1311cc53201a | 278 | |
| Jeej | 34:1311cc53201a | 279 | // copy payload and parameters |
| Jeej | 45:b85384e7d825 | 280 | memcpy(p, msg->pbuf, msg->plen); |
| Jeej | 45:b85384e7d825 | 281 | p += msg->plen; |
| Jeej | 45:b85384e7d825 | 282 | memcpy(p, msg->abuf, msg->alen); |
| Jeej | 45:b85384e7d825 | 283 | p += msg->alen; |
| Jeej | 34:1311cc53201a | 284 | |
| Jeej | 45:b85384e7d825 | 285 | tx_buf->len = (uint32_t)(p - t); |
| Jeej | 34:1311cc53201a | 286 | |
| Jeej | 45:b85384e7d825 | 287 | ASSERT(tx_buf->len == len, "New msg wrong length %d expected %d\r\n", tx_buf->len, len); |
| Jeej | 45:b85384e7d825 | 288 | |
| Jeej | 45:b85384e7d825 | 289 | return tx_buf; |
| Jeej | 34:1311cc53201a | 290 | } |
| Jeej | 34:1311cc53201a | 291 | |
| Jeej | 34:1311cc53201a | 292 | void d7a_com_post_msg(d7a_com_tx_msg_t* msg) |
| Jeej | 45:b85384e7d825 | 293 | { |
| Jeej | 45:b85384e7d825 | 294 | FPRINT("\r\n"); |
| Jeej | 26:9f0b9833cac6 | 295 | |
| Jeej | 45:b85384e7d825 | 296 | g_com_ctx.tx_queue.put(d7a_com_new_msg(msg)); |
| Jeej | 26:9f0b9833cac6 | 297 | } |
| Jeej | 26:9f0b9833cac6 | 298 | |
| Jeej | 30:d775c1409849 | 299 | void d7a_com_dump(uint8_t* buf, uint8_t len, d7a_com_flow_t flow) |
| Jeej | 30:d775c1409849 | 300 | { |
| Jeej | 30:d775c1409849 | 301 | d7a_com_tx_msg_t msg; |
| Jeej | 30:d775c1409849 | 302 | |
| Jeej | 30:d775c1409849 | 303 | msg.id = flow; |
| Jeej | 30:d775c1409849 | 304 | msg.pbuf = buf; |
| Jeej | 30:d775c1409849 | 305 | msg.plen = len; |
| Jeej | 30:d775c1409849 | 306 | msg.alen = 0; |
| Jeej | 34:1311cc53201a | 307 | d7a_com_post_msg(&msg); |
| Jeej | 30:d775c1409849 | 308 | } |
| Jeej | 30:d775c1409849 | 309 | |
| Jeej | 25:aac250164497 | 310 | static void d7a_com_new_pkt(d7a_com_rx_msg_t* pkt) |
| Jeej | 25:aac250164497 | 311 | { |
| Jeej | 26:9f0b9833cac6 | 312 | //FPRINT("\r\n"); |
| Jeej | 35:1fe2975c5a63 | 313 | |
| Jeej | 35:1fe2975c5a63 | 314 | DPRINT("--> (0x%02X) %d\r\n", pkt->id, pkt->blen); |
| Jeej | 35:1fe2975c5a63 | 315 | |
| Jeej | 25:aac250164497 | 316 | // Distribute packet types to processes |
| Jeej | 25:aac250164497 | 317 | switch (KAL_COM_FLOWID(pkt->id)) |
| Jeej | 25:aac250164497 | 318 | { |
| Jeej | 25:aac250164497 | 319 | case KAL_COM_FLOWID_FS: |
| Jeej | 25:aac250164497 | 320 | d7a_fs_new_pkt(pkt); |
| Jeej | 25:aac250164497 | 321 | break; |
| Jeej | 25:aac250164497 | 322 | case KAL_COM_FLOWID_CMD: |
| Jeej | 25:aac250164497 | 323 | d7a_modem_new_pkt(pkt); |
| Jeej | 25:aac250164497 | 324 | break; |
| Jeej | 45:b85384e7d825 | 325 | case KAL_COM_FLOWID_ALP: |
| Jeej | 45:b85384e7d825 | 326 | d7a_alp_new_pkt(pkt); |
| Jeej | 45:b85384e7d825 | 327 | break; |
| Jeej | 25:aac250164497 | 328 | case KAL_COM_FLOWID_SYS: |
| Jeej | 30:d775c1409849 | 329 | // This has to be here to avoid going to another process |
| Jeej | 30:d775c1409849 | 330 | if (pkt->id == KAL_COM_FLOW_SYS_XON) |
| Jeej | 30:d775c1409849 | 331 | { |
| Jeej | 65:ac3844adfe49 | 332 | FREE(pkt); |
| Jeej | 42:1578f0480dcb | 333 | DPRINT("XON\r\n"); |
| Jeej | 34:1311cc53201a | 334 | g_com_ctx.tx_thread->signal_set(XON_SIGNAL); |
| Jeej | 30:d775c1409849 | 335 | } |
| Jeej | 30:d775c1409849 | 336 | else if (pkt->id == KAL_COM_FLOW_SYS_XOFF) |
| Jeej | 30:d775c1409849 | 337 | { |
| Jeej | 65:ac3844adfe49 | 338 | FREE(pkt); |
| Jeej | 42:1578f0480dcb | 339 | DPRINT("XOFF\r\n"); |
| Jeej | 34:1311cc53201a | 340 | d7a_sys_xack(); |
| Jeej | 30:d775c1409849 | 341 | } |
| Jeej | 30:d775c1409849 | 342 | else |
| Jeej | 30:d775c1409849 | 343 | { |
| Jeej | 30:d775c1409849 | 344 | d7a_sys_new_pkt(pkt); |
| Jeej | 30:d775c1409849 | 345 | } |
| Jeej | 30:d775c1409849 | 346 | break; |
| Jeej | 25:aac250164497 | 347 | default: |
| Jeej | 25:aac250164497 | 348 | EPRINT("Untreated pkt type 0x%02X\r\n", pkt->id); |
| Jeej | 25:aac250164497 | 349 | FREE(pkt); |
| Jeej | 25:aac250164497 | 350 | break; |
| Jeej | 25:aac250164497 | 351 | } |
| Jeej | 25:aac250164497 | 352 | } |
| Jeej | 24:a8433b091764 | 353 | |
| Jeej | 33:f9a542d3efaa | 354 | |
| Jeej | 24:a8433b091764 | 355 | /** |
| Jeej | 34:1311cc53201a | 356 | Reads the Rx buffer, parses the packets |
| Jeej | 24:a8433b091764 | 357 | |
| Jeej | 24:a8433b091764 | 358 | @param void |
| Jeej | 24:a8433b091764 | 359 | @return void |
| Jeej | 24:a8433b091764 | 360 | */ |
| Jeej | 37:e04613e021f2 | 361 | static void parse_packet_header(void) |
| Jeej | 24:a8433b091764 | 362 | { |
| Jeej | 76:fda2e34ff19d | 363 | FPRINT("\r\n"); |
| Jeej | 76:fda2e34ff19d | 364 | |
| Jeej | 37:e04613e021f2 | 365 | uint8_t header[KAL_COM_HEADER_LEN]; |
| Jeej | 37:e04613e021f2 | 366 | uint8_t seqnum; |
| Jeej | 33:f9a542d3efaa | 367 | |
| Jeej | 76:fda2e34ff19d | 368 | ASSERT(g_com_ctx.rx_buf->available_data() >= KAL_COM_HEADER_LEN, "Not enough data for header\r\n"); |
| Jeej | 42:1578f0480dcb | 369 | |
| Jeej | 37:e04613e021f2 | 370 | g_com_ctx.skipped_bytes = 0; |
| Jeej | 33:f9a542d3efaa | 371 | |
| Jeej | 69:18852c154df9 | 372 | header[0] = g_com_ctx.rx_buf->pop(); |
| Jeej | 69:18852c154df9 | 373 | |
| Jeej | 76:fda2e34ff19d | 374 | while (g_com_ctx.rx_buf->available_data() >= KAL_COM_HEADER_LEN - 1) |
| Jeej | 24:a8433b091764 | 375 | { |
| Jeej | 69:18852c154df9 | 376 | header[1] = g_com_ctx.rx_buf->pop(); |
| Jeej | 69:18852c154df9 | 377 | |
| Jeej | 69:18852c154df9 | 378 | // Check sync bytes |
| Jeej | 69:18852c154df9 | 379 | if(KAL_COM_SYNC_BYTE_0 == header[0] && KAL_COM_SYNC_BYTE_1 == header[1]) |
| Jeej | 24:a8433b091764 | 380 | { |
| Jeej | 69:18852c154df9 | 381 | // Copy header |
| Jeej | 69:18852c154df9 | 382 | g_com_ctx.rx_buf->get(&header[2], KAL_COM_HEADER_LEN - 2); |
| Jeej | 69:18852c154df9 | 383 | |
| Jeej | 69:18852c154df9 | 384 | // Fill temp header |
| Jeej | 69:18852c154df9 | 385 | g_com_ctx.msg.blen = header[2]; |
| Jeej | 69:18852c154df9 | 386 | seqnum = header[3]; |
| Jeej | 69:18852c154df9 | 387 | g_com_ctx.msg.id = header[4]; |
| Jeej | 69:18852c154df9 | 388 | |
| Jeej | 69:18852c154df9 | 389 | // Update seqnum |
| Jeej | 69:18852c154df9 | 390 | WARNING(g_com_ctx.rx_seq == seqnum, "COM Bad seqnum expected:%d got:%d\r\n", g_com_ctx.rx_seq, seqnum); |
| Jeej | 69:18852c154df9 | 391 | g_com_ctx.rx_seq = seqnum + 1; |
| Jeej | 69:18852c154df9 | 392 | |
| Jeej | 69:18852c154df9 | 393 | // search for body |
| Jeej | 69:18852c154df9 | 394 | g_com_ctx.state = SEARCH_BODY; |
| Jeej | 69:18852c154df9 | 395 | |
| Jeej | 69:18852c154df9 | 396 | // Start parsing if data is already available |
| Jeej | 76:fda2e34ff19d | 397 | if (g_com_ctx.rx_buf->available_data() >= g_com_ctx.msg.blen) |
| Jeej | 33:f9a542d3efaa | 398 | { |
| Jeej | 69:18852c154df9 | 399 | g_com_ctx.state = PARSE_BODY; |
| Jeej | 69:18852c154df9 | 400 | g_com_ctx.data_parsing->release(); |
| Jeej | 33:f9a542d3efaa | 401 | } |
| Jeej | 69:18852c154df9 | 402 | |
| Jeej | 76:fda2e34ff19d | 403 | //DPRINT("COM header found (id: %02X seq: %d body: %d/%d bytes)\r\n", g_com_ctx.msg.id, seqnum, g_com_ctx.rx_buf->available_data(), g_com_ctx.msg.blen); |
| Jeej | 69:18852c154df9 | 404 | break; |
| Jeej | 24:a8433b091764 | 405 | } |
| Jeej | 69:18852c154df9 | 406 | else |
| Jeej | 69:18852c154df9 | 407 | { |
| Jeej | 69:18852c154df9 | 408 | // Shift by 1 byte |
| Jeej | 69:18852c154df9 | 409 | WARNING(false, "COM Skipped byte 0x%02X.\r\n", header[0]); |
| Jeej | 69:18852c154df9 | 410 | header[0] = header[1]; |
| Jeej | 69:18852c154df9 | 411 | } |
| Jeej | 37:e04613e021f2 | 412 | } |
| Jeej | 37:e04613e021f2 | 413 | } |
| Jeej | 37:e04613e021f2 | 414 | |
| Jeej | 37:e04613e021f2 | 415 | /** |
| Jeej | 37:e04613e021f2 | 416 | Reads the Rx buffer, parses the packets |
| Jeej | 37:e04613e021f2 | 417 | |
| Jeej | 37:e04613e021f2 | 418 | @param void |
| Jeej | 37:e04613e021f2 | 419 | @return void |
| Jeej | 37:e04613e021f2 | 420 | */ |
| Jeej | 37:e04613e021f2 | 421 | static void parse_packet_body(void) |
| Jeej | 37:e04613e021f2 | 422 | { |
| Jeej | 76:fda2e34ff19d | 423 | ASSERT(g_com_ctx.rx_buf->available_data() >= g_com_ctx.msg.blen, "Not enough data for body\r\n"); |
| Jeej | 42:1578f0480dcb | 424 | |
| Jeej | 37:e04613e021f2 | 425 | if (KAL_COM_FLOWID(g_com_ctx.msg.id) != KAL_COM_FLOWID_TRC) |
| Jeej | 37:e04613e021f2 | 426 | { |
| Jeej | 65:ac3844adfe49 | 427 | //DPRINT("COM body found (%d bytes)\r\n", g_com_ctx.msg.blen); |
| Jeej | 37:e04613e021f2 | 428 | |
| Jeej | 65:ac3844adfe49 | 429 | 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 | 430 | |
| Jeej | 37:e04613e021f2 | 431 | // copy data to buffer |
| Jeej | 37:e04613e021f2 | 432 | pkt->blen = g_com_ctx.msg.blen; |
| Jeej | 37:e04613e021f2 | 433 | pkt->id = g_com_ctx.msg.id; |
| Jeej | 69:18852c154df9 | 434 | g_com_ctx.rx_buf->get(pkt->buffer, g_com_ctx.msg.blen); |
| Jeej | 65:ac3844adfe49 | 435 | |
| Jeej | 37:e04613e021f2 | 436 | // add packet to queue |
| Jeej | 37:e04613e021f2 | 437 | d7a_com_new_pkt(pkt); |
| Jeej | 37:e04613e021f2 | 438 | } |
| Jeej | 37:e04613e021f2 | 439 | else |
| Jeej | 37:e04613e021f2 | 440 | { |
| Jeej | 37:e04613e021f2 | 441 | // Ignore packet |
| Jeej | 65:ac3844adfe49 | 442 | //DPRINT("Ignore pkt id %02X\r\n", g_com_ctx.msg.id); |
| Jeej | 69:18852c154df9 | 443 | g_com_ctx.rx_buf->get(NULL, g_com_ctx.msg.blen); |
| Jeej | 24:a8433b091764 | 444 | } |
| Jeej | 33:f9a542d3efaa | 445 | |
| Jeej | 69:18852c154df9 | 446 | // Seach for next header |
| Jeej | 37:e04613e021f2 | 447 | g_com_ctx.state = SEARCH_HEADER; |
| Jeej | 42:1578f0480dcb | 448 | |
| Jeej | 42:1578f0480dcb | 449 | // Start parsing if data is already available |
| Jeej | 76:fda2e34ff19d | 450 | if (g_com_ctx.rx_buf->available_data() >= KAL_COM_HEADER_LEN) |
| Jeej | 42:1578f0480dcb | 451 | { |
| Jeej | 42:1578f0480dcb | 452 | g_com_ctx.state = PARSE_HEADER; |
| Jeej | 42:1578f0480dcb | 453 | g_com_ctx.data_parsing->release(); |
| Jeej | 42:1578f0480dcb | 454 | } |
| Jeej | 24:a8433b091764 | 455 | } |
| Jeej | 24:a8433b091764 | 456 | |
| Jeej | 24:a8433b091764 | 457 | |
| Jeej | 24:a8433b091764 | 458 | // Thread for parsing packets from RX buffer. |
| Jeej | 76:fda2e34ff19d | 459 | void d7a_com_rx_thread() |
| Jeej | 24:a8433b091764 | 460 | { |
| Jeej | 58:38a366236bda | 461 | FPRINT("(id:0x%08x)\r\n", osThreadGetId()); |
| Jeej | 24:a8433b091764 | 462 | while (true) |
| Jeej | 24:a8433b091764 | 463 | { |
| Jeej | 24:a8433b091764 | 464 | // wait for data available |
| Jeej | 24:a8433b091764 | 465 | g_com_ctx.data_parsing->wait(); |
| Jeej | 37:e04613e021f2 | 466 | |
| Jeej | 37:e04613e021f2 | 467 | if (g_com_ctx.state == PARSE_HEADER) |
| Jeej | 33:f9a542d3efaa | 468 | { |
| Jeej | 37:e04613e021f2 | 469 | parse_packet_header(); |
| Jeej | 37:e04613e021f2 | 470 | } |
| Jeej | 37:e04613e021f2 | 471 | else if (g_com_ctx.state == PARSE_BODY) |
| Jeej | 37:e04613e021f2 | 472 | { |
| Jeej | 37:e04613e021f2 | 473 | parse_packet_body(); |
| Jeej | 33:f9a542d3efaa | 474 | } |
| Jeej | 24:a8433b091764 | 475 | } |
| Jeej | 24:a8433b091764 | 476 | } |
| Jeej | 31:ab9bfdbc6b44 | 477 | |
| Jeej | 76:fda2e34ff19d | 478 | void d7a_com_tx_thread() |
| Jeej | 31:ab9bfdbc6b44 | 479 | { |
| Jeej | 58:38a366236bda | 480 | FPRINT("(id:0x%08x)\r\n", osThreadGetId()); |
| Jeej | 31:ab9bfdbc6b44 | 481 | |
| Jeej | 31:ab9bfdbc6b44 | 482 | d7a_com_tx_buf_t* msg; |
| Jeej | 31:ab9bfdbc6b44 | 483 | osEvent evt; |
| Jeej | 34:1311cc53201a | 484 | uint8_t flow_id; |
| Jeej | 34:1311cc53201a | 485 | |
| Jeej | 31:ab9bfdbc6b44 | 486 | while (true) |
| Jeej | 31:ab9bfdbc6b44 | 487 | { |
| Jeej | 31:ab9bfdbc6b44 | 488 | // wait for data to send |
| Jeej | 31:ab9bfdbc6b44 | 489 | evt = g_com_ctx.tx_queue.get(); |
| Jeej | 31:ab9bfdbc6b44 | 490 | msg = (evt.status == osEventMessage)? (d7a_com_tx_buf_t*)evt.value.p : NULL; |
| Jeej | 37:e04613e021f2 | 491 | |
| Jeej | 31:ab9bfdbc6b44 | 492 | |
| Jeej | 31:ab9bfdbc6b44 | 493 | // send message |
| Jeej | 31:ab9bfdbc6b44 | 494 | if (msg != NULL) |
| Jeej | 31:ab9bfdbc6b44 | 495 | { |
| Jeej | 34:1311cc53201a | 496 | flow_id = msg->buf[4]; |
| Jeej | 34:1311cc53201a | 497 | |
| Jeej | 45:b85384e7d825 | 498 | d7a_com_send(msg); |
| Jeej | 31:ab9bfdbc6b44 | 499 | FREE(msg); |
| Jeej | 34:1311cc53201a | 500 | |
| Jeej | 34:1311cc53201a | 501 | if (KAL_COM_FLOW_SYS_XACK == flow_id) |
| Jeej | 34:1311cc53201a | 502 | { |
| Jeej | 42:1578f0480dcb | 503 | DPRINT("XACK\r\n"); |
| Jeej | 34:1311cc53201a | 504 | g_com_ctx.tx_thread->signal_wait(XON_SIGNAL); |
| Jeej | 34:1311cc53201a | 505 | } |
| Jeej | 31:ab9bfdbc6b44 | 506 | } |
| Jeej | 31:ab9bfdbc6b44 | 507 | } |
| Jeej | 31:ab9bfdbc6b44 | 508 | } |
