Dash7Board Code Upgrade Protocol demonstration code.

Dependencies:   modem_ref_helper CRC

Committer:
mikl_andre
Date:
Fri Oct 05 16:59:14 2018 +0000
Revision:
3:cfe26c2bb78b
Parent:
2:49acddddec25
Child:
4:c97df2bc1731
Updated to support repeated packets

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 0:5589104abba0 1 // @autor: jeremie@wizzilab.com
Jeej 0:5589104abba0 2 // @date: 2017-12-14
Jeej 0:5589104abba0 3
Jeej 0:5589104abba0 4 #include "modem_ref_helper.h"
Jeej 0:5589104abba0 5 #include "modem_callbacks.h"
Jeej 0:5589104abba0 6 #include "files.h"
Jeej 0:5589104abba0 7 #include "crc.h"
Jeej 0:5589104abba0 8
Jeej 0:5589104abba0 9 #define CHUNK_SIZE (128)
Jeej 0:5589104abba0 10
Jeej 0:5589104abba0 11 Semaphore modem_ready(0);
Jeej 0:5589104abba0 12 Queue<touch_t, 8> g_file_modified;
Jeej 0:5589104abba0 13
Jeej 0:5589104abba0 14 // CRC calculated on the incoming data stream
Jeej 0:5589104abba0 15 extern uint32_t stream_crc;
mikl_andre 3:cfe26c2bb78b 16 extern int32_t last_end;
Jeej 0:5589104abba0 17
Jeej 0:5589104abba0 18 const uint8_t default_root_key[] = {206, 87, 116, 11, 4, 30, 202, 254, 206, 87, 116, 11, 4, 30, 202, 254};
Jeej 0:5589104abba0 19
Jeej 0:5589104abba0 20 void print_resp(uint8_t id, int status)
Jeej 0:5589104abba0 21 {
Jeej 0:5589104abba0 22 switch (status)
Jeej 0:5589104abba0 23 {
Jeej 0:5589104abba0 24 case ALP_ERR_NONE:
Jeej 0:5589104abba0 25 //PRINT("Resp[%d]: OK\n", id);
Jeej 0:5589104abba0 26 break;
Jeej 0:5589104abba0 27 case ALP_ERR_FILE_EXIST:
Jeej 0:5589104abba0 28 PRINT("Resp[%d]: Already registered\n", id);
Jeej 0:5589104abba0 29 break;
Jeej 0:5589104abba0 30 default:
Jeej 0:5589104abba0 31 PRINT("Resp[%d]: error %d\n", id, status);
Jeej 0:5589104abba0 32 break;
Jeej 0:5589104abba0 33 }
Jeej 0:5589104abba0 34 }
Jeej 0:5589104abba0 35
Jeej 0:5589104abba0 36 modem_callbacks_t callbacks = {
Jeej 0:5589104abba0 37 .read = my_read,
Jeej 0:5589104abba0 38 .write = my_write,
Jeej 0:5589104abba0 39 .read_fprop = my_read_fprop,
Jeej 0:5589104abba0 40 .flush = my_flush,
Jeej 0:5589104abba0 41 .remove = my_delete,
Jeej 0:5589104abba0 42 .udata = my_udata,
Jeej 0:5589104abba0 43 .lqual = my_lqual,
Jeej 0:5589104abba0 44 .ldown = my_ldown,
Jeej 0:5589104abba0 45 .reset = my_reset,
Jeej 1:dd4e18b267a1 46 .boot = my_boot,
Jeej 1:dd4e18b267a1 47 .busy = my_busy
Jeej 0:5589104abba0 48 };
Jeej 0:5589104abba0 49
Jeej 0:5589104abba0 50 // Callback
Jeej 0:5589104abba0 51 void my_main_callback(uint8_t terminal, int8_t err, uint8_t id)
Jeej 0:5589104abba0 52 {
Jeej 0:5589104abba0 53 (void)id;
Jeej 0:5589104abba0 54
Jeej 0:5589104abba0 55 print_resp(id, err);
Jeej 0:5589104abba0 56
Jeej 0:5589104abba0 57 if (terminal)
Jeej 0:5589104abba0 58 {
Jeej 0:5589104abba0 59 modem_ready.release();
Jeej 0:5589104abba0 60 }
Jeej 0:5589104abba0 61 }
Jeej 0:5589104abba0 62
Jeej 0:5589104abba0 63 void thread_file_modified()
Jeej 0:5589104abba0 64 {
Jeej 0:5589104abba0 65 touch_t* touch;
Jeej 0:5589104abba0 66 osEvent evt;
Jeej 0:5589104abba0 67 Timer tim;
Jeej 0:5589104abba0 68 uint32_t total = 0;
Jeej 0:5589104abba0 69 uint32_t next_chunk = 0;
mikl_andre 3:cfe26c2bb78b 70 uint32_t chunks=0;
Jeej 0:5589104abba0 71
Jeej 0:5589104abba0 72 uint8_t id = modem_get_id(my_main_callback);
Jeej 0:5589104abba0 73
Jeej 0:5589104abba0 74 PRINT("Ready\n");
Jeej 0:5589104abba0 75
Jeej 0:5589104abba0 76 while (true)
Jeej 0:5589104abba0 77 {
Jeej 0:5589104abba0 78 evt = g_file_modified.get();
Jeej 0:5589104abba0 79 touch = (evt.status == osEventMessage)? (touch_t*)evt.value.p : NULL;
Jeej 0:5589104abba0 80 ASSERT(touch != NULL, "NULL touch pointer!\n");
Jeej 0:5589104abba0 81
Jeej 0:5589104abba0 82 switch (touch->fid)
Jeej 0:5589104abba0 83 {
Jeej 0:5589104abba0 84 case FID_APP_CUP_CFG:
Jeej 0:5589104abba0 85 cup_cfg_t cup_cfg;
Jeej 0:5589104abba0 86
Jeej 0:5589104abba0 87 ram_fs_read(FID_APP_CUP_CFG, 0, sizeof(cup_cfg_t), (uint8_t*)&cup_cfg);
Jeej 0:5589104abba0 88
Jeej 0:5589104abba0 89 if (CUP_CMD_UPGRADE_FILE_START == cup_cfg.cmd)
Jeej 0:5589104abba0 90 {
Jeej 0:5589104abba0 91 PRINT("Enter upload mode. Watchdog %ds\n", cup_cfg.arch_nb);
Jeej 0:5589104abba0 92
Jeej 2:49acddddec25 93 tim.stop();
Jeej 0:5589104abba0 94 tim.reset();
Jeej 0:5589104abba0 95 total = 0;
Jeej 0:5589104abba0 96 next_chunk = 0;
Jeej 0:5589104abba0 97 stream_crc = 0;
mikl_andre 3:cfe26c2bb78b 98 chunks=0;
Jeej 0:5589104abba0 99
Jeej 0:5589104abba0 100 // Write to the modem CUP config file (as root)
Jeej 0:5589104abba0 101 // to enter upload mode
Jeej 0:5589104abba0 102 cup_cfg.cmd = CUP_CMD_UPGRADE_UPLOAD;
Jeej 0:5589104abba0 103 modem_write_file_root(FID_CUP_CFG, (uint8_t*)&cup_cfg, 0, 4, (uint8_t*)default_root_key, id);
Jeej 0:5589104abba0 104 modem_ready.wait();
Jeej 0:5589104abba0 105 }
Jeej 0:5589104abba0 106 else if (CUP_CMD_UPGRADE_FILE_END == cup_cfg.cmd)
Jeej 0:5589104abba0 107 {
Jeej 0:5589104abba0 108 float time_s = tim.read();
Jeej 0:5589104abba0 109 uint32_t expected_size = cup_cfg.src_offset;
Jeej 0:5589104abba0 110 uint32_t expected_crc = cup_cfg.signature;
mikl_andre 3:cfe26c2bb78b 111
mikl_andre 3:cfe26c2bb78b 112 PRINT("\nDone. %d/%d bytes received in %d chunks in %.2f sec (%.2f kb/s)\r\n"
Jeej 0:5589104abba0 113 "Expected CRC 0x%08X. Stream CRC 0x%08X.\r\n",
mikl_andre 3:cfe26c2bb78b 114 total, expected_size, chunks, time_s, (double)(total/time_s)/1024.0,
Jeej 0:5589104abba0 115 expected_crc, stream_crc);
Jeej 0:5589104abba0 116
Jeej 0:5589104abba0 117 tim.stop();
Jeej 0:5589104abba0 118
Jeej 0:5589104abba0 119 // Compare expected crc with received data crc
Jeej 0:5589104abba0 120 if (stream_crc == expected_crc)
Jeej 0:5589104abba0 121 {
Jeej 0:5589104abba0 122 PRINT("Received complete binary.\n");
Jeej 0:5589104abba0 123 }
Jeej 0:5589104abba0 124 else
Jeej 0:5589104abba0 125 {
Jeej 0:5589104abba0 126 PRINT("Missed or corrupted data in this session.\n");
Jeej 0:5589104abba0 127 }
Jeej 0:5589104abba0 128
Jeej 0:5589104abba0 129
Jeej 0:5589104abba0 130 // Actual check is done here since we could have received some of the missed data in a previous session.
Jeej 0:5589104abba0 131
Jeej 0:5589104abba0 132 /******************************/
Jeej 0:5589104abba0 133 /* Compute CRC on saved data. */
Jeej 0:5589104abba0 134 /******************************/
Jeej 0:5589104abba0 135
Jeej 0:5589104abba0 136 // If you have the full binary data,
Jeej 0:5589104abba0 137 // You can use this function to compute CRC
Jeej 0:5589104abba0 138 //binary_crc = crc32((char*)binary_data, expected_size);
Jeej 0:5589104abba0 139
Jeej 0:5589104abba0 140 // Else just do a loop and a fast CRC on data chunks like in my_write
Jeej 0:5589104abba0 141 }
Jeej 0:5589104abba0 142 else
Jeej 0:5589104abba0 143 {
Jeej 0:5589104abba0 144 PRINT("CUP command 0x%04X\n", cup_cfg.cmd);
Jeej 0:5589104abba0 145 }
Jeej 0:5589104abba0 146
Jeej 0:5589104abba0 147 break;
Jeej 0:5589104abba0 148 case FID_APP_CUP_CODE:
Jeej 0:5589104abba0 149 // Chunk data should be saved in my_write callback
mikl_andre 3:cfe26c2bb78b 150 //PRINT("Got CUP code chunk length %d offset %d\n", touch->length, touch->offset);
mikl_andre 3:cfe26c2bb78b 151 chunks++;
Jeej 0:5589104abba0 152
Jeej 2:49acddddec25 153 if (!next_chunk)
Jeej 2:49acddddec25 154 {
Jeej 2:49acddddec25 155 // First chunk, start timer
Jeej 2:49acddddec25 156 tim.start();
mikl_andre 3:cfe26c2bb78b 157 PRINT("Receiving CUP code chunks-> ");
Jeej 2:49acddddec25 158 }
Jeej 2:49acddddec25 159
Jeej 0:5589104abba0 160
mikl_andre 3:cfe26c2bb78b 161 if (next_chunk < touch->offset)
mikl_andre 3:cfe26c2bb78b 162 {
mikl_andre 3:cfe26c2bb78b 163 PRINT("\nMissed %d chunk(s) at offset %d (got offset %d)\n", (touch->offset - next_chunk) / CHUNK_SIZE, next_chunk, touch->offset);
mikl_andre 3:cfe26c2bb78b 164 next_chunk = touch->offset + touch->length;
mikl_andre 3:cfe26c2bb78b 165 total += touch->length;
mikl_andre 3:cfe26c2bb78b 166 }
mikl_andre 3:cfe26c2bb78b 167 else if (next_chunk == touch->offset)
Jeej 0:5589104abba0 168 {
mikl_andre 3:cfe26c2bb78b 169 next_chunk = touch->offset + touch->length;
mikl_andre 3:cfe26c2bb78b 170 total += touch->length;
mikl_andre 3:cfe26c2bb78b 171 PRINT(".");
Jeej 0:5589104abba0 172 }
mikl_andre 3:cfe26c2bb78b 173 else
mikl_andre 3:cfe26c2bb78b 174 {
mikl_andre 3:cfe26c2bb78b 175 //PRINT("Repeat chunk(s) at offset %d\n", touch->offset);
mikl_andre 3:cfe26c2bb78b 176 }
Jeej 0:5589104abba0 177
Jeej 0:5589104abba0 178 // Notify modem code file to reset upload watchdog
Jeej 0:5589104abba0 179 // else the device will exit upload mode after the watchdog timeout
Jeej 0:5589104abba0 180 modem_notify_file(FID_CUP_CODE, 0, 1, id);
Jeej 0:5589104abba0 181 modem_ready.wait();
Jeej 0:5589104abba0 182
Jeej 0:5589104abba0 183 break;
Jeej 0:5589104abba0 184 default:
Jeej 0:5589104abba0 185 PRINT("TOUCH FID %d OFF %d LEN %d\n", touch->fid, touch->offset, touch->length);
Jeej 0:5589104abba0 186 break;
Jeej 0:5589104abba0 187 }
Jeej 0:5589104abba0 188
Jeej 0:5589104abba0 189 FREE(touch);
Jeej 0:5589104abba0 190 }
Jeej 0:5589104abba0 191 }
Jeej 0:5589104abba0 192
Jeej 0:5589104abba0 193 /*** Main function ------------------------------------------------------------- ***/
Jeej 0:5589104abba0 194 int main() {
Jeej 0:5589104abba0 195 // Start & initialize
Jeej 0:5589104abba0 196 #ifdef DEBUG_LED
Jeej 0:5589104abba0 197 DBG_OPEN(DEBUG_LED);
Jeej 0:5589104abba0 198 #else
Jeej 0:5589104abba0 199 DBG_OPEN(NC);
Jeej 0:5589104abba0 200 #endif
Jeej 0:5589104abba0 201 PRINT("\n"
Jeej 0:5589104abba0 202 "-----------------------------------------\n"
Jeej 0:5589104abba0 203 "---------------- Demo CUP ---------------\n"
Jeej 0:5589104abba0 204 "-----------------------------------------\n");
Jeej 0:5589104abba0 205
Jeej 0:5589104abba0 206 modem_helper_open(&callbacks);
Jeej 0:5589104abba0 207
Jeej 0:5589104abba0 208 PRINT("--------------- APP infos ---------------\r\n");
Jeej 0:5589104abba0 209 PRINT(" - Manufacturer ID: %08X\r\n", f_rev.manufacturer_id);
Jeej 0:5589104abba0 210 PRINT(" - Device ID: %08X\r\n", f_rev.device_id);
Jeej 0:5589104abba0 211 PRINT(" - Hardware version: %08X\r\n", f_rev.hw_version);
Jeej 0:5589104abba0 212 PRINT(" - Firmware version: v%d.%d.%d [%02X]\r\n", f_rev.fw_version.major, f_rev.fw_version.minor, f_rev.fw_version.patch, f_rev.fw_version.id);
Jeej 0:5589104abba0 213 PRINT(" - CUP max size: %d\r\n", f_rev.cup_max_size);
Jeej 0:5589104abba0 214 PRINT("-----------------------------------------\r\n");
Jeej 0:5589104abba0 215
Jeej 0:5589104abba0 216 uint8_t id = modem_get_id(my_main_callback);
Jeej 0:5589104abba0 217
Jeej 0:5589104abba0 218 PRINT("Register Files\n");
Jeej 0:5589104abba0 219 modem_update_file(FID_HOST_REV, (alp_file_header_t*)&h_rev, (uint8_t*)&f_rev);
Jeej 0:5589104abba0 220 modem_update_file(FID_APP_CUP_CFG, (alp_file_header_t*)&h_cup_cfg, (uint8_t*)&f_cup_cfg);
Jeej 0:5589104abba0 221
Jeej 0:5589104abba0 222 // Declare the cup code file
Jeej 0:5589104abba0 223 // It needs a special handling of its data in my_write callback since we want to keep them.
Jeej 0:5589104abba0 224 // (can't be done with the current RAM file system)
Jeej 0:5589104abba0 225 modem_declare_file(FID_APP_CUP_CODE, (alp_file_header_t*)&h_cup_code, true, id);
Jeej 0:5589104abba0 226 modem_ready.wait();
Jeej 0:5589104abba0 227
Jeej 1:dd4e18b267a1 228 PRINT("Setup URCs\n");
Jeej 1:dd4e18b267a1 229 // Busy URC to know if modem enters CUP mode
Jeej 1:dd4e18b267a1 230 modem_enable_urc(ALP_URC_TYPE_BUSY, 0, 0, true, id);
Jeej 1:dd4e18b267a1 231 modem_ready.wait();
Jeej 1:dd4e18b267a1 232
Jeej 0:5589104abba0 233 PRINT("Start D7A Stack\n");
Jeej 0:5589104abba0 234 //modem_activate_itf(ALP_ITF_TYPE_D7A, 24, 0, ALP_D7A_ISTAT_RESP | ALP_D7A_ISTAT_UNS, true, id);
Jeej 0:5589104abba0 235 modem_activate_itf(ALP_ITF_TYPE_D7A, 24, 0, 0, true, id);
Jeej 0:5589104abba0 236 modem_ready.wait();
Jeej 0:5589104abba0 237
Jeej 0:5589104abba0 238 PRINT("Notify Modem Version\n");
Jeej 0:5589104abba0 239 modem_notify_file(D7A_FID_FIRMWARE_VERSION, 0, SIZE_HOST_REV, id);
Jeej 0:5589104abba0 240 modem_ready.wait();
Jeej 0:5589104abba0 241
Jeej 0:5589104abba0 242 PRINT("Notify Host Version\n");
Jeej 0:5589104abba0 243 modem_notify_file(FID_HOST_REV, 0, SIZE_HOST_REV, id);
Jeej 0:5589104abba0 244 modem_ready.wait();
Jeej 0:5589104abba0 245
Jeej 0:5589104abba0 246 // id no longer needed
Jeej 0:5589104abba0 247 modem_free_id(id);
Jeej 0:5589104abba0 248
Jeej 0:5589104abba0 249 // Start file modified thread
Jeej 0:5589104abba0 250 Thread th_file_modified(osPriorityNormal, 1024, NULL);
Jeej 0:5589104abba0 251 osStatus status = th_file_modified.start(thread_file_modified);
Jeej 0:5589104abba0 252 ASSERT(status == osOK, "Failed to start thread_file_modified (err: %d)\r\n", status);
Jeej 0:5589104abba0 253
Jeej 0:5589104abba0 254 #ifdef DEBUG_LED
Jeej 0:5589104abba0 255 DigitalOut my_led(DEBUG_LED);
Jeej 0:5589104abba0 256 #endif
Jeej 0:5589104abba0 257
Jeej 0:5589104abba0 258 // Set main task to lowest priority
Jeej 0:5589104abba0 259 osThreadSetPriority(osThreadGetId(), osPriorityIdle);
Jeej 0:5589104abba0 260 while(true)
Jeej 0:5589104abba0 261 {
Jeej 0:5589104abba0 262 Thread::wait(500);
Jeej 0:5589104abba0 263 #ifdef DEBUG_LED
Jeej 0:5589104abba0 264 my_led = !my_led;
Jeej 0:5589104abba0 265 #endif
Jeej 0:5589104abba0 266 }
Jeej 0:5589104abba0 267 }