Skip to content

Commit 8755881

Browse files
committed
Initial commit to add LZSS decompression at reboot
1 parent 0f502c7 commit 8755881

File tree

3 files changed

+304
-34
lines changed

3 files changed

+304
-34
lines changed

libraries/SBU/extras/SBUBoot/SBUBoot.ino

+67-34
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
#include <FlashStorage.h>
2020
#include <MKRNB.h>
2121

22+
#include "lzss.h"
23+
2224
#define SBU_START 0x2000
2325
#define SBU_SIZE 0x8000
2426

2527
#define SKETCH_START (uint32_t*)(SBU_START + SBU_SIZE)
2628

27-
static constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN";
28-
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
29+
const char * UPDATE_FILE_NAME = "UPDATE.BIN";
30+
const char * UPDATE_FILE_NAME_LZSS = "UPDATE.BIN.LZSS";
31+
static const char * CHECK_FILE_NAME = "UPDATE.OK";
2932

3033
FlashClass mcu_flash;
3134

32-
NBFileUtils fileUtils(true);
35+
NBFileUtils fileUtils(true);
3336

3437
extern "C" void __libc_init_array(void);
3538

@@ -49,41 +52,71 @@ int main()
4952
// Try to update only if update file
5053
// has been download successfully.
5154

52-
if (fileUtils.listFile(CHECK_FILE_NAME)) {
53-
uint32_t updateSize = fileUtils.listFile(UPDATE_FILE_NAME);
54-
uint32_t tot_bytes = 0;
55-
uint32_t read_bytes = 0;
56-
57-
if (updateSize > SBU_SIZE) {
58-
updateSize = updateSize - SBU_SIZE;
59-
size_t cycles = (updateSize / blockSize);
60-
size_t spare_bytes = (updateSize % blockSize);
61-
/* Erase the MCU flash */
62-
uint32_t flash_address = (uint32_t)SKETCH_START;
63-
mcu_flash.erase((void*)flash_address, updateSize);
64-
65-
for (auto i = 0; i < cycles; i++) {
66-
uint8_t block[blockSize] { 0 };
67-
digitalWrite(LED_BUILTIN, LOW);
68-
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, (i * blockSize) + SBU_SIZE, blockSize, block);
69-
digitalWrite(LED_BUILTIN, HIGH);
70-
mcu_flash.write((void*)flash_address, block, read_bytes);
71-
flash_address += read_bytes;
72-
tot_bytes += read_bytes;
73-
}
74-
75-
if (spare_bytes){
76-
uint8_t block[spare_bytes] { 0 };
77-
digitalWrite(LED_BUILTIN, LOW);
78-
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, tot_bytes + SBU_SIZE, spare_bytes, block);
79-
digitalWrite(LED_BUILTIN, HIGH);
80-
mcu_flash.write((void*)flash_address, block, read_bytes);
81-
flash_address += read_bytes;
82-
}
55+
if (fileUtils.existFile(CHECK_FILE_NAME))
56+
{
57+
/*This is for LZSS compressed binaries. */
58+
if (fileUtils.existFile(UPDATE_FILE_NAME_LZSS))
59+
{
60+
/* Erase the complete flash starting from the SSU forward
61+
* because we've got no possibility of knowing how large
62+
* the decompressed binary will finally be.
63+
*/
64+
mcu_flash.erase((void*)SKETCH_START, 0x40000 - (uint32_t)SKETCH_START);
65+
/* Initialize the lzss module with the data which
66+
* it requires.
67+
*/
68+
lzss_init((uint32_t)SKETCH_START);
69+
/* During the process of decoding UPDATE.BIN.LZSS
70+
* is decompressed and stored as UPDATE.BIN.
71+
*/
72+
lzss_decode();
73+
/* Write the data remaining in the write buffer to
74+
* the file.
75+
*/
76+
lzss_flush();
77+
/* Signal a successul update. */
8378
update_success = true;
8479
}
80+
/* This is for uncompressed binaries. */
81+
else if (fileUtils.listFile(UPDATE_FILE_NAME) > 0)
82+
{
83+
uint32_t updateSize = fileUtils.listFile(UPDATE_FILE_NAME);
84+
uint32_t tot_bytes = 0;
85+
uint32_t read_bytes = 0;
86+
87+
if (updateSize > SBU_SIZE) {
88+
updateSize = updateSize - SBU_SIZE;
89+
size_t cycles = (updateSize / blockSize) + 1;
90+
size_t spare_bytes = (updateSize % blockSize);
91+
92+
/* Erase the MCU flash */
93+
uint32_t flash_address = (uint32_t)SKETCH_START;
94+
mcu_flash.erase((void*)flash_address, updateSize);
95+
96+
for (auto i = 0; i < cycles; i++) {
97+
uint8_t block[blockSize] { 0 };
98+
digitalWrite(LED_BUILTIN, LOW);
99+
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, (i * blockSize) + SBU_SIZE, blockSize, block);
100+
digitalWrite(LED_BUILTIN, HIGH);
101+
mcu_flash.write((void*)flash_address, block, read_bytes);
102+
flash_address += read_bytes;
103+
tot_bytes += read_bytes;
104+
}
105+
106+
if (spare_bytes){
107+
uint8_t block[spare_bytes] { 0 };
108+
digitalWrite(LED_BUILTIN, LOW);
109+
read_bytes = fileUtils.readBlock(UPDATE_FILE_NAME, tot_bytes + SBU_SIZE, spare_bytes, block);
110+
digitalWrite(LED_BUILTIN, HIGH);
111+
mcu_flash.write((void*)flash_address, block, read_bytes);
112+
flash_address += read_bytes;
113+
}
114+
update_success = true;
115+
}
116+
}
85117
if (update_success) {
86118
fileUtils.deleteFile(UPDATE_FILE_NAME);
119+
fileUtils.deleteFile(UPDATE_FILE_NAME_LZSS);
87120
fileUtils.deleteFile(CHECK_FILE_NAME);
88121
}
89122
}

libraries/SBU/extras/SBUBoot/lzss.cpp

+219
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 <MKRNB.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 NBFileUtils 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 SBU 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 SBUBoot: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/SBU/extras/SBUBoot/lzss.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef SBU_LZSS_H_
2+
#define SBU_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 /* SBU_LZSS_H_ */

0 commit comments

Comments
 (0)