Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6bff0b2

Browse filesBrowse files
authored
Merge pull request #544 from arduino/ssu-lzss
Add feature for decompressing LZSS compressed binary files by second stage bootloader SSU
2 parents 761e1e6 + 807f450 commit 6bff0b2
Copy full SHA for 6bff0b2

File tree

4 files changed

+2537
-2205
lines changed
Filter options

4 files changed

+2537
-2205
lines changed

‎libraries/SSU/extras/SSUBoot/SSUBoot.ino

Copy file name to clipboardExpand all lines: libraries/SSU/extras/SSUBoot/SSUBoot.ino
+54-24Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <FlashStorage.h>
2424
#include <MKRGSM.h>
2525

26+
#include "lzss.h"
2627

2728
/**************************************************************************************
2829
DEFINE
@@ -37,17 +38,16 @@
3738
GLOBAL CONSTANTS
3839
**************************************************************************************/
3940

40-
static constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN";
41-
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
42-
41+
const char * UPDATE_FILE_NAME = "UPDATE.BIN";
42+
const char * UPDATE_FILE_NAME_LZSS = "UPDATE.BIN.LZSS";
43+
static const char * CHECK_FILE_NAME = "UPDATE.OK";
4344

4445
/**************************************************************************************
4546
GLOBAL VARIABLES
4647
**************************************************************************************/
4748

4849
FlashClass mcu_flash;
49-
50-
GSMFileUtils fileUtils;
50+
GSMFileUtils fileUtils;
5151

5252
/**************************************************************************************
5353
FUNCTION DECLARATION
@@ -75,29 +75,59 @@ int main()
7575

7676
// Try to update only if update file
7777
// has been download successfully.
78-
if (fileUtils.listFile(CHECK_FILE_NAME) == 1) {
79-
uint32_t size = fileUtils.listFile(UPDATE_FILE_NAME);
80-
size_t cycles = (size / blockSize) + 1;
81-
82-
if (size > SSU_SIZE) {
83-
size -= SSU_SIZE;
84-
85-
/* Erase the MCU flash */
86-
uint32_t flash_address = (uint32_t)SKETCH_START;
87-
mcu_flash.erase((void*)flash_address, size);
88-
89-
for (auto i = 0; i < cycles; i++) {
90-
uint8_t block[blockSize] { 0 };
91-
digitalWrite(LED_BUILTIN, LOW);
92-
uint32_t read = fileUtils.readBlock(UPDATE_FILE_NAME, (i * blockSize) + SSU_SIZE, blockSize, block);
93-
digitalWrite(LED_BUILTIN, HIGH);
94-
mcu_flash.write((void*)flash_address, block, read);
95-
flash_address += read;
96-
}
78+
if (fileUtils.listFile(CHECK_FILE_NAME) > 0)
79+
{
80+
/* This is for LZSS compressed binaries. */
81+
if (fileUtils.listFile(UPDATE_FILE_NAME_LZSS) > 0)
82+
{
83+
/* Erase the complete flash starting from the SSU forward
84+
* because we've got no possibility of knowing how large
85+
* the decompressed binary will finally be.
86+
*/
87+
mcu_flash.erase((void*)SKETCH_START, 0x40000 - (uint32_t)SKETCH_START);
88+
/* Initialize the lzss module with the data which
89+
* it requires.
90+
*/
91+
lzss_init((uint32_t)SKETCH_START);
92+
/* During the process of decoding UPDATE.BIN.LZSS
93+
* is decompressed and stored as UPDATE.BIN.
94+
*/
95+
lzss_decode();
96+
/* Write the data remaining in the write buffer to
97+
* the file.
98+
*/
99+
lzss_flush();
100+
/* Signal a successul update. */
97101
update_success = true;
98102
}
103+
/* This is for uncompressed binaries. */
104+
else if (fileUtils.listFile(UPDATE_FILE_NAME) > 0)
105+
{
106+
uint32_t size = fileUtils.listFile(UPDATE_FILE_NAME);
107+
size_t cycles = (size / blockSize) + 1;
108+
109+
if (size > SSU_SIZE) {
110+
size -= SSU_SIZE;
111+
112+
/* Erase the MCU flash */
113+
uint32_t flash_address = (uint32_t)SKETCH_START;
114+
mcu_flash.erase((void*)flash_address, size);
115+
116+
for (auto i = 0; i < cycles; i++) {
117+
uint8_t block[blockSize] { 0 };
118+
digitalWrite(LED_BUILTIN, LOW);
119+
uint32_t read = fileUtils.readBlock(UPDATE_FILE_NAME, (i * blockSize) + SSU_SIZE, blockSize, block);
120+
digitalWrite(LED_BUILTIN, HIGH);
121+
mcu_flash.write((void*)flash_address, block, read);
122+
flash_address += read;
123+
}
124+
update_success = true;
125+
}
126+
}
127+
/* Clean up in case of success */
99128
if (update_success) {
100129
fileUtils.deleteFile(UPDATE_FILE_NAME);
130+
fileUtils.deleteFile(UPDATE_FILE_NAME_LZSS);
101131
fileUtils.deleteFile(CHECK_FILE_NAME);
102132
}
103133
}

