Revisions on Gareth's comments.
o Implemented byte writes to EEPROM now that the emulator has a byte-wide target write. o Added comment describing the reason that mass erase doesn't work. o Removed all unused code. o Changed to Linux kernel indent style. o Changed to Linux kernel function to parenthesis style. o Stub generation doesn't use Perl, switched to sed. Also, only including the instructions instead of the source and the instructions. o Handling unaligned destination writes.
This commit is contained in:
parent
e0a8ce5a88
commit
bf1cb71eb7
|
@ -11,3 +11,9 @@ of half-words for inclusion in the target driver. The use of a higher
|
|||
level language allows more detailed code and for easy revisions.
|
||||
These stubs communicate with the driver through a structure defined in
|
||||
the src/include/stm32l0-nvm.h header.
|
||||
|
||||
The dump-to-array.sh helper script uses sed to transform the output of
|
||||
'objdump -d' into a half-word array of the instructions that may be
|
||||
included in C code to declare the stub. FWIW, objcopy doesn't produce
|
||||
the same output as objdump. It omits some of the instructions,
|
||||
probably because the object file isn't linked.
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Convert the output of objdump to an array of bytes are can include
|
||||
# into our program.
|
||||
|
||||
while (<>) {
|
||||
if (m/^\s*([0-9a-fA-F]+):\s*([0-9a-fA-F]+)(.*)/) {
|
||||
my $addr = "0x$1";
|
||||
my $value = $2;
|
||||
if (length ($value) == 4) {
|
||||
print " [$addr/2] = 0x$value, // $_";
|
||||
}
|
||||
else {
|
||||
my $lsb = substr ($value, 4, 4);
|
||||
my $msb = substr ($value, 0, 4);
|
||||
print " [$addr/2] = 0x$lsb, // $_";
|
||||
print " [$addr/2 + 1] = 0x$msb,\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "// ", $_;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Convert the output of objdump to an array of half-words that can be
|
||||
# included into C code to represent the stub.
|
||||
#
|
||||
# Invoke with something like this:
|
||||
#
|
||||
# objdump -z -d FILE.o | dump-to-array.sh > FILE.stub
|
||||
#
|
||||
|
||||
sed -E "/^[ ][ ]*[0-9a-fA-F]+:/!d; s/([0-9a-fA-F]+):[ \t]+([0-9a-fA-F]+).*/[0x\1\/2] = 0x\2,/ ; s/0x(....)(....),/0x\2, 0x\1,/"
|
|
@ -42,52 +42,52 @@
|
|||
/* Erase a region of flash. In the event that the erase is misaligned
|
||||
with respect to pages, it will erase the pages that contain the
|
||||
requested range of bytes. */
|
||||
extern "C" void __attribute((naked)) stm32l05x_nvm_prog_erase () {
|
||||
// Leave room for INFO at second word of routine
|
||||
__asm volatile ("b 0f\n\t"
|
||||
".align 2\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
"0:");
|
||||
extern "C" void __attribute((naked)) stm32l05x_nvm_prog_erase() {
|
||||
// Leave room for INFO at second word of routine
|
||||
__asm volatile ("b 0f\n\t"
|
||||
".align 2\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
"0:");
|
||||
|
||||
auto& nvm = Nvm (Info.nvm);
|
||||
auto& nvm = Nvm (Info.nvm);
|
||||
|
||||
// Align to the start of the first page so that we make sure to erase
|
||||
// all of the target pages.
|
||||
auto remainder = reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size - 1);
|
||||
Info.size += remainder;
|
||||
Info.destination -= remainder/sizeof (*Info.destination);
|
||||
// Align to the start of the first page so that we make sure to erase
|
||||
// all of the target pages.
|
||||
auto remainder = reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size - 1);
|
||||
Info.size += remainder;
|
||||
Info.destination -= remainder/sizeof (*Info.destination);
|
||||
|
||||
if (!unlock (nvm))
|
||||
goto quit;
|
||||
if (!unlock(nvm))
|
||||
goto quit;
|
||||
|
||||
nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
|
||||
// Enable erasing
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE;
|
||||
if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
!= (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
goto quit;
|
||||
// Enable erasing
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE;
|
||||
if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
!= (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
goto quit;
|
||||
|
||||
while (Info.size > 0) {
|
||||
*Info.destination = 0; // Initiate erase
|
||||
while (Info.size > 0) {
|
||||
*Info.destination = 0; // Initiate erase
|
||||
|
||||
Info.destination += Info.page_size/sizeof (*Info.destination);
|
||||
Info.size -= Info.page_size;
|
||||
}
|
||||
Info.destination += Info.page_size/sizeof (*Info.destination);
|
||||
Info.size -= Info.page_size;
|
||||
}
|
||||
|
||||
quit:
|
||||
lock (nvm);
|
||||
__asm volatile ("bkpt");
|
||||
lock(nvm);
|
||||
__asm volatile ("bkpt");
|
||||
}
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-erase.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-erase.lst stm32l05x-nvm-prog-erase.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-erase.o | ./code-to-array.pl > stm32l05x-nvm-prog-erase.stub"
|
||||
compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-erase.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-erase.lst stm32l05x-nvm-prog-erase.cc ; /opt/arm/arm-none-eabi-objdump -d -z stm32l05x-nvm-prog-erase.o | ./dump-to-array.sh > stm32l05x-nvm-prog-erase.stub"
|
||||
End:
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,159 +1,67 @@
|
|||
//
|
||||
// stm32l05x-nvm-prog-erase.o: file format elf32-littlearm
|
||||
//
|
||||
//
|
||||
// Disassembly of section .text:
|
||||
//
|
||||
// 00000000 <stm32l05x_nvm_prog_erase>:
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// "0:");
|
||||
[0x0/2] = 0xe00a, // 0: e00a b.n 18 <stm32l05x_nvm_prog_erase+0x18>
|
||||
[0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8)
|
||||
// ...
|
||||
//
|
||||
// auto& nvm = Nvm (Info.nvm);
|
||||
[0x18/2] = 0x491a, // 18: 491a ldr r1, [pc, #104] ; (84 <stm32l05x_nvm_prog_erase+0x84>)
|
||||
//
|
||||
// // Align to the start of the first page so that we make sure to erase
|
||||
// // all of the target pages.
|
||||
// auto remainder = reinterpret_cast<uint32_t> (Info.destination)
|
||||
// & (Info.page_size - 1);
|
||||
[0x1a/2] = 0x8a08, // 1a: 8a08 ldrh r0, [r1, #16]
|
||||
[0x1c/2] = 0x680c, // 1c: 680c ldr r4, [r1, #0]
|
||||
// Info.size += remainder;
|
||||
[0x1e/2] = 0x684d, // 1e: 684d ldr r5, [r1, #4]
|
||||
// auto& nvm = Nvm (Info.nvm);
|
||||
//
|
||||
// // Align to the start of the first page so that we make sure to erase
|
||||
// // all of the target pages.
|
||||
// auto remainder = reinterpret_cast<uint32_t> (Info.destination)
|
||||
// & (Info.page_size - 1);
|
||||
[0x20/2] = 0x1e42, // 20: 1e42 subs r2, r0, #1
|
||||
[0x22/2] = 0x4022, // 22: 4022 ands r2, r4
|
||||
// Info.size += remainder;
|
||||
[0x24/2] = 0x1955, // 24: 1955 adds r5, r2, r5
|
||||
// Info.destination -= remainder/sizeof (*Info.destination);
|
||||
[0x26/2] = 0x0892, // 26: 0892 lsrs r2, r2, #2
|
||||
[0x28/2] = 0x0092, // 28: 0092 lsls r2, r2, #2
|
||||
[0x2a/2] = 0x1aa2, // 2a: 1aa2 subs r2, r4, r2
|
||||
[0x2c/2] = 0x600a, // 2c: 600a str r2, [r1, #0]
|
||||
// #define Nvm(nvm) (*reinterpret_cast<STM32::NVM*>(nvm))
|
||||
// #define Info (*reinterpret_cast<stm32lx_nvm_stub_info*>(STM32Lx_STUB_INFO_PHYS))
|
||||
//
|
||||
// namespace {
|
||||
// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock
|
||||
[0x2e/2] = 0x2201, // 2e: 2201 movs r2, #1
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// "0:");
|
||||
//
|
||||
// auto& nvm = Nvm (Info.nvm);
|
||||
[0x30/2] = 0x68cb, // 30: 68cb ldr r3, [r1, #12]
|
||||
//
|
||||
// // Align to the start of the first page so that we make sure to erase
|
||||
// // all of the target pages.
|
||||
// auto remainder = reinterpret_cast<uint32_t> (Info.destination)
|
||||
// & (Info.page_size - 1);
|
||||
// Info.size += remainder;
|
||||
[0x32/2] = 0x604d, // 32: 604d str r5, [r1, #4]
|
||||
[0x34/2] = 0x605a, // 34: 605a str r2, [r3, #4]
|
||||
// nvm.pkeyr = STM32::NVM::PKEY1;
|
||||
[0x36/2] = 0x4a14, // 36: 4a14 ldr r2, [pc, #80] ; (88 <stm32l05x_nvm_prog_erase+0x88>)
|
||||
[0x38/2] = 0x60da, // 38: 60da str r2, [r3, #12]
|
||||
// nvm.pkeyr = STM32::NVM::PKEY2;
|
||||
[0x3a/2] = 0x4a14, // 3a: 4a14 ldr r2, [pc, #80] ; (8c <stm32l05x_nvm_prog_erase+0x8c>)
|
||||
[0x3c/2] = 0x60da, // 3c: 60da str r2, [r3, #12]
|
||||
// nvm.prgkeyr = STM32::NVM::PRGKEY1;
|
||||
[0x3e/2] = 0x4a14, // 3e: 4a14 ldr r2, [pc, #80] ; (90 <stm32l05x_nvm_prog_erase+0x90>)
|
||||
[0x40/2] = 0x611a, // 40: 611a str r2, [r3, #16]
|
||||
// nvm.prgkeyr = STM32::NVM::PRGKEY2;
|
||||
[0x42/2] = 0x4a14, // 42: 4a14 ldr r2, [pc, #80] ; (94 <stm32l05x_nvm_prog_erase+0x94>)
|
||||
[0x44/2] = 0x611a, // 44: 611a str r2, [r3, #16]
|
||||
// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK);
|
||||
[0x46/2] = 0x685a, // 46: 685a ldr r2, [r3, #4]
|
||||
// Info.destination -= remainder/sizeof (*Info.destination);
|
||||
//
|
||||
// if (!unlock (nvm))
|
||||
[0x48/2] = 0x0792, // 48: 0792 lsls r2, r2, #30
|
||||
[0x4a/2] = 0xd502, // 4a: d502 bpl.n 52 <stm32l05x_nvm_prog_erase+0x52>
|
||||
// }
|
||||
// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; }
|
||||
[0x4c/2] = 0x2201, // 4c: 2201 movs r2, #1
|
||||
[0x4e/2] = 0x605a, // 4e: 605a str r2, [r3, #4]
|
||||
// Info.size -= Info.page_size;
|
||||
// }
|
||||
//
|
||||
// quit:
|
||||
// lock (nvm);
|
||||
// __asm volatile ("bkpt");
|
||||
[0x50/2] = 0xbe00, // 50: be00 bkpt 0x0000
|
||||
// Info.destination -= remainder/sizeof (*Info.destination);
|
||||
//
|
||||
// if (!unlock (nvm))
|
||||
// goto quit;
|
||||
//
|
||||
// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
[0x52/2] = 0x4a11, // 52: 4a11 ldr r2, [pc, #68] ; (98 <stm32l05x_nvm_prog_erase+0x98>)
|
||||
[0x54/2] = 0x619a, // 54: 619a str r2, [r3, #24]
|
||||
//
|
||||
// // Enable erasing
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE;
|
||||
[0x56/2] = 0x2282, // 56: 2282 movs r2, #130 ; 0x82
|
||||
[0x58/2] = 0x0092, // 58: 0092 lsls r2, r2, #2
|
||||
[0x5a/2] = 0x605a, // 5a: 605a str r2, [r3, #4]
|
||||
// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
[0x5c/2] = 0x685c, // 5c: 685c ldr r4, [r3, #4]
|
||||
[0x5e/2] = 0x4014, // 5e: 4014 ands r4, r2
|
||||
[0x60/2] = 0x4294, // 60: 4294 cmp r4, r2
|
||||
[0x62/2] = 0xd1f3, // 62: d1f3 bne.n 4c <stm32l05x_nvm_prog_erase+0x4c>
|
||||
// goto quit;
|
||||
//
|
||||
// while (Info.size > 0) {
|
||||
// *Info.destination = 0; // Initiate erase
|
||||
//
|
||||
// Info.destination += Info.page_size/sizeof (*Info.destination);
|
||||
[0x64/2] = 0x0884, // 64: 0884 lsrs r4, r0, #2
|
||||
[0x66/2] = 0x00a4, // 66: 00a4 lsls r4, r4, #2
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE;
|
||||
// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
// != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
// goto quit;
|
||||
//
|
||||
// while (Info.size > 0) {
|
||||
[0x68/2] = 0x684d, // 68: 684d ldr r5, [r1, #4]
|
||||
[0x6a/2] = 0x4a06, // 6a: 4a06 ldr r2, [pc, #24] ; (84 <stm32l05x_nvm_prog_erase+0x84>)
|
||||
[0x6c/2] = 0x2d00, // 6c: 2d00 cmp r5, #0
|
||||
[0x6e/2] = 0xdded, // 6e: dded ble.n 4c <stm32l05x_nvm_prog_erase+0x4c>
|
||||
// *Info.destination = 0; // Initiate erase
|
||||
[0x70/2] = 0x2600, // 70: 2600 movs r6, #0
|
||||
[0x72/2] = 0x6815, // 72: 6815 ldr r5, [r2, #0]
|
||||
[0x74/2] = 0x602e, // 74: 602e str r6, [r5, #0]
|
||||
//
|
||||
// Info.destination += Info.page_size/sizeof (*Info.destination);
|
||||
[0x76/2] = 0x6815, // 76: 6815 ldr r5, [r2, #0]
|
||||
[0x78/2] = 0x192d, // 78: 192d adds r5, r5, r4
|
||||
[0x7a/2] = 0x6015, // 7a: 6015 str r5, [r2, #0]
|
||||
// Info.size -= Info.page_size;
|
||||
[0x7c/2] = 0x6855, // 7c: 6855 ldr r5, [r2, #4]
|
||||
[0x7e/2] = 0x1a2d, // 7e: 1a2d subs r5, r5, r0
|
||||
[0x80/2] = 0x6055, // 80: 6055 str r5, [r2, #4]
|
||||
[0x82/2] = 0xe7f1, // 82: e7f1 b.n 68 <stm32l05x_nvm_prog_erase+0x68>
|
||||
[0x84/2] = 0x0004, // 84: 20000004 .word 0x20000004
|
||||
[0x84/2 + 1] = 0x2000,
|
||||
[0x88/2] = 0xcdef, // 88: 89abcdef .word 0x89abcdef
|
||||
[0x88/2 + 1] = 0x89ab,
|
||||
[0x8c/2] = 0x0405, // 8c: 02030405 .word 0x02030405
|
||||
[0x8c/2 + 1] = 0x0203,
|
||||
[0x90/2] = 0xaebf, // 90: 8c9daebf .word 0x8c9daebf
|
||||
[0x90/2 + 1] = 0x8c9d,
|
||||
[0x94/2] = 0x1516, // 94: 13141516 .word 0x13141516
|
||||
[0x94/2 + 1] = 0x1314,
|
||||
[0x98/2] = 0x0700, // 98: 00010700 .word 0x00010700
|
||||
[0x98/2 + 1] = 0x0001,
|
||||
[0x0/2] = 0xe00a,
|
||||
[0x2/2] = 0x46c0,
|
||||
[0x4/2] = 0x0000, 0x0000,
|
||||
[0x8/2] = 0x0000, 0x0000,
|
||||
[0xc/2] = 0x0000, 0x0000,
|
||||
[0x10/2] = 0x0000, 0x0000,
|
||||
[0x14/2] = 0x0000, 0x0000,
|
||||
[0x18/2] = 0x491a,
|
||||
[0x1a/2] = 0x8a08,
|
||||
[0x1c/2] = 0x680c,
|
||||
[0x1e/2] = 0x684d,
|
||||
[0x20/2] = 0x1e42,
|
||||
[0x22/2] = 0x4022,
|
||||
[0x24/2] = 0x1955,
|
||||
[0x26/2] = 0x0892,
|
||||
[0x28/2] = 0x0092,
|
||||
[0x2a/2] = 0x1aa2,
|
||||
[0x2c/2] = 0x600a,
|
||||
[0x2e/2] = 0x2201,
|
||||
[0x30/2] = 0x68cb,
|
||||
[0x32/2] = 0x604d,
|
||||
[0x34/2] = 0x605a,
|
||||
[0x36/2] = 0x4a14,
|
||||
[0x38/2] = 0x60da,
|
||||
[0x3a/2] = 0x4a14,
|
||||
[0x3c/2] = 0x60da,
|
||||
[0x3e/2] = 0x4a14,
|
||||
[0x40/2] = 0x611a,
|
||||
[0x42/2] = 0x4a14,
|
||||
[0x44/2] = 0x611a,
|
||||
[0x46/2] = 0x685a,
|
||||
[0x48/2] = 0x0792,
|
||||
[0x4a/2] = 0xd502,
|
||||
[0x4c/2] = 0x2201,
|
||||
[0x4e/2] = 0x605a,
|
||||
[0x50/2] = 0xbe00,
|
||||
[0x52/2] = 0x4a11,
|
||||
[0x54/2] = 0x619a,
|
||||
[0x56/2] = 0x2282,
|
||||
[0x58/2] = 0x0092,
|
||||
[0x5a/2] = 0x605a,
|
||||
[0x5c/2] = 0x685c,
|
||||
[0x5e/2] = 0x4014,
|
||||
[0x60/2] = 0x4294,
|
||||
[0x62/2] = 0xd1f3,
|
||||
[0x64/2] = 0x0884,
|
||||
[0x66/2] = 0x00a4,
|
||||
[0x68/2] = 0x684d,
|
||||
[0x6a/2] = 0x4a06,
|
||||
[0x6c/2] = 0x2d00,
|
||||
[0x6e/2] = 0xdded,
|
||||
[0x70/2] = 0x2600,
|
||||
[0x72/2] = 0x6815,
|
||||
[0x74/2] = 0x602e,
|
||||
[0x76/2] = 0x6815,
|
||||
[0x78/2] = 0x192d,
|
||||
[0x7a/2] = 0x6015,
|
||||
[0x7c/2] = 0x6855,
|
||||
[0x7e/2] = 0x1a2d,
|
||||
[0x80/2] = 0x6055,
|
||||
[0x82/2] = 0xe7f1,
|
||||
[0x84/2] = 0x0004, 0x2000,
|
||||
[0x88/2] = 0xcdef, 0x89ab,
|
||||
[0x8c/2] = 0x0405, 0x0203,
|
||||
[0x90/2] = 0xaebf, 0x8c9d,
|
||||
[0x94/2] = 0x1516, 0x1314,
|
||||
[0x98/2] = 0x0700, 0x0001,
|
||||
|
|
|
@ -43,70 +43,71 @@
|
|||
/* Write a block of bytes to flash. The called is responsible for
|
||||
making sure that the address are aligned and that the count is an
|
||||
even multiple of words. */
|
||||
extern "C" void __attribute((naked)) stm32l05x_nvm_prog_write () {
|
||||
extern "C" void __attribute((naked)) stm32l05x_nvm_prog_write() {
|
||||
// Leave room for INFO at second word of routine
|
||||
__asm volatile ("b 0f\n\t"
|
||||
".align 2\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
"0:");
|
||||
__asm volatile ("b 0f\n\t"
|
||||
".align 2\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
".word 0\n\t"
|
||||
"0:");
|
||||
|
||||
auto& nvm = Nvm (Info.nvm);
|
||||
auto& nvm = Nvm (Info.nvm);
|
||||
|
||||
if (!unlock (nvm))
|
||||
goto quit;
|
||||
if (!unlock(nvm))
|
||||
goto quit;
|
||||
|
||||
nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
|
||||
while (Info.size > 0) {
|
||||
while (Info.size > 0) {
|
||||
|
||||
// Either we're not half-page aligned or we have less than a half
|
||||
// page to write
|
||||
if (Info.size < Info.page_size/2
|
||||
|| (reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size/2 - 1))) {
|
||||
nvm.pecr = (Info.options & OPT_STM32L1) ? 0
|
||||
: STM32Lx_NVM_PECR_PROG; // Word programming
|
||||
size_t c = Info.page_size/2
|
||||
- (reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size/2 - 1));
|
||||
if (c > Info.size)
|
||||
c = Info.size;
|
||||
Info.size -= c;
|
||||
c /= 4;
|
||||
while (c--) {
|
||||
uint32_t v = *Info.source++;
|
||||
*Info.destination++ = v;
|
||||
if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
// Or we are writing a half-page(s)
|
||||
else {
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg
|
||||
size_t c = Info.size & ~(Info.page_size/2 - 1);
|
||||
Info.size -= c;
|
||||
c /= 4;
|
||||
while (c--) {
|
||||
uint32_t v = *Info.source++;
|
||||
*Info.destination++ = v;
|
||||
}
|
||||
if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
// Either we're not half-page aligned or we have less
|
||||
// than a half page to write
|
||||
if (Info.size < Info.page_size/2
|
||||
|| (reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size/2 - 1))) {
|
||||
nvm.pecr = (Info.options & OPT_STM32L1) ? 0
|
||||
: STM32Lx_NVM_PECR_PROG; // Word programming
|
||||
size_t c = Info.page_size/2
|
||||
- (reinterpret_cast<uint32_t> (Info.destination)
|
||||
& (Info.page_size/2 - 1));
|
||||
if (c > Info.size)
|
||||
c = Info.size;
|
||||
Info.size -= c;
|
||||
c /= 4;
|
||||
while (c--) {
|
||||
uint32_t v = *Info.source++;
|
||||
*Info.destination++ = v;
|
||||
if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
// Or we are writing a half-page(s)
|
||||
else {
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PROG
|
||||
| STM32Lx_NVM_PECR_FPRG; // Half-page prg
|
||||
size_t c = Info.size & ~(Info.page_size/2 - 1);
|
||||
Info.size -= c;
|
||||
c /= 4;
|
||||
while (c--) {
|
||||
uint32_t v = *Info.source++;
|
||||
*Info.destination++ = v;
|
||||
}
|
||||
if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
quit:
|
||||
lock (nvm);
|
||||
__asm volatile ("bkpt");
|
||||
lock(nvm);
|
||||
__asm volatile ("bkpt");
|
||||
}
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-write.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-write.lst stm32l05x-nvm-prog-write.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-write.o | ./code-to-array.pl > stm32l05x-nvm-prog-write.stub"
|
||||
compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-write.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-write.lst stm32l05x-nvm-prog-write.cc ; /opt/arm/arm-none-eabi-objdump -d -z stm32l05x-nvm-prog-write.o | ./dump-to-array.sh > stm32l05x-nvm-prog-write.stub"
|
||||
End:
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,201 +1,99 @@
|
|||
//
|
||||
// stm32l05x-nvm-prog-write.o: file format elf32-littlearm
|
||||
//
|
||||
//
|
||||
// Disassembly of section .text:
|
||||
//
|
||||
// 00000000 <stm32l05x_nvm_prog_write>:
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// ".word 0\n\t"
|
||||
// "0:");
|
||||
[0x0/2] = 0xe00a, // 0: e00a b.n 18 <stm32l05x_nvm_prog_write+0x18>
|
||||
[0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8)
|
||||
// ...
|
||||
// #define Nvm(nvm) (*reinterpret_cast<STM32::NVM*>(nvm))
|
||||
// #define Info (*reinterpret_cast<stm32lx_nvm_stub_info*>(STM32Lx_STUB_INFO_PHYS))
|
||||
//
|
||||
// namespace {
|
||||
// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock
|
||||
[0x18/2] = 0x2201, // 18: 2201 movs r2, #1
|
||||
//
|
||||
// auto& nvm = Nvm (Info.nvm);
|
||||
[0x1a/2] = 0x4b2a, // 1a: 4b2a ldr r3, [pc, #168] ; (c4 <stm32l05x_nvm_prog_write+0xc4>)
|
||||
[0x1c/2] = 0x68d9, // 1c: 68d9 ldr r1, [r3, #12]
|
||||
[0x1e/2] = 0x604a, // 1e: 604a str r2, [r1, #4]
|
||||
// nvm.pkeyr = STM32::NVM::PKEY1;
|
||||
[0x20/2] = 0x4a29, // 20: 4a29 ldr r2, [pc, #164] ; (c8 <stm32l05x_nvm_prog_write+0xc8>)
|
||||
[0x22/2] = 0x60ca, // 22: 60ca str r2, [r1, #12]
|
||||
// nvm.pkeyr = STM32::NVM::PKEY2;
|
||||
[0x24/2] = 0x4a29, // 24: 4a29 ldr r2, [pc, #164] ; (cc <stm32l05x_nvm_prog_write+0xcc>)
|
||||
[0x26/2] = 0x60ca, // 26: 60ca str r2, [r1, #12]
|
||||
// nvm.prgkeyr = STM32::NVM::PRGKEY1;
|
||||
[0x28/2] = 0x4a29, // 28: 4a29 ldr r2, [pc, #164] ; (d0 <stm32l05x_nvm_prog_write+0xd0>)
|
||||
[0x2a/2] = 0x610a, // 2a: 610a str r2, [r1, #16]
|
||||
// nvm.prgkeyr = STM32::NVM::PRGKEY2;
|
||||
[0x2c/2] = 0x4a29, // 2c: 4a29 ldr r2, [pc, #164] ; (d4 <stm32l05x_nvm_prog_write+0xd4>)
|
||||
[0x2e/2] = 0x610a, // 2e: 610a str r2, [r1, #16]
|
||||
// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK);
|
||||
[0x30/2] = 0x684a, // 30: 684a ldr r2, [r1, #4]
|
||||
//
|
||||
// if (!unlock (nvm))
|
||||
[0x32/2] = 0x0792, // 32: 0792 lsls r2, r2, #30
|
||||
[0x34/2] = 0xd502, // 34: d502 bpl.n 3c <stm32l05x_nvm_prog_write+0x3c>
|
||||
// }
|
||||
// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; }
|
||||
[0x36/2] = 0x2301, // 36: 2301 movs r3, #1
|
||||
[0x38/2] = 0x604b, // 38: 604b str r3, [r1, #4]
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// quit:
|
||||
// lock (nvm);
|
||||
// __asm volatile ("bkpt");
|
||||
[0x3a/2] = 0xbe00, // 3a: be00 bkpt 0x0000
|
||||
// auto& nvm = Nvm (Info.nvm);
|
||||
//
|
||||
// if (!unlock (nvm))
|
||||
// goto quit;
|
||||
//
|
||||
// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||
[0x3c/2] = 0x4826, // 3c: 4826 ldr r0, [pc, #152] ; (d8 <stm32l05x_nvm_prog_write+0xd8>)
|
||||
[0x3e/2] = 0x6188, // 3e: 6188 str r0, [r1, #24]
|
||||
//
|
||||
// while (Info.size > 0) {
|
||||
[0x40/2] = 0x685d, // 40: 685d ldr r5, [r3, #4]
|
||||
[0x42/2] = 0x4e20, // 42: 4e20 ldr r6, [pc, #128] ; (c4 <stm32l05x_nvm_prog_write+0xc4>)
|
||||
[0x44/2] = 0x2d00, // 44: 2d00 cmp r5, #0
|
||||
[0x46/2] = 0xddf6, // 46: ddf6 ble.n 36 <stm32l05x_nvm_prog_write+0x36>
|
||||
//
|
||||
// // Either we're not half-page aligned or we have less than a half
|
||||
// // page to write
|
||||
// if (Info.size < Info.page_size/2
|
||||
[0x48/2] = 0x8a32, // 48: 8a32 ldrh r2, [r6, #16]
|
||||
[0x4a/2] = 0x0852, // 4a: 0852 lsrs r2, r2, #1
|
||||
[0x4c/2] = 0x1e54, // 4c: 1e54 subs r4, r2, #1
|
||||
[0x4e/2] = 0x4295, // 4e: 4295 cmp r5, r2
|
||||
[0x50/2] = 0xdb02, // 50: db02 blt.n 58 <stm32l05x_nvm_prog_write+0x58>
|
||||
// || (reinterpret_cast<uint32_t> (Info.destination)
|
||||
[0x52/2] = 0x6837, // 52: 6837 ldr r7, [r6, #0]
|
||||
[0x54/2] = 0x4227, // 54: 4227 tst r7, r4
|
||||
[0x56/2] = 0xd01d, // 56: d01d beq.n 94 <stm32l05x_nvm_prog_write+0x94>
|
||||
// & (Info.page_size/2 - 1))) {
|
||||
// nvm.pecr = (Info.options & OPT_STM32L1) ? 0
|
||||
// : STM32Lx_NVM_PECR_PROG; // Word programming
|
||||
[0x58/2] = 0x2602, // 58: 2602 movs r6, #2
|
||||
// // Either we're not half-page aligned or we have less than a half
|
||||
// // page to write
|
||||
// if (Info.size < Info.page_size/2
|
||||
// || (reinterpret_cast<uint32_t> (Info.destination)
|
||||
// & (Info.page_size/2 - 1))) {
|
||||
// nvm.pecr = (Info.options & OPT_STM32L1) ? 0
|
||||
[0x5a/2] = 0x8a5f, // 5a: 8a5f ldrh r7, [r3, #18]
|
||||
// : STM32Lx_NVM_PECR_PROG; // Word programming
|
||||
[0x5c/2] = 0x4037, // 5c: 4037 ands r7, r6
|
||||
[0x5e/2] = 0x427e, // 5e: 427e negs r6, r7
|
||||
[0x60/2] = 0x417e, // 60: 417e adcs r6, r7
|
||||
[0x62/2] = 0x00f6, // 62: 00f6 lsls r6, r6, #3
|
||||
[0x64/2] = 0x604e, // 64: 604e str r6, [r1, #4]
|
||||
// size_t c = Info.page_size/2
|
||||
// - (reinterpret_cast<uint32_t> (Info.destination)
|
||||
// & (Info.page_size/2 - 1));
|
||||
[0x66/2] = 0x681e, // 66: 681e ldr r6, [r3, #0]
|
||||
[0x68/2] = 0x4034, // 68: 4034 ands r4, r6
|
||||
[0x6a/2] = 0x1b12, // 6a: 1b12 subs r2, r2, r4
|
||||
[0x6c/2] = 0x42aa, // 6c: 42aa cmp r2, r5
|
||||
[0x6e/2] = 0xd900, // 6e: d900 bls.n 72 <stm32l05x_nvm_prog_write+0x72>
|
||||
[0x70/2] = 0x1c2a, // 70: 1c2a adds r2, r5, #0
|
||||
// if (c > Info.size)
|
||||
// c = Info.size;
|
||||
// Info.size -= c;
|
||||
[0x72/2] = 0x1aad, // 72: 1aad subs r5, r5, r2
|
||||
[0x74/2] = 0x605d, // 74: 605d str r5, [r3, #4]
|
||||
// c /= 4;
|
||||
[0x76/2] = 0x0892, // 76: 0892 lsrs r2, r2, #2
|
||||
// while (c--) {
|
||||
[0x78/2] = 0x3a01, // 78: 3a01 subs r2, #1
|
||||
[0x7a/2] = 0xd3e1, // 7a: d3e1 bcc.n 40 <stm32l05x_nvm_prog_write+0x40>
|
||||
// uint32_t v = *Info.source++;
|
||||
[0x7c/2] = 0x689c, // 7c: 689c ldr r4, [r3, #8]
|
||||
[0x7e/2] = 0x1d25, // 7e: 1d25 adds r5, r4, #4
|
||||
[0x80/2] = 0x609d, // 80: 609d str r5, [r3, #8]
|
||||
[0x82/2] = 0x6825, // 82: 6825 ldr r5, [r4, #0]
|
||||
// *Info.destination++ = v;
|
||||
[0x84/2] = 0x681c, // 84: 681c ldr r4, [r3, #0]
|
||||
[0x86/2] = 0x1d26, // 86: 1d26 adds r6, r4, #4
|
||||
[0x88/2] = 0x601e, // 88: 601e str r6, [r3, #0]
|
||||
[0x8a/2] = 0x6025, // 8a: 6025 str r5, [r4, #0]
|
||||
// if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
[0x8c/2] = 0x698c, // 8c: 698c ldr r4, [r1, #24]
|
||||
[0x8e/2] = 0x4204, // 8e: 4204 tst r4, r0
|
||||
[0x90/2] = 0xd0f2, // 90: d0f2 beq.n 78 <stm32l05x_nvm_prog_write+0x78>
|
||||
[0x92/2] = 0xe7d0, // 92: e7d0 b.n 36 <stm32l05x_nvm_prog_write+0x36>
|
||||
// goto quit;
|
||||
// }
|
||||
// }
|
||||
// // Or we are writing a half-page(s)
|
||||
// else {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg
|
||||
[0x94/2] = 0x2481, // 94: 2481 movs r4, #129 ; 0x81
|
||||
// size_t c = Info.size & ~(Info.page_size/2 - 1);
|
||||
[0x96/2] = 0x4252, // 96: 4252 negs r2, r2
|
||||
[0x98/2] = 0x402a, // 98: 402a ands r2, r5
|
||||
// Info.size -= c;
|
||||
[0x9a/2] = 0x1aad, // 9a: 1aad subs r5, r5, r2
|
||||
// goto quit;
|
||||
// }
|
||||
// }
|
||||
// // Or we are writing a half-page(s)
|
||||
// else {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg
|
||||
[0x9c/2] = 0x00e4, // 9c: 00e4 lsls r4, r4, #3
|
||||
[0x9e/2] = 0x604c, // 9e: 604c str r4, [r1, #4]
|
||||
// size_t c = Info.size & ~(Info.page_size/2 - 1);
|
||||
// Info.size -= c;
|
||||
// c /= 4;
|
||||
[0xa0/2] = 0x0892, // a0: 0892 lsrs r2, r2, #2
|
||||
// }
|
||||
// // Or we are writing a half-page(s)
|
||||
// else {
|
||||
// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg
|
||||
// size_t c = Info.size & ~(Info.page_size/2 - 1);
|
||||
// Info.size -= c;
|
||||
[0xa2/2] = 0x6075, // a2: 6075 str r5, [r6, #4]
|
||||
// c /= 4;
|
||||
// while (c--) {
|
||||
[0xa4/2] = 0x3a01, // a4: 3a01 subs r2, #1
|
||||
[0xa6/2] = 0xd308, // a6: d308 bcc.n ba <stm32l05x_nvm_prog_write+0xba>
|
||||
// uint32_t v = *Info.source++;
|
||||
[0xa8/2] = 0x689c, // a8: 689c ldr r4, [r3, #8]
|
||||
[0xaa/2] = 0x1d25, // aa: 1d25 adds r5, r4, #4
|
||||
[0xac/2] = 0x609d, // ac: 609d str r5, [r3, #8]
|
||||
[0xae/2] = 0x6825, // ae: 6825 ldr r5, [r4, #0]
|
||||
// *Info.destination++ = v;
|
||||
[0xb0/2] = 0x681c, // b0: 681c ldr r4, [r3, #0]
|
||||
[0xb2/2] = 0x1d26, // b2: 1d26 adds r6, r4, #4
|
||||
[0xb4/2] = 0x601e, // b4: 601e str r6, [r3, #0]
|
||||
[0xb6/2] = 0x6025, // b6: 6025 str r5, [r4, #0]
|
||||
[0xb8/2] = 0xe7f4, // b8: e7f4 b.n a4 <stm32l05x_nvm_prog_write+0xa4>
|
||||
// }
|
||||
// if (nvm.sr & STM32Lx_NVM_SR_ERR_M)
|
||||
[0xba/2] = 0x698a, // ba: 698a ldr r2, [r1, #24]
|
||||
[0xbc/2] = 0x4202, // bc: 4202 tst r2, r0
|
||||
[0xbe/2] = 0xd0bf, // be: d0bf beq.n 40 <stm32l05x_nvm_prog_write+0x40>
|
||||
[0xc0/2] = 0xe7b9, // c0: e7b9 b.n 36 <stm32l05x_nvm_prog_write+0x36>
|
||||
[0xc2/2] = 0x46c0, // c2: 46c0 nop ; (mov r8, r8)
|
||||
[0xc4/2] = 0x0004, // c4: 20000004 .word 0x20000004
|
||||
[0xc4/2 + 1] = 0x2000,
|
||||
[0xc8/2] = 0xcdef, // c8: 89abcdef .word 0x89abcdef
|
||||
[0xc8/2 + 1] = 0x89ab,
|
||||
[0xcc/2] = 0x0405, // cc: 02030405 .word 0x02030405
|
||||
[0xcc/2 + 1] = 0x0203,
|
||||
[0xd0/2] = 0xaebf, // d0: 8c9daebf .word 0x8c9daebf
|
||||
[0xd0/2 + 1] = 0x8c9d,
|
||||
[0xd4/2] = 0x1516, // d4: 13141516 .word 0x13141516
|
||||
[0xd4/2 + 1] = 0x1314,
|
||||
[0xd8/2] = 0x0700, // d8: 00010700 .word 0x00010700
|
||||
[0xd8/2 + 1] = 0x0001,
|
||||
[0x0/2] = 0xe00a,
|
||||
[0x2/2] = 0x46c0,
|
||||
[0x4/2] = 0x0000, 0x0000,
|
||||
[0x8/2] = 0x0000, 0x0000,
|
||||
[0xc/2] = 0x0000, 0x0000,
|
||||
[0x10/2] = 0x0000, 0x0000,
|
||||
[0x14/2] = 0x0000, 0x0000,
|
||||
[0x18/2] = 0x2201,
|
||||
[0x1a/2] = 0x4b2a,
|
||||
[0x1c/2] = 0x68d9,
|
||||
[0x1e/2] = 0x604a,
|
||||
[0x20/2] = 0x4a29,
|
||||
[0x22/2] = 0x60ca,
|
||||
[0x24/2] = 0x4a29,
|
||||
[0x26/2] = 0x60ca,
|
||||
[0x28/2] = 0x4a29,
|
||||
[0x2a/2] = 0x610a,
|
||||
[0x2c/2] = 0x4a29,
|
||||
[0x2e/2] = 0x610a,
|
||||
[0x30/2] = 0x684a,
|
||||
[0x32/2] = 0x0792,
|
||||
[0x34/2] = 0xd502,
|
||||
[0x36/2] = 0x2301,
|
||||
[0x38/2] = 0x604b,
|
||||
[0x3a/2] = 0xbe00,
|
||||
[0x3c/2] = 0x4826,
|
||||
[0x3e/2] = 0x6188,
|
||||
[0x40/2] = 0x685d,
|
||||
[0x42/2] = 0x4e20,
|
||||
[0x44/2] = 0x2d00,
|
||||
[0x46/2] = 0xddf6,
|
||||
[0x48/2] = 0x8a32,
|
||||
[0x4a/2] = 0x0852,
|
||||
[0x4c/2] = 0x1e54,
|
||||
[0x4e/2] = 0x4295,
|
||||
[0x50/2] = 0xdb02,
|
||||
[0x52/2] = 0x6837,
|
||||
[0x54/2] = 0x4227,
|
||||
[0x56/2] = 0xd01d,
|
||||
[0x58/2] = 0x2602,
|
||||
[0x5a/2] = 0x8a5f,
|
||||
[0x5c/2] = 0x4037,
|
||||
[0x5e/2] = 0x427e,
|
||||
[0x60/2] = 0x417e,
|
||||
[0x62/2] = 0x00f6,
|
||||
[0x64/2] = 0x604e,
|
||||
[0x66/2] = 0x681e,
|
||||
[0x68/2] = 0x4034,
|
||||
[0x6a/2] = 0x1b12,
|
||||
[0x6c/2] = 0x42aa,
|
||||
[0x6e/2] = 0xd900,
|
||||
[0x70/2] = 0x1c2a,
|
||||
[0x72/2] = 0x1aad,
|
||||
[0x74/2] = 0x605d,
|
||||
[0x76/2] = 0x0892,
|
||||
[0x78/2] = 0x3a01,
|
||||
[0x7a/2] = 0xd3e1,
|
||||
[0x7c/2] = 0x689c,
|
||||
[0x7e/2] = 0x1d25,
|
||||
[0x80/2] = 0x609d,
|
||||
[0x82/2] = 0x6825,
|
||||
[0x84/2] = 0x681c,
|
||||
[0x86/2] = 0x1d26,
|
||||
[0x88/2] = 0x601e,
|
||||
[0x8a/2] = 0x6025,
|
||||
[0x8c/2] = 0x698c,
|
||||
[0x8e/2] = 0x4204,
|
||||
[0x90/2] = 0xd0f2,
|
||||
[0x92/2] = 0xe7d0,
|
||||
[0x94/2] = 0x2481,
|
||||
[0x96/2] = 0x4252,
|
||||
[0x98/2] = 0x402a,
|
||||
[0x9a/2] = 0x1aad,
|
||||
[0x9c/2] = 0x00e4,
|
||||
[0x9e/2] = 0x604c,
|
||||
[0xa0/2] = 0x0892,
|
||||
[0xa2/2] = 0x6075,
|
||||
[0xa4/2] = 0x3a01,
|
||||
[0xa6/2] = 0xd308,
|
||||
[0xa8/2] = 0x689c,
|
||||
[0xaa/2] = 0x1d25,
|
||||
[0xac/2] = 0x609d,
|
||||
[0xae/2] = 0x6825,
|
||||
[0xb0/2] = 0x681c,
|
||||
[0xb2/2] = 0x1d26,
|
||||
[0xb4/2] = 0x601e,
|
||||
[0xb6/2] = 0x6025,
|
||||
[0xb8/2] = 0xe7f4,
|
||||
[0xba/2] = 0x698a,
|
||||
[0xbc/2] = 0x4202,
|
||||
[0xbe/2] = 0xd0bf,
|
||||
[0xc0/2] = 0xe7b9,
|
||||
[0xc2/2] = 0x46c0,
|
||||
[0xc4/2] = 0x0004, 0x2000,
|
||||
[0xc8/2] = 0xcdef, 0x89ab,
|
||||
[0xcc/2] = 0x0405, 0x0203,
|
||||
[0xd0/2] = 0xaebf, 0x8c9d,
|
||||
[0xd4/2] = 0x1516, 0x1314,
|
||||
[0xd8/2] = 0x0700, 0x0001,
|
||||
|
|
|
@ -31,108 +31,108 @@
|
|||
/* ----- Types */
|
||||
|
||||
enum {
|
||||
STM32Lx_STUB_PHYS = 0x20000000ul,
|
||||
STM32Lx_STUB_INFO_PHYS = 0x20000004ul,
|
||||
STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024),
|
||||
STM32Lx_STUB_DATA_MAX = 2048,
|
||||
STM32Lx_STUB_PHYS = 0x20000000ul,
|
||||
STM32Lx_STUB_INFO_PHYS = 0x20000004ul,
|
||||
STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024),
|
||||
STM32Lx_STUB_DATA_MAX = 2048,
|
||||
|
||||
STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul,
|
||||
STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul,
|
||||
STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul,
|
||||
STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul,
|
||||
|
||||
STM32L0_NVM_PHYS = 0x40022000ul,
|
||||
STM32L0_NVM_PROG_PAGE_SIZE = 128,
|
||||
STM32L0_NVM_DATA_PAGE_SIZE = 4,
|
||||
STM32L0_NVM_OPT_SIZE = 12,
|
||||
STM32L0_NVM_EEPROM_SIZE = 2*1024,
|
||||
STM32L0_NVM_PHYS = 0x40022000ul,
|
||||
STM32L0_NVM_PROG_PAGE_SIZE = 128,
|
||||
STM32L0_NVM_DATA_PAGE_SIZE = 4,
|
||||
STM32L0_NVM_OPT_SIZE = 12,
|
||||
STM32L0_NVM_EEPROM_SIZE = 2*1024,
|
||||
|
||||
STM32L1_NVM_PHYS = 0x40023c00ul,
|
||||
STM32L1_NVM_PROG_PAGE_SIZE = 256,
|
||||
STM32L1_NVM_DATA_PAGE_SIZE = 4,
|
||||
STM32L1_NVM_OPT_SIZE = 32,
|
||||
STM32L1_NVM_EEPROM_SIZE = 16*1024,
|
||||
STM32L1_NVM_PHYS = 0x40023c00ul,
|
||||
STM32L1_NVM_PROG_PAGE_SIZE = 256,
|
||||
STM32L1_NVM_DATA_PAGE_SIZE = 4,
|
||||
STM32L1_NVM_OPT_SIZE = 32,
|
||||
STM32L1_NVM_EEPROM_SIZE = 16*1024,
|
||||
|
||||
STM32Lx_NVM_PEKEY1 = 0x89abcdeful,
|
||||
STM32Lx_NVM_PEKEY2 = 0x02030405ul,
|
||||
STM32Lx_NVM_PRGKEY1 = 0x8c9daebful,
|
||||
STM32Lx_NVM_PRGKEY2 = 0x13141516ul,
|
||||
STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul,
|
||||
STM32Lx_NVM_OPTKEY2 = 0x24252627ul,
|
||||
STM32Lx_NVM_PEKEY1 = 0x89abcdeful,
|
||||
STM32Lx_NVM_PEKEY2 = 0x02030405ul,
|
||||
STM32Lx_NVM_PRGKEY1 = 0x8c9daebful,
|
||||
STM32Lx_NVM_PRGKEY2 = 0x13141516ul,
|
||||
STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul,
|
||||
STM32Lx_NVM_OPTKEY2 = 0x24252627ul,
|
||||
|
||||
STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18),
|
||||
STM32Lx_NVM_PECR_ERRIE = (1<<17),
|
||||
STM32Lx_NVM_PECR_EOPIE = (1<<16),
|
||||
STM32Lx_NVM_PECR_FPRG = (1<<10),
|
||||
STM32Lx_NVM_PECR_ERASE = (1<< 9),
|
||||
STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */
|
||||
STM32Lx_NVM_PECR_DATA = (1<< 4),
|
||||
STM32Lx_NVM_PECR_PROG = (1<< 3),
|
||||
STM32Lx_NVM_PECR_OPTLOCK = (1<< 2),
|
||||
STM32Lx_NVM_PECR_PRGLOCK = (1<< 1),
|
||||
STM32Lx_NVM_PECR_PELOCK = (1<< 0),
|
||||
STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18),
|
||||
STM32Lx_NVM_PECR_ERRIE = (1<<17),
|
||||
STM32Lx_NVM_PECR_EOPIE = (1<<16),
|
||||
STM32Lx_NVM_PECR_FPRG = (1<<10),
|
||||
STM32Lx_NVM_PECR_ERASE = (1<< 9),
|
||||
STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */
|
||||
STM32Lx_NVM_PECR_DATA = (1<< 4),
|
||||
STM32Lx_NVM_PECR_PROG = (1<< 3),
|
||||
STM32Lx_NVM_PECR_OPTLOCK = (1<< 2),
|
||||
STM32Lx_NVM_PECR_PRGLOCK = (1<< 1),
|
||||
STM32Lx_NVM_PECR_PELOCK = (1<< 0),
|
||||
|
||||
STM32Lx_NVM_SR_FWWERR = (1<<17),
|
||||
STM32Lx_NVM_SR_NOTZEROERR = (1<<16),
|
||||
STM32Lx_NVM_SR_RDERR = (1<<13),
|
||||
STM32Lx_NVM_SR_OPTVER = (1<<11),
|
||||
STM32Lx_NVM_SR_SIZERR = (1<<10),
|
||||
STM32Lx_NVM_SR_PGAERR = (1<<9),
|
||||
STM32Lx_NVM_SR_WRPERR = (1<<8),
|
||||
STM32Lx_NVM_SR_READY = (1<<3),
|
||||
STM32Lx_NVM_SR_HWOFF = (1<<2),
|
||||
STM32Lx_NVM_SR_EOP = (1<<1),
|
||||
STM32Lx_NVM_SR_BSY = (1<<0),
|
||||
STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR
|
||||
| STM32Lx_NVM_SR_PGAERR
|
||||
| STM32Lx_NVM_SR_SIZERR
|
||||
| STM32Lx_NVM_SR_NOTZEROERR),
|
||||
STM32Lx_NVM_SR_FWWERR = (1<<17),
|
||||
STM32Lx_NVM_SR_NOTZEROERR = (1<<16),
|
||||
STM32Lx_NVM_SR_RDERR = (1<<13),
|
||||
STM32Lx_NVM_SR_OPTVER = (1<<11),
|
||||
STM32Lx_NVM_SR_SIZERR = (1<<10),
|
||||
STM32Lx_NVM_SR_PGAERR = (1<<9),
|
||||
STM32Lx_NVM_SR_WRPERR = (1<<8),
|
||||
STM32Lx_NVM_SR_READY = (1<<3),
|
||||
STM32Lx_NVM_SR_HWOFF = (1<<2),
|
||||
STM32Lx_NVM_SR_EOP = (1<<1),
|
||||
STM32Lx_NVM_SR_BSY = (1<<0),
|
||||
STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR
|
||||
| STM32Lx_NVM_SR_PGAERR
|
||||
| STM32Lx_NVM_SR_SIZERR
|
||||
| STM32Lx_NVM_SR_NOTZEROERR),
|
||||
|
||||
STM32L0_NVM_OPTR_BOOT1 = (1<<31),
|
||||
STM32L0_NVM_OPTR_WDG_SW = (1<<20),
|
||||
STM32L0_NVM_OPTR_WPRMOD = (1<<8),
|
||||
STM32L0_NVM_OPTR_RDPROT_S = (0),
|
||||
STM32L0_NVM_OPTR_RDPROT_M = (0xff),
|
||||
STM32L0_NVM_OPTR_RDPROT_0 = (0xaa),
|
||||
STM32L0_NVM_OPTR_RDPROT_2 = (0xcc),
|
||||
STM32L0_NVM_OPTR_BOOT1 = (1<<31),
|
||||
STM32L0_NVM_OPTR_WDG_SW = (1<<20),
|
||||
STM32L0_NVM_OPTR_WPRMOD = (1<<8),
|
||||
STM32L0_NVM_OPTR_RDPROT_S = (0),
|
||||
STM32L0_NVM_OPTR_RDPROT_M = (0xff),
|
||||
STM32L0_NVM_OPTR_RDPROT_0 = (0xaa),
|
||||
STM32L0_NVM_OPTR_RDPROT_2 = (0xcc),
|
||||
|
||||
STM32L1_NVM_OPTR_nBFB2 = (1<<23),
|
||||
STM32L1_NVM_OPTR_nRST_STDBY = (1<<22),
|
||||
STM32L1_NVM_OPTR_nRST_STOP = (1<<21),
|
||||
STM32L1_NVM_OPTR_WDG_SW = (1<<20),
|
||||
STM32L1_NVM_OPTR_BOR_LEV_S = (16),
|
||||
STM32L1_NVM_OPTR_BOR_LEV_M = (0xf),
|
||||
STM32L1_NVM_OPTR_SPRMOD = (1<<8),
|
||||
STM32L1_NVM_OPTR_RDPROT_S = (0),
|
||||
STM32L1_NVM_OPTR_RDPROT_M = (0xff),
|
||||
STM32L1_NVM_OPTR_RDPROT_0 = (0xaa),
|
||||
STM32L1_NVM_OPTR_RDPROT_2 = (0xcc),
|
||||
STM32L1_NVM_OPTR_nBFB2 = (1<<23),
|
||||
STM32L1_NVM_OPTR_nRST_STDBY = (1<<22),
|
||||
STM32L1_NVM_OPTR_nRST_STOP = (1<<21),
|
||||
STM32L1_NVM_OPTR_WDG_SW = (1<<20),
|
||||
STM32L1_NVM_OPTR_BOR_LEV_S = (16),
|
||||
STM32L1_NVM_OPTR_BOR_LEV_M = (0xf),
|
||||
STM32L1_NVM_OPTR_SPRMOD = (1<<8),
|
||||
STM32L1_NVM_OPTR_RDPROT_S = (0),
|
||||
STM32L1_NVM_OPTR_RDPROT_M = (0xff),
|
||||
STM32L1_NVM_OPTR_RDPROT_0 = (0xaa),
|
||||
STM32L1_NVM_OPTR_RDPROT_2 = (0xcc),
|
||||
|
||||
};
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
||||
namespace STM32 {
|
||||
struct NVM {
|
||||
volatile uint32_t acr;
|
||||
volatile uint32_t pecr;
|
||||
volatile uint32_t pdkeyr;
|
||||
volatile uint32_t pkeyr;
|
||||
volatile uint32_t prgkeyr;
|
||||
volatile uint32_t optkeyr;
|
||||
volatile uint32_t sr;
|
||||
volatile uint32_t optr;
|
||||
volatile uint32_t wrprot;
|
||||
struct NVM {
|
||||
volatile uint32_t acr;
|
||||
volatile uint32_t pecr;
|
||||
volatile uint32_t pdkeyr;
|
||||
volatile uint32_t pkeyr;
|
||||
volatile uint32_t prgkeyr;
|
||||
volatile uint32_t optkeyr;
|
||||
volatile uint32_t sr;
|
||||
volatile uint32_t optr;
|
||||
volatile uint32_t wrprot;
|
||||
|
||||
static constexpr uint32_t PKEY1 = 0x89abcdef;
|
||||
static constexpr uint32_t PKEY2 = 0x02030405;
|
||||
static constexpr uint32_t PRGKEY1 = 0x8c9daebf;
|
||||
static constexpr uint32_t PRGKEY2 = 0x13141516;
|
||||
static constexpr uint32_t OPTKEY1 = 0xfbead9c8;
|
||||
static constexpr uint32_t OPTKEY2 = 0x24252627;
|
||||
static constexpr uint32_t PDKEY1 = 0x04152637;
|
||||
static constexpr uint32_t PDKEY2 = 0xfafbfcfd;
|
||||
};
|
||||
static constexpr uint32_t PKEY1 = 0x89abcdef;
|
||||
static constexpr uint32_t PKEY2 = 0x02030405;
|
||||
static constexpr uint32_t PRGKEY1 = 0x8c9daebf;
|
||||
static constexpr uint32_t PRGKEY2 = 0x13141516;
|
||||
static constexpr uint32_t OPTKEY1 = 0xfbead9c8;
|
||||
static constexpr uint32_t OPTKEY2 = 0x24252627;
|
||||
static constexpr uint32_t PDKEY1 = 0x04152637;
|
||||
static constexpr uint32_t PDKEY2 = 0xfafbfcfd;
|
||||
};
|
||||
|
||||
static_assert(sizeof (NVM) == 9*4, "NVM size error");
|
||||
static_assert(sizeof (NVM) == 9*4, "NVM size error");
|
||||
}
|
||||
using stm32lx_stub_pointer_t = uint32_t*;
|
||||
|
||||
|
@ -140,16 +140,18 @@ using stm32lx_stub_pointer_t = uint32_t*;
|
|||
#define Info (*reinterpret_cast<stm32lx_nvm_stub_info*>(STM32Lx_STUB_INFO_PHYS))
|
||||
|
||||
namespace {
|
||||
inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) {
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock
|
||||
nvm.pkeyr = STM32::NVM::PKEY1;
|
||||
nvm.pkeyr = STM32::NVM::PKEY2;
|
||||
nvm.prgkeyr = STM32::NVM::PRGKEY1;
|
||||
nvm.prgkeyr = STM32::NVM::PRGKEY2;
|
||||
return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK);
|
||||
}
|
||||
inline __attribute((always_inline)) void lock (STM32::NVM& nvm) {
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PELOCK; }
|
||||
inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) {
|
||||
// Lock guarantees unlock
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PELOCK;
|
||||
|
||||
nvm.pkeyr = STM32::NVM::PKEY1;
|
||||
nvm.pkeyr = STM32::NVM::PKEY2;
|
||||
nvm.prgkeyr = STM32::NVM::PRGKEY1;
|
||||
nvm.prgkeyr = STM32::NVM::PRGKEY2;
|
||||
return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK);
|
||||
}
|
||||
inline __attribute((always_inline)) void lock (STM32::NVM& nvm) {
|
||||
nvm.pecr = STM32Lx_NVM_PECR_PELOCK; }
|
||||
|
||||
}
|
||||
|
||||
|
@ -158,15 +160,15 @@ namespace {
|
|||
typedef uint32_t stm32lx_stub_pointer_t;
|
||||
|
||||
struct stm32lx_nvm {
|
||||
volatile uint32_t acr;
|
||||
volatile uint32_t pecr;
|
||||
volatile uint32_t pdkeyr;
|
||||
volatile uint32_t pekeyr;
|
||||
volatile uint32_t prgkeyr;
|
||||
volatile uint32_t optkeyr;
|
||||
volatile uint32_t sr;
|
||||
volatile uint32_t optr; /* or obr */
|
||||
volatile uint32_t wrprot; /* or wprot1 */
|
||||
volatile uint32_t acr;
|
||||
volatile uint32_t pecr;
|
||||
volatile uint32_t pdkeyr;
|
||||
volatile uint32_t pekeyr;
|
||||
volatile uint32_t prgkeyr;
|
||||
volatile uint32_t optkeyr;
|
||||
volatile uint32_t sr;
|
||||
volatile uint32_t optr; /* or obr */
|
||||
volatile uint32_t wrprot; /* or wprot1 */
|
||||
};
|
||||
|
||||
#define STM32Lx_NVM(p) (*(struct stm32lx_nvm*) (p))
|
||||
|
@ -180,16 +182,16 @@ struct stm32lx_nvm {
|
|||
#endif
|
||||
|
||||
enum {
|
||||
OPT_STM32L1 = 1<<1,
|
||||
OPT_STM32L1 = 1<<1,
|
||||
};
|
||||
|
||||
struct stm32lx_nvm_stub_info {
|
||||
stm32lx_stub_pointer_t destination;
|
||||
int32_t size;
|
||||
stm32lx_stub_pointer_t source;
|
||||
uint32_t nvm;
|
||||
uint16_t page_size;
|
||||
uint16_t options;
|
||||
stm32lx_stub_pointer_t destination;
|
||||
int32_t size;
|
||||
stm32lx_stub_pointer_t source;
|
||||
uint32_t nvm;
|
||||
uint16_t page_size;
|
||||
uint16_t options;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* ----- Globals */
|
||||
|
|
1436
src/stm32l0.c
1436
src/stm32l0.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue