14
14
15
15
#include "spi_mem.h"
16
16
#include "bitbox02_pins.h"
17
+ #include "random.h"
18
+ #include "screen.h"
17
19
#include "util.h"
18
20
#include <hal_delay.h>
19
21
#include <spi_lite.h>
24
26
#define SECTOR_MASK 0xFFFFF000
25
27
#define MEMORY_LIMIT (SPI_MEM_MEMORY_SIZE - 1)
26
28
#define SR_WIP 0x01
29
+ #define SR_PROTECT_BITS_MASK 0x3C
30
+ #define SR_PROTECT_BITS_SHIFT 2
31
+ #define SR_PROTECT_BITS (SPI_MEM_PROTECTED_BLOCKS << SR_PROTECT_BITS_SHIFT)
32
+ #define CR1_TB_BIT_BOTTOM 0x8
33
+ #define CR1_TB_BIT_MASK 0x8
27
34
#define CMD_READ 0x03
28
35
#define CMD_WREN 0x06
36
+ #define CMD_WRSR 0x01
29
37
#define CMD_SE 0x20
30
38
#define CMD_PP 0x02
31
39
#define CMD_RDSR 0x05
40
+ #define CMD_RDCR 0x15
32
41
#define CMD_CE 0x60
33
42
43
+ // Drives the chip select pin low
34
44
static void _spi_mem_cs_low (void )
35
45
{
36
46
gpio_set_pin_level (PIN_MEM_CS , 0 );
37
47
}
38
48
49
+ // Drives the chip select pin high
39
50
static void _spi_mem_cs_high (void )
40
51
{
41
52
gpio_set_pin_level (PIN_MEM_CS , 1 );
42
53
}
43
54
55
+ // Reads the status register
44
56
static uint8_t _spi_mem_read_sr (void )
45
57
{
46
58
uint8_t buffer [2 ] = {0 };
@@ -51,19 +63,19 @@ static uint8_t _spi_mem_read_sr(void)
51
63
return buffer [1 ];
52
64
}
53
65
54
- static void _spi_mem_read (uint32_t address , size_t size , uint8_t * buffer )
66
+ // Reads the configuration register
67
+ static void _spi_mem_read_cr (uint8_t * data_out )
55
68
{
56
- buffer [0 ] = CMD_READ ;
57
- buffer [1 ] = (address >> 16 ) & 0xFF ;
58
- buffer [2 ] = (address >> 8 ) & 0xFF ;
59
- buffer [3 ] = address & 0xFF ;
60
- memset (& buffer [4 ], 0x00 , size );
61
-
69
+ uint8_t buffer [3 ] = {0 };
70
+ buffer [0 ] = CMD_RDCR ;
62
71
_spi_mem_cs_low ();
63
- SPI_MEM_exchange_block (buffer , size + 4 );
72
+ SPI_MEM_exchange_block (buffer , 3 );
64
73
_spi_mem_cs_high ();
74
+
75
+ memcpy (data_out , & buffer [1 ], 2 );
65
76
}
66
77
78
+ // Waits until the WIP bits goes low
67
79
static void _spi_mem_wait (void )
68
80
{
69
81
uint8_t status ;
@@ -72,23 +84,67 @@ static void _spi_mem_wait(void)
72
84
} while (status & SR_WIP );
73
85
}
74
86
75
- void spi_mem_full_erase (void )
87
+ // Set write enable bit
88
+ static void _spi_mem_write_enable (void )
76
89
{
77
- uint8_t buffer [2 ];
90
+ uint8_t cmd = CMD_WREN ;
91
+ _spi_mem_cs_low ();
92
+ SPI_MEM_exchange_block (& cmd , 1 );
93
+ _spi_mem_cs_high ();
94
+ }
95
+
96
+ // Verify if the given address is protected
97
+ static bool _spi_mem_verify_address_protected (uint32_t address )
98
+ {
99
+ uint8_t protected_blocks = (_spi_mem_read_sr () & SR_PROTECT_BITS_MASK ) >> SR_PROTECT_BITS_SHIFT ;
100
+ if (address < (protected_blocks * SPI_MEM_BLOCK_SIZE )) {
101
+ return true;
102
+ }
103
+ return false;
104
+ }
78
105
79
- // --- Enable Write ---
80
- buffer [0 ] = CMD_WREN ;
106
+ // Write the status and configuration registers
107
+ static void _spi_mem_write_sr (uint8_t * data_in )
108
+ {
109
+ _spi_mem_write_enable ();
110
+ uint8_t buffer [4 ] = {0 };
111
+ buffer [0 ] = CMD_WRSR ;
112
+ memcpy (& buffer [1 ], data_in , 3 );
81
113
_spi_mem_cs_low ();
82
- SPI_MEM_exchange_block (buffer , 1 );
114
+ SPI_MEM_exchange_block (buffer , 4 );
83
115
_spi_mem_cs_high ();
116
+ _spi_mem_wait ();
117
+ }
84
118
85
- // --- Chip Erase ---
86
- buffer [0 ] = CMD_CE ;
119
+ // Reads `size` bytes starting from `address` and writes the data into `buffer`
120
+ static void _spi_mem_read (uint32_t address , size_t size , uint8_t * buffer )
121
+ {
122
+ buffer [0 ] = CMD_READ ;
123
+ buffer [1 ] = (address >> 16 ) & 0xFF ;
124
+ buffer [2 ] = (address >> 8 ) & 0xFF ;
125
+ buffer [3 ] = address & 0xFF ;
126
+ memset (& buffer [4 ], 0x00 , size );
127
+
128
+ _spi_mem_cs_low ();
129
+ SPI_MEM_exchange_block (buffer , size + 4 );
130
+ _spi_mem_cs_high ();
131
+ }
132
+
133
+ bool spi_mem_full_erase (void )
134
+ {
135
+ if (_spi_mem_read_sr () & SR_PROTECT_BITS_MASK ) {
136
+ util_log ("Cannot erase with protected area locked." );
137
+ return false;
138
+ }
139
+ _spi_mem_write_enable ();
140
+
141
+ uint8_t cmd = CMD_CE ;
87
142
_spi_mem_cs_low ();
88
- SPI_MEM_exchange_block (buffer , 1 );
143
+ SPI_MEM_exchange_block (& cmd , 1 );
89
144
_spi_mem_cs_high ();
90
145
91
146
_spi_mem_wait ();
147
+ return true;
92
148
}
93
149
94
150
bool spi_mem_sector_erase (uint32_t sector_addr )
@@ -97,15 +153,15 @@ bool spi_mem_sector_erase(uint32_t sector_addr)
97
153
util_log ("Invalid sector address %p" , (void * )(uintptr_t )sector_addr );
98
154
return false;
99
155
}
156
+ if (_spi_mem_verify_address_protected (sector_addr )) {
157
+ util_log ("Sector address %p protected" , (void * )(uintptr_t )sector_addr );
158
+ return false;
159
+ }
100
160
101
- uint8_t buffer [SPI_MEM_PAGE_SIZE + 4 ];
102
- // --- Enable Write ---
103
- buffer [0 ] = CMD_WREN ;
104
- _spi_mem_cs_low ();
105
- SPI_MEM_exchange_block (buffer , 1 );
106
- _spi_mem_cs_high ();
161
+ _spi_mem_write_enable ();
107
162
108
163
// --- Sector Erase (write 4 bytes) ---
164
+ uint8_t buffer [SPI_MEM_PAGE_SIZE + 4 ];
109
165
buffer [0 ] = CMD_SE ;
110
166
buffer [1 ] = (sector_addr >> 16 ) & 0xFF ;
111
167
buffer [2 ] = (sector_addr >> 8 ) & 0xFF ;
@@ -118,6 +174,21 @@ bool spi_mem_sector_erase(uint32_t sector_addr)
118
174
// --- Wait for write to end ---
119
175
_spi_mem_wait ();
120
176
177
+ // --- Check that sector has been actually erased ---
178
+ uint8_t page_data [SPI_MEM_PAGE_SIZE ];
179
+ for (size_t i = 0 ; i < SPI_MEM_SECTOR_SIZE / SPI_MEM_PAGE_SIZE ; i ++ ) {
180
+ uint32_t page_addr = sector_addr + i * SPI_MEM_PAGE_SIZE ;
181
+ if (!spi_mem_page_read (page_addr , page_data )) {
182
+ util_log ("Read after sector erase at %p failed" , (void * )(uintptr_t )page_addr );
183
+ return false;
184
+ }
185
+ for (size_t j = 0 ; j < SPI_MEM_PAGE_SIZE ; j ++ ) {
186
+ if (page_data [j ] != 0xFF ) {
187
+ util_log ("Sector erase at %p failed" , (void * )(uintptr_t )(page_addr + j ));
188
+ return false;
189
+ }
190
+ }
191
+ }
121
192
return true;
122
193
}
123
194
@@ -156,21 +227,23 @@ uint8_t* spi_mem_read(uint32_t address, size_t size)
156
227
return buffer ;
157
228
}
158
229
230
+ // Writes SPI_MEM_PAGE_SIZE bytes from `input` at `page_addr`
159
231
static bool _spi_mem_page_write (uint32_t page_addr , const uint8_t * input )
160
232
{
161
233
if (page_addr % SPI_MEM_PAGE_SIZE != 0 ) {
162
234
util_log ("Invalid page write address %p" , (void * )(uintptr_t )page_addr );
163
235
return false;
164
236
}
165
237
166
- uint8_t buffer [ SPI_MEM_PAGE_SIZE + 4 ];
167
- // --- Enable Write ---
168
- buffer [ 0 ] = CMD_WREN ;
169
- _spi_mem_cs_low ();
170
- SPI_MEM_exchange_block ( buffer , 1 );
171
- _spi_mem_cs_high ();
238
+ if ( _spi_mem_verify_address_protected ( page_addr )) {
239
+ util_log ( "Page address %p protected" , ( void * )( uintptr_t ) page_addr );
240
+ return false ;
241
+ }
242
+
243
+ _spi_mem_write_enable ();
172
244
173
245
// --- Page Program (write 4 bytes) ---
246
+ uint8_t buffer [SPI_MEM_PAGE_SIZE + 4 ];
174
247
buffer [0 ] = CMD_PP ;
175
248
buffer [1 ] = (page_addr >> 16 ) & 0xFF ;
176
249
buffer [2 ] = (page_addr >> 8 ) & 0xFF ;
@@ -184,6 +257,16 @@ static bool _spi_mem_page_write(uint32_t page_addr, const uint8_t* input)
184
257
// --- Wait for write to end ---
185
258
_spi_mem_wait ();
186
259
260
+ // --- Check that input data has been properly written ---
261
+ uint8_t read_data [SPI_MEM_PAGE_SIZE ];
262
+ if (!spi_mem_page_read (page_addr , read_data )) {
263
+ util_log ("Read after page write at %p failed" , (void * )(uintptr_t )page_addr );
264
+ return false;
265
+ }
266
+ if (memcmp (read_data , input , SPI_MEM_PAGE_SIZE ) != 0 ) {
267
+ util_log ("Write page at %p failed" , (void * )(uintptr_t )page_addr );
268
+ return false;
269
+ }
187
270
return true;
188
271
}
189
272
@@ -194,6 +277,11 @@ bool spi_mem_write(uint32_t address, const uint8_t* input, size_t size)
194
277
return false;
195
278
}
196
279
280
+ if (_spi_mem_verify_address_protected (address )) {
281
+ util_log ("Address %p protected" , (void * )(uintptr_t )address );
282
+ return false;
283
+ }
284
+
197
285
uint32_t initial_sector_addr = address & SECTOR_MASK ;
198
286
uint32_t final_sector_addr = ((address + size - 1 ) & SECTOR_MASK ) + SPI_MEM_SECTOR_SIZE ;
199
287
uint16_t sectors = (final_sector_addr - initial_sector_addr ) / SPI_MEM_SECTOR_SIZE ;
@@ -250,3 +338,52 @@ int32_t spi_mem_smart_erase(void)
250
338
251
339
return erased_sectors ;
252
340
}
341
+
342
+ // Writes the `protection` bits into the status register and sets the
343
+ // Top/Bottom bit to bottom in the configuration register.
344
+ static void _spi_mem_set_protection (uint8_t protection )
345
+ {
346
+ uint8_t reg [3 ];
347
+ reg [0 ] = _spi_mem_read_sr ();
348
+ _spi_mem_read_cr (& reg [1 ]);
349
+
350
+ // clean and update status register with protection bits
351
+ reg [0 ] &= ~SR_PROTECT_BITS_MASK ;
352
+ reg [0 ] |= protection & SR_PROTECT_BITS_MASK ;
353
+
354
+ // set the top/bottom protection bit.
355
+ // This is an OTP bit,so the write will have an effect
356
+ // only the first time.
357
+ reg [1 ] = reg [1 ] | CR1_TB_BIT_BOTTOM ;
358
+
359
+ _spi_mem_write_sr (reg );
360
+ }
361
+
362
+ void spi_mem_protected_area_lock (void )
363
+ {
364
+ _spi_mem_set_protection (SR_PROTECT_BITS );
365
+ }
366
+
367
+ void spi_mem_protected_area_unlock (void )
368
+ {
369
+ _spi_mem_set_protection (0x0 );
370
+ }
371
+
372
+ bool spi_mem_protected_area_write (uint32_t address , const uint8_t * input , size_t size )
373
+ {
374
+ // Additional assert to simplify debug.
375
+ ASSERT (_spi_mem_verify_address_protected (address + size ));
376
+ if (!_spi_mem_verify_address_protected (address + size )) {
377
+ util_log (
378
+ "Write address %p and size %i outside protected area" ,
379
+ (void * )(uintptr_t )address ,
380
+ (int )size );
381
+ return false;
382
+ }
383
+ uint8_t protection = _spi_mem_read_sr () & SR_PROTECT_BITS_MASK ;
384
+ _spi_mem_set_protection (0x0 );
385
+ bool result = spi_mem_write (address , input , size );
386
+ _spi_mem_set_protection (protection );
387
+
388
+ return result ;
389
+ }
0 commit comments