‎libraries/SSU/extras/SSUBoot/lzss.cpp

Copy file name to clipboard
+219Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/**************************************************************************************
2+
INCLUDE
3+
**************************************************************************************/
4+
5+
#include "lzss.h"
6+
7+
#include <stdlib.h>
8+
#include <stdint.h>
9+
10+
#include <MKRGSM.h>
11+
#include <FlashStorage.h>
12+
13+
/**************************************************************************************
14+
DEFINE
15+
**************************************************************************************/
16+
17+
#define EI 11 /* typically 10..13 */
18+
#define EJ 4 /* typically 4..5 */
19+
#define P 1 /* If match length <= P then output one character */
20+
#define N (1 << EI) /* buffer size */
21+
#define F ((1 << EJ) + 1) /* lookahead buffer size */
22+
23+
#define LZSS_EOF (-1)
24+
25+
#define FPUTC_BUF_SIZE (512)
26+
#define FGETC_BUF_SIZE (512)
27+
28+
/**************************************************************************************
29+
GLOBAL VARIABLES
30+
**************************************************************************************/
31+
32+
extern GSMFileUtils fileUtils;
33+
extern FlashClass mcu_flash;
34+
extern const char * UPDATE_FILE_NAME_LZSS;
35+
36+
static uint32_t SKETCH_START = 0;
37+
static uint32_t LZSS_FILE_SIZE = 0;
38+
39+
int bit_buffer = 0, bit_mask = 128;
40+
unsigned char buffer[N * 2];
41+
42+
static char write_buf[FPUTC_BUF_SIZE];
43+
static size_t write_buf_num_bytes = 0;
44+
static size_t bytes_written_fputc = 0;
45+
static size_t bytes_written_flash = 0;
46+
static uint32_t flash_addr = 0;
47+
48+
/**************************************************************************************
49+
PUBLIC FUNCTIONS
50+
**************************************************************************************/
51+
52+
void lzss_init(uint32_t const sketch_start)
53+
{
54+
SKETCH_START = sketch_start;
55+
flash_addr = sketch_start;
56+
LZSS_FILE_SIZE = fileUtils.listFile(UPDATE_FILE_NAME_LZSS);
57+
}
58+
59+
void lzss_flush()
60+
{
61+
bytes_written_fputc += write_buf_num_bytes;
62+
63+
/* Only write to the flash once we've surpassed
64+
* the SSU in the update binary.
65+
*/
66+
if (bytes_written_fputc > (SKETCH_START - 0x2000))
67+
{
68+
mcu_flash.write((void*)flash_addr, write_buf, write_buf_num_bytes);
69+
flash_addr += write_buf_num_bytes;
70+
}
71+
72+
write_buf_num_bytes = 0;
73+
}
74+
75+
/**************************************************************************************
76+
PRIVATE FUNCTIONS
77+
**************************************************************************************/
78+
79+
void lzss_fputc(int const c)
80+
{
81+
/* Buffer the decompressed data into a buffer so
82+
* we can perform block writes and don't need to
83+
* write every byte singly on the flash (which
84+
* wouldn't be possible anyway).
85+
*/
86+
write_buf[write_buf_num_bytes] = static_cast<char>(c);
87+
write_buf_num_bytes++;
88+
89+
/* The write buffer is full of decompressed
90+
* data, write it to the flash now.
91+
*/
92+
if (write_buf_num_bytes == FPUTC_BUF_SIZE)
93+
lzss_flush();
94+
}
95+
96+
int lzss_fgetc()
97+
{
98+
static uint8_t read_buf[FGETC_BUF_SIZE];
99+
static size_t read_buf_pos = FGETC_BUF_SIZE;
100+
static size_t bytes_read_fgetc = 0;
101+
static size_t bytes_read_from_modem = 0;
102+
103+
/* lzss_file_size is set within SSUBoot:main
104+
* and contains the size of the LZSS file. Once
105+
* all those bytes have been read its time to return
106+
* LZSS_EOF in order to signal that the end of
107+
* the file has been reached.
108+
*/
109+
if (bytes_read_fgetc == LZSS_FILE_SIZE)
110+
return LZSS_EOF;
111+
112+
/* If there is no data left to be read from the read buffer
113+
* than read a new block and store it into the read buffer.
114+
*/
115+
if (read_buf_pos == FGETC_BUF_SIZE)
116+
{
117+
/* Read the next block from the flash memory. */
118+
bytes_read_from_modem += fileUtils.readBlock(UPDATE_FILE_NAME_LZSS, bytes_read_from_modem, FGETC_BUF_SIZE, read_buf);
119+
/* Reset the read buffer position. */
120+
read_buf_pos = 0;
121+
}
122+
123+
uint8_t const c = read_buf[read_buf_pos];
124+
read_buf_pos++;
125+
bytes_read_fgetc++;
126+
127+
return c;
128+
}
129+
130+
/**************************************************************************************
131+
LZSS FUNCTIONS
132+
**************************************************************************************/
133+
134+
void putbit1(void)
135+
{
136+
bit_buffer |= bit_mask;
137+
if ((bit_mask >>= 1) == 0) {
138+
lzss_fputc(bit_buffer);
139+
bit_buffer = 0; bit_mask = 128;
140+
}
141+
}
142+
143+
void putbit0(void)
144+
{
145+
if ((bit_mask >>= 1) == 0) {
146+
lzss_fputc(bit_buffer);
147+
bit_buffer = 0; bit_mask = 128;
148+
}
149+
}
150+
151+
void output1(int c)
152+
{
153+
int mask;
154+
155+
putbit1();
156+
mask = 256;
157+
while (mask >>= 1) {
158+
if (c & mask) putbit1();
159+
else putbit0();
160+
}
161+
}
162+
163+
void output2(int x, int y)
164+
{
165+
int mask;
166+
167+
putbit0();
168+
mask = N;
169+
while (mask >>= 1) {
170+
if (x & mask) putbit1();
171+
else putbit0();
172+
}
173+
mask = (1 << EJ);
174+
while (mask >>= 1) {
175+
if (y & mask) putbit1();
176+
else putbit0();
177+
}
178+
}
179+
180+
int getbit(int n) /* get n bits */
181+
{
182+
int i, x;
183+
static int buf, mask = 0;
184+
185+
x = 0;
186+
for (i = 0; i < n; i++) {
187+
if (mask == 0) {
188+
if ((buf = lzss_fgetc()) == LZSS_EOF) return LZSS_EOF;
189+
mask = 128;
190+
}
191+
x <<= 1;
192+
if (buf & mask) x++;
193+
mask >>= 1;
194+
}
195+
return x;
196+
}
197+
198+
void lzss_decode(void)
199+
{
200+
int i, j, k, r, c;
201+
202+
for (i = 0; i < N - F; i++) buffer[i] = ' ';
203+
r = N - F;
204+
while ((c = getbit(1)) != LZSS_EOF) {
205+
if (c) {
206+
if ((c = getbit(8)) == LZSS_EOF) break;
207+
lzss_fputc(c);
208+
buffer[r++] = c; r &= (N - 1);
209+
} else {
210+
if ((i = getbit(EI)) == LZSS_EOF) break;
211+
if ((j = getbit(EJ)) == LZSS_EOF) break;
212+
for (k = 0; k <= j + 1; k++) {
213+
c = buffer[(i + k) & (N - 1)];
214+
lzss_fputc(c);
215+
buffer[r++] = c; r &= (N - 1);
216+
}
217+
}
218+
}
219+
}

‎libraries/SSU/extras/SSUBoot/lzss.h

Copy file name to clipboard
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef SSU_LZSS_H_
2+
#define SSU_LZSS_H_
3+
4+
/**************************************************************************************
5+
INCLUDE
6+
**************************************************************************************/
7+
8+
#include <stdint.h>
9+
10+
/**************************************************************************************
11+
FUNCTION DEFINITION
12+
**************************************************************************************/
13+
14+
void lzss_init(uint32_t const sketch_start);
15+
void lzss_decode();
16+
void lzss_flush();
17+
18+
#endif /* SSU_LZSS_H_ */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.