Merge pull request #75 from beewoolie/stm32lx-whole
STM32Lx target support.
This commit is contained in:
commit
51f91092e7
|
@ -1,5 +1,19 @@
|
||||||
These are the assembler routines for executing a flash write
|
Flash Stubs
|
||||||
on the supported targets. They are kept here for reference, but
|
===========
|
||||||
are not used, as the compiled binary code is included in the
|
|
||||||
target drivers.
|
|
||||||
|
|
||||||
|
For most of the targets, these are assembler routines for executing
|
||||||
|
a flash write on the supported targets. They are kept here for
|
||||||
|
reference, but are not used, as the compiled binary code is included
|
||||||
|
in the target drivers.
|
||||||
|
|
||||||
|
For the STM32l0x, the stubs are written in C++ and emitted as arrays
|
||||||
|
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.
|
||||||
|
|
|
@ -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,/"
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* @file stm32l05x-nvm-prog-erase.cc
|
||||||
|
*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Woollysoft
|
||||||
|
* Written by Marc Singer <elf@woollysoft.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -----------
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
|
||||||
|
NVM program flash erase stub for STM32L05x, a Cortex-M0+ core. The
|
||||||
|
stub uses SRAM to host the code fragment to perform the erase.
|
||||||
|
|
||||||
|
This stub works with the STM32L1xx given a few options.
|
||||||
|
|
||||||
|
If you plan to modify this routine and emit a new stub, make sure
|
||||||
|
to audit the code. We don't have a stack so we cannot make calls
|
||||||
|
that save the link pointer. IOW, the inline functions should be be
|
||||||
|
inlined.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../src/include/stm32lx-nvm.h"
|
||||||
|
|
||||||
|
/* 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:");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!unlock(nvm))
|
||||||
|
goto quit;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
while (Info.size > 0) {
|
||||||
|
*Info.destination = 0; // Initiate erase
|
||||||
|
|
||||||
|
Info.destination += Info.page_size/sizeof (*Info.destination);
|
||||||
|
Info.size -= Info.page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
quit:
|
||||||
|
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 -d -z stm32l05x-nvm-prog-erase.o | ./dump-to-array.sh > stm32l05x-nvm-prog-erase.stub"
|
||||||
|
End:
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,67 @@
|
||||||
|
[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,
|
|
@ -0,0 +1,113 @@
|
||||||
|
/* @file stm32l05x-nvm-prog-write.cc
|
||||||
|
*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Woollysoft
|
||||||
|
* Written by Marc Singer <elf@woollysoft.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -----------
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
|
||||||
|
NVM program flash writing stub for STM32L05x, a Cortex-M0+ core.
|
||||||
|
The stub uses SRAM to host the code fragment and source data to
|
||||||
|
perform a write to flash.
|
||||||
|
|
||||||
|
This stub works with the STM32L1xx given a few options.
|
||||||
|
|
||||||
|
If you plan to modify this routine and emit a new stub, make sure
|
||||||
|
to audit the code. We don't have a stack so we cannot make calls
|
||||||
|
that save the link pointer. IOW, the inline functions should be be
|
||||||
|
inlined.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../src/include/stm32lx-nvm.h"
|
||||||
|
|
||||||
|
/* 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() {
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
if (!unlock(nvm))
|
||||||
|
goto quit;
|
||||||
|
|
||||||
|
nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quit:
|
||||||
|
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 -d -z stm32l05x-nvm-prog-write.o | ./dump-to-array.sh > stm32l05x-nvm-prog-write.stub"
|
||||||
|
End:
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,99 @@
|
||||||
|
[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,
|
|
@ -41,6 +41,7 @@ SRC = \
|
||||||
samd.c \
|
samd.c \
|
||||||
stm32f1.c \
|
stm32f1.c \
|
||||||
stm32f4.c \
|
stm32f4.c \
|
||||||
|
stm32l0.c \
|
||||||
stm32l1.c \
|
stm32l1.c \
|
||||||
swdptap.c \
|
swdptap.c \
|
||||||
target.c \
|
target.c \
|
||||||
|
|
|
@ -251,6 +251,7 @@ cortexm_probe(struct target_s *target)
|
||||||
|
|
||||||
PROBE(stm32f1_probe);
|
PROBE(stm32f1_probe);
|
||||||
PROBE(stm32f4_probe);
|
PROBE(stm32f4_probe);
|
||||||
|
PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */
|
||||||
PROBE(stm32l1_probe);
|
PROBE(stm32l1_probe);
|
||||||
PROBE(lpc11xx_probe);
|
PROBE(lpc11xx_probe);
|
||||||
PROBE(lpc43xx_probe);
|
PROBE(lpc43xx_probe);
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
/* @file stm32lx-nvm.h
|
||||||
|
*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Woollysoft
|
||||||
|
* Written by Marc Singer <elf@woollysoft.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined (STM32Lx_NVM_H_INCLUDED)
|
||||||
|
# define STM32Lx_NVM_H_INCLUDED
|
||||||
|
|
||||||
|
/* ----- Includes */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* ----- Macros */
|
||||||
|
|
||||||
|
/* ----- Types */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
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,
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
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_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),
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
using stm32lx_stub_pointer_t = uint32_t*;
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
// 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; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STM32Lx_NVM(p) (*(struct stm32lx_nvm*) (p))
|
||||||
|
#define STM32Lx_NVM_PECR(p) ((uint32_t) &STM32Lx_NVM(p).pecr)
|
||||||
|
#define STM32Lx_NVM_PEKEYR(p) ((uint32_t) &STM32Lx_NVM(p).pekeyr)
|
||||||
|
#define STM32Lx_NVM_PRGKEYR(p) ((uint32_t) &STM32Lx_NVM(p).prgkeyr)
|
||||||
|
#define STM32Lx_NVM_OPTKEYR(p) ((uint32_t) &STM32Lx_NVM(p).optkeyr)
|
||||||
|
#define STM32Lx_NVM_SR(p) ((uint32_t) &STM32Lx_NVM(p).sr)
|
||||||
|
#define STM32Lx_NVM_OPTR(p) ((uint32_t) &STM32Lx_NVM(p).optr)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
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;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* ----- Globals */
|
||||||
|
|
||||||
|
/* ----- Prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STM32Lx_NVM_H_INCLUDED */
|
|
@ -216,6 +216,7 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na
|
||||||
bool cortexm_probe(struct target_s *target);
|
bool cortexm_probe(struct target_s *target);
|
||||||
bool stm32f1_probe(struct target_s *target);
|
bool stm32f1_probe(struct target_s *target);
|
||||||
bool stm32f4_probe(struct target_s *target);
|
bool stm32f4_probe(struct target_s *target);
|
||||||
|
bool stm32l0_probe(struct target_s *target);
|
||||||
bool stm32l1_probe(struct target_s *target);
|
bool stm32l1_probe(struct target_s *target);
|
||||||
bool lmi_probe(struct target_s *target);
|
bool lmi_probe(struct target_s *target);
|
||||||
bool lpc11xx_probe(struct target_s *target);
|
bool lpc11xx_probe(struct target_s *target);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue