17
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
// /////////////////////////////////////////////////////////////////////////////
19
19
20
- #include < stdint.h>
21
- #include < stdio.h>
22
- #include < stdlib.h>
23
- #include < memory>
24
- #include < iostream>
25
- #include < exception>
26
-
27
- #include " Samba.h"
28
- #include " WordCopyApplet.h"
29
20
#include " NvmFlash.h"
30
21
31
22
// System control brown out register.
37
28
#define SYSCTRL_STATUS_REG_BOD33_RESET_ENABLE_BIT (0x8ul )
38
29
#define SYSCTRL_STATUS_REG_BOD33_RESET_MASK (0xffffffe7ul )
39
30
40
- // The base address of the NVM module in
41
- // main memory + offset to the CTRLA register
42
- #define NVM_CTRLA_REG (_regs+0x00 )
43
-
44
- #define NVM_CTRLB_REG (_regs+0x04 )
45
-
46
- // The NVM register that stores lock status
47
- #define NVM_LOCK_REG (_regs+0x20 )
48
-
49
- // The interrupt status register
50
- #define NVM_INT_STATUS_REG (_regs+0x14 )
31
+ // CMDEX field should be 0xA5 to allow execution of any command.
32
+ #define CMDEX_KEY 0xa500
51
33
52
34
// NVM ready bit mask
53
35
#define NVM_INT_STATUS_READY_MASK 0x1
54
36
55
- // NVM input register to some of the CMDEX commands.
56
- #define NVM_ADDR_REG (_regs+0x1c )
57
-
58
- // NVM STATUS register
59
- #define NVM_STATUS_REG (_regs+0x18 )
60
- #define NVMCTRL_STATUS_MASK (0xFFEBu )
61
-
62
- // CMDEX field should be 0xA5 to allow execution of any command.
63
- #define CMDEX_KEY (0xa500u )
64
-
65
- // List of NVM Commands.//as per datasheet prefix CMDEX
66
- #define CMD_LOCK_REGION (CMDEX_KEY | 0x0040u )
67
- #define CMD_UNLOCK_REGION (CMDEX_KEY | 0x0041u )
68
- #define CMD_ERASE_ROW (CMDEX_KEY | 0x0002u )
69
- #define CMD_WRITE_PAGE (CMDEX_KEY | 0x0004u )
70
- #define CMD_SET_SECURITY_BIT (CMDEX_KEY | 0x0045u )
71
- #define CMD_CLEAR_PAGE_BUFFER (CMDEX_KEY | 0x0044u )
72
-
73
- // This is the word size allowed by the communication layer of this bossa client, not the NVM word size which is 2 bytes
74
- #define SAMBA_API_WORD_SIZE (4ul ) // bytes
37
+ // NVM status mask
38
+ #define NVM_CTRL_STATUS_MASK 0xFFEB
39
+
40
+ NvmFlashD2x::NvmFlashD2x (
41
+ Samba& samba,
42
+ const std::string& name,
43
+ uint32_t addr,
44
+ uint32_t pages,
45
+ uint32_t size,
46
+ uint32_t planes,
47
+ uint32_t lockRegions,
48
+ uint32_t user,
49
+ uint32_t stack,
50
+ bool canBrownout) : NvmFlash(samba, name, addr, pages, size, planes, lockRegions, user, stack, canBrownout)
51
+ {
52
+ _regBase = 0x41004000 ;
53
+
54
+ _regCTRLA = 0x00 ;
55
+ _regCTRLB = 0x04 ;
56
+ _regINTFLAG = 0x14 ;
57
+ _regSTATUS = 0x18 ;
58
+ _regADDR = 0x1c ;
59
+ _regLOCK = 0x20 ;
60
+
61
+ _cmdER = 0x02 ;
62
+ _cmdWP = 0x04 ;
63
+ _cmdLR = 0x40 ;
64
+ _cmdUR = 0x41 ;
65
+ _cmdSSB = 0x45 ;
66
+ _cmdPBC = 0x44 ;
67
+ }
75
68
76
69
/* This class is designed specifically for SAM Dxx architecture in mind */
77
70
NvmFlash::NvmFlash (Samba& samba,
@@ -83,14 +76,10 @@ NvmFlash::NvmFlash(Samba& samba,
83
76
uint32_t lockRegions,
84
77
uint32_t user,
85
78
uint32_t stack,
86
- uint32_t regs,
87
79
bool canBrownout)
88
80
: Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack),
89
- _regs(regs), _canBrownout(canBrownout)
81
+ _canBrownout(canBrownout)
90
82
{
91
- // Upon power up the NVM controller goes through a power up sequence.
92
- // During this time, access to the NVM controller is halted. Upon power up the
93
- // the NVM controller is operational without any need for user configuration.
94
83
}
95
84
96
85
NvmFlash::~NvmFlash ()
@@ -109,42 +98,42 @@ NvmFlash::eraseAll()
109
98
// Leave the first 8KB, where bootloader resides, erase the rest.
110
99
// Row is a concept used for convinence. When writing you have to write
111
100
// page(s). When erasing you have to erase row(s).
112
-
101
+ // Use the extended Samba command if available
113
102
if (_samba.canChipErase ())
114
103
{
115
104
_samba.chipErase (_addr);
116
- return ;
117
105
}
118
-
119
- // Calculate the number of rows that samba occupies (should be 32 for 8KB/0x2000bytes).
120
- uint32_t starting_row = bootloaderSize / _size / flashRowPages;
121
- uint32_t total_rows = _pages / flashRowPages;
122
-
123
- for (uint32_t row=starting_row; row<total_rows; row++)
106
+ else
124
107
{
125
- uint32_t addr_in_flash = (row * flashRowPages * pageSize ());
126
- // The address is byte address, so convert it to word address.
127
- addr_in_flash = addr_in_flash / 2 ;
108
+ // Calculate the number of rows that samba occupies (should be 32 for 8KB/0x2000bytes).
109
+ uint32_t starting_row = bootloaderSize / _size / flashRowPages;
110
+ uint32_t total_rows = _pages / flashRowPages ;
128
111
129
- // Safe wait. Check and see if this is needed all the time
130
- while (!nvmIsReady ())
112
+ for (uint32_t row=starting_row; row<total_rows; row++)
131
113
{
132
- }
114
+ uint32_t addr_in_flash = (row * flashRowPages * pageSize ());
115
+ // The address is byte address, so convert it to word address.
116
+ addr_in_flash = addr_in_flash / 2 ;
117
+
118
+ // Safe wait. Check and see if this is needed all the time
119
+ while (!nvmIsReady ())
120
+ ;
133
121
134
- // Clear error bits
135
- uint16_t status_reg = _samba. readWord (NVM_STATUS_REG ) & 0xffff ;
136
- _samba. writeWord (NVM_STATUS_REG , status_reg | NVMCTRL_STATUS_MASK );
122
+ // Clear error bits
123
+ uint16_t status_reg = readReg (_regSTATUS ) & 0xffff ;
124
+ writeReg (_regSTATUS , status_reg | NVM_CTRL_STATUS_MASK );
137
125
138
- // Issue erase command
139
- _samba.writeWord (NVM_ADDR_REG, addr_in_flash);
140
- executeNvmCommand (CMD_ERASE_ROW);
126
+ // Issue erase command
127
+ writeReg (_regADDR, addr_in_flash);
128
+ executeNvmCommand (_cmdER);
129
+ }
141
130
}
142
131
}
143
132
144
133
bool
145
134
NvmFlash::nvmIsReady ()
146
135
{
147
- uint8_t int_flag = _samba. readByte (NVM_INT_STATUS_REG ) & NVM_INT_STATUS_READY_MASK;
136
+ uint8_t int_flag = readReg (_regINTFLAG ) & NVM_INT_STATUS_READY_MASK;
148
137
149
138
return int_flag == 1 ;
150
139
}
@@ -170,7 +159,7 @@ NvmFlash::getLockRegion(uint32_t region)
170
159
throw FlashRegionError ();
171
160
}
172
161
173
- uint32_t value = _samba. readWord (NVM_LOCK_REG );
162
+ uint32_t value = readReg (_regLOCK );
174
163
175
164
return ((value & (1 << region)) == 0 ); // 0 -> locked, 1 -> unlocked,
176
165
}
@@ -193,17 +182,17 @@ NvmFlash::setLockRegion(uint32_t region, bool enable)
193
182
// on the NVM controller.
194
183
uint32_t addr_to_lock = getAddressByRegion (region);
195
184
// addr_to_lock = addr_to_lock & 0x1fffff;
196
- _samba. writeWord (NVM_ADDR_REG , addr_to_lock);
185
+ writeReg (_regADDR , addr_to_lock);
197
186
198
- executeNvmCommand (CMD_LOCK_REGION );
187
+ executeNvmCommand (_cmdLR );
199
188
}
200
189
else
201
190
{
202
191
uint32_t addr_to_unlock = getAddressByRegion (region);
203
192
addr_to_unlock = addr_to_unlock & 0x1fffff ;
204
- _samba. writeWord (NVM_ADDR_REG , addr_to_unlock);
193
+ writeReg (_regADDR , addr_to_unlock);
205
194
206
- executeNvmCommand (CMD_UNLOCK_REGION );
195
+ executeNvmCommand (_cmdUR );
207
196
}
208
197
}
209
198
}
@@ -213,7 +202,7 @@ NvmFlash::setLockRegion(uint32_t region, bool enable)
213
202
bool
214
203
NvmFlash::getSecurity ()
215
204
{
216
- uint16_t status_reg_value = _samba. readWord (NVM_STATUS_REG) & 0xffff ;
205
+ uint16_t status_reg_value = readReg (_regSTATUS) ;
217
206
218
207
// If the 8th bit is 1 then security bit is set, else unset.
219
208
return (((status_reg_value >> 8 ) & 0x1 ) == 1 );
@@ -225,7 +214,7 @@ NvmFlash::setSecurity()
225
214
{
226
215
if (!getSecurity ())
227
216
{
228
- executeNvmCommand (CMD_SET_SECURITY_BIT );
217
+ executeNvmCommand (_cmdSSB );
229
218
230
219
if (!getSecurity ())
231
220
{
@@ -310,16 +299,16 @@ NvmFlash::writePage(uint32_t page)
310
299
}
311
300
312
301
// Clear page buffer
313
- executeNvmCommand (CMD_CLEAR_PAGE_BUFFER );
302
+ executeNvmCommand (_cmdPBC );
314
303
315
304
// Clear error flags in target
316
- uint16_t status_reg = _samba. readWord (NVM_STATUS_REG ) & 0xffff ;
317
- _samba. writeWord (NVM_STATUS_REG , status_reg | NVMCTRL_STATUS_MASK );
305
+ uint16_t status_reg = readReg (_regSTATUS ) & 0xffff ;
306
+ writeReg (_regSTATUS , status_reg | NVM_CTRL_STATUS_MASK );
318
307
319
308
// Configure manual page write. This is critical for the write to work
320
309
// irrespective of full page or partial page.
321
- uint32_t ctrlb_reg = _samba. readWord (NVM_CTRLB_REG );
322
- _samba. writeWord (NVM_CTRLB_REG , ctrlb_reg | (0x1 << 7 ));
310
+ uint32_t ctrlb_reg = readReg (_regCTRLB );
311
+ writeReg (_regCTRLB , ctrlb_reg | (0x1 << 7 ));
323
312
324
313
// Compute the start address.
325
314
uint32_t addr = _addr + (page * _size );
@@ -335,9 +324,9 @@ NvmFlash::writePage(uint32_t page)
335
324
336
325
while (!nvmIsReady ());
337
326
338
- _samba. writeWord (NVM_ADDR_REG , addr_cached >> 1 );
327
+ writeReg (_regADDR , addr_cached >> 1 );
339
328
// Reset the buffer, so that subsequent reads are clear
340
- executeNvmCommand (CMD_WRITE_PAGE );
329
+ executeNvmCommand (_cmdWP );
341
330
}
342
331
343
332
void
@@ -355,6 +344,18 @@ NvmFlash::readPage(uint32_t page, uint8_t* buf)
355
344
_samba.read (addr, buf, pageSize ());
356
345
}
357
346
347
+ uint32_t
348
+ NvmFlash::readReg (uint8_t reg)
349
+ {
350
+ return _samba.readWord (_regBase + reg);
351
+ }
352
+
353
+ void
354
+ NvmFlash::writeReg (uint8_t reg, uint32_t value)
355
+ {
356
+ _samba.writeWord (_regBase + reg, value);
357
+ }
358
+
358
359
// Returns the start address of a specified region number
359
360
// based on the flash specifications. The returned address is
360
361
// word address (not byte address).
@@ -374,20 +375,18 @@ NvmFlash::getAddressByRegion(uint32_t region_num)
374
375
}
375
376
376
377
void
377
- NvmFlash::executeNvmCommand (uint32_t cmd)
378
+ NvmFlash::executeNvmCommand (uint8_t cmd)
378
379
{
379
380
// Wait for the nvm controller to be ready
380
381
while (!nvmIsReady ())
381
- {
382
- }
382
+ ;
383
383
384
384
// Send the comamnd to nvm controller.
385
- _samba. writeWord (NVM_CTRLA_REG, cmd);
385
+ writeReg (_regCTRLA, CMDEX_KEY | cmd);
386
386
387
387
// Wait till the operation completes.
388
388
while (!nvmIsReady ())
389
- {
390
- }
389
+ ;
391
390
392
391
// TODO : check and return return error status from nvm status flag.
393
392
}
0 commit comments