The STM32F2 micro-controller has build in capabilities to prevent readout of application code using a debug interface. It works fine and is accomplished pretty easily by configuring the read protection(RDP) level to '1' (!0xAA || !0xCC) or '2' (0xCC which is irreversible). Except trying to turn it off is where i run in to issues.
The expected behavior when the RDP level is lowered back to 0:
The chip will perform a mass flash erase.
Followed by clearing the protection flag.
System reset
Except after a power cycle the flash has been successfully erased but the protection flag remains on level '1' (0x55) keeping the debug interface disabled. And thus preventing me from writing any new application code. It is possible to fiddle around with the debugger and force the flag to level 0 (0xAA) manually though..
Is there anyone who have had the same or similar issues with the STM32F2xx series that can help me out? I'm using the STM32 standard peripheral drivers for programming the flash.
Enable
// Enable read out protection
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_1);
FLASH_OB_Launch();
FLASH_OB_Lock();
// Restart platform
NVIC_SystemReset();
Disable
// Disable read out protection
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_0);
FLASH_OB_Launch();
FLASH_OB_Lock();
// Restart platform
NVIC_SystemReset();
This is because before the clearing the protection flag, and in the middle of mass flash erase, you restart the chip.
The only way to recover the chip is to use the system bootloader.
Force boot0 pin to be 1 and force boot1 pin to be 0 at power up, start bootloader then connect USB and program the chip with DFU programmer.
You can download the DFU programmer here.
I used the library as follows (it was not working without FLASH_Unlock();):
// Flash Readout Protection Level 1
if (FLASH_OB_GetRDP() != SET) {
FLASH_Unlock(); // this line is critical!
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_1);
FLASH_OB_Launch(); // Option Bytes programming
FLASH_OB_Lock();
FLASH_Lock();
}
No need for NVIC_SystemReset();.
Checking functionality worked best with STM32 ST-LINK utility CLI for me:
> "C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe" -c SWD -rOB
STM32 ST-LINK CLI v3.0.0.0
STM32 ST-LINK Command Line Interface
ST-LINK SN : 51FF6D064989525019422287
ST-LINK Firmware version : V2J27S0
Connected via SWD.
SWD Frequency = 4000K.
Target voltage = 2.9 V.
Connection mode : Normal.
Device ID:0x422
Device flash Size : 256 Kbytes
Device family :STM32F302xB-xC/F303xB-xC/F358xx
Option bytes:
RDP : Level 1
IWDG_SW : 1
nRST_STOP : 1
nRST_STDBY : 1
nBoot1 : 1
VDDA : 1
Data0 : 0xFF
Data1 : 0xFF
nSRAM_Parity: 1
WRP : 0xFFFFFFFF
Not really a solution, but I hope this saves someone some time.
Related
I have a nucleo-144 board with stm32f746zg MCU. I'm trying to program the board with openocd, using gnu make and the makefile generated from stm32cubemx. I've added following line to my makefile to automate the flashing process:
flash: all
openocd -f interface/stlink.cfg -f target/stm32f7x.cfg -c "program $(BUILD_DIR)/$(TARGET).elf verify reset exit"
The code compiles without any problem and when I type make flash in the terminal the result is:
❯ make flash
openocd -f interface/stlink.cfg -f target/stm32f7x.cfg -c "program build/my-board.elf verify reset exit"
Open On-Chip Debugger 0.11.0 (2021-11-18) [https://github.com/sysprogs/openocd]
Licensed under GNU GPL v2
libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : DEPRECATED target event trace-config; use TPIU events {pre,post}-{enable,disable}
Info : clock speed 2000 kHz
Error: libusb_open() failed with LIBUSB_ERROR_NOT_SUPPORTED
Info : STLINK V2J33M25 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.236769
Info : stm32f7x.cpu: Cortex-M7 r0p1 processor detected
Warn : Silicon bug: single stepping may enter pending exception handler!
Info : stm32f7x.cpu: target has 8 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f7x.cpu on 3333
Error: couldn't bind gdb to socket on port 3333: No error
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08002a18 msp: 0x20050000
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
** Programming Started **
Info : device id = 0x10016449
Info : flash size = 1024 kbytes
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
shutdown command invoked
But the program doesn't run on the board and there's no blinking. I tried this in windows and wsl ubuntu. In both cases the results are the same. Also tried loading the binary file instead of .elf but again no luck.
Can somebody tell me what am I doing wrong here?
Ok. I'm not sure if I should post this as an answer, but the problem wasn't either openocd or the broken hardware.
When I started the project in cubemx, I initialized the default nucleo-f746zg peripherals and for some reason (probably one of the peripherals need higher clock frequency to work properly) in clock configuration the default clock source is selected as HSE and this option cannot be changed. On the other hand the nucleo board doesn't come with an external oscillator and it should be soldered by the user. So after generating the code and flashing it to the board it causes an error and the program doesn't run. Although, I think there was a block of code in clock configuration of HAL libraries that would "try" to use HSE and PLL as clock source and in case of not responding or any problem in settings, the HSI would be used as default source.
Anyway when I start the project from MCU selector in cubemx and don't use nucleo initializations, I can set the clock to HSI and everything works fine.
I have ordered the black pill ( STM32F411CEU6, real ones ) to replace my blue pill dev kits that didn't have enough RAM and have had nothing but issues getting it going. I have generated the project using STM32CubeIDE.
I'm using A11, 12, 13 for GPIO output and PB9, 8 for I2C communication, and A10, 11 for my USART device.
I am able to get the st link programmer and software to detect my black pill and debug for a short duration until I enter MX_GPIO_Init()
After this the programmer loses communication with the device and prevents me from doing any real programming. Some places I have looked says to try to set the Sys -> Debug setting to "Serial Wire" but this is disabled by default for me and am unable to switch it.
In context of debugging when I do debug in live mode I can see a debug enabled
Starting server with the following options:
Persistent Mode : Disabled
Logging Level : 1
Listen Port Number : 61234
Status Refresh Delay : 15s
Verbose Mode : Disabled
SWD Debug : Enabled
InitWhile : Enabled
So the debugging looks like it's set up properly but I just don't understand why it can't call the init for the GPIO from looking at the debug console I get this
handle_vCont_c, Failed continue thread
which is thrown after entering this function
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
which doesn't make a whole lot of sense to me as I have not seen this before, can someone please help me out setting up this project properly? thanks.
The serial wire debug interface is defined for PA13 and PA14. In CubeMx IDE, first set SYS->Debug->Serial Wire. Select another pin for GPIO instead of PA13.
I'm busy bring up some new hardware with a STM32F030C8 mcu. I'm using the STM32CubeIDE with gcc. I'm very new to microcontroller development and this is my first project with ST and their tools.
This is a very basic program that just triggers a GPIO. The rest is all generated code. As I have very little experience in this field I hope somebody can point to a location where I can look. I suspect that it might be a configuration issue.
Here is the code (I removed all generated comments to keep it a bit more compact):
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2); //my code 1
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2); //my code 2
while (1)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
HAL_Delay(1000);
}
}
When I step through the code It will trigger the GPIO on "my code 1" once I step to "my code 2" it will cause the issue. I have even tried just running a fully generated program with no modifications and the issue persists. This was a quick test to see if the program actually does run on the mcu. And it does, as well as trigger the GPIO.
Debugger console Output:
Temporary breakpoint 1, main () at ../Core/Src/main.c:74
74 HAL_Init();
Program received signal SIGTRAP, Trace/breakpoint trap.
0x1fffecec in ?? ()
The Temporary breakpoint is where the program starts, I can then either run from there. Or step through, all with the same result.
Console Output:
Waiting for debugger connection...
Debugger connected
-------------------------------------------------------------------
STM32CubeProgrammer v2.4.0
-------------------------------------------------------------------
ST-LINK SN : 34FF6E065250343816210143
ST-LINK FW : V2J36S7
Voltage : 3.22V
SWD freq : 4000 KHz
Connect mode: Under Reset
Reset mode : Hardware reset
Device ID : 0x440
Device name : STM32F05x/F030x8
Flash size : 64 KBytes
Device type : MCU
Device CPU : Cortex-M0
Memory Programming ...
Opening and parsing file: ST-LINK_GDB_server_PEkdAh.srec
File : ST-LINK_GDB_server_PEkdAh.srec
Size : 4944 Bytes
Address : 0x08000000
Erasing memory corresponding to segment 0:
Erasing internal memory sectors [0 4]
Download in Progress:
File download complete
Time elapsed during download operation: 00:00:00.627
Verifying ...
Download verified successfully
Full Error:
Break at address "0x1fffecec" with no debug information available, or outside of program code.
Here is two images that might help. As I mention I'm very new to this. So any other information required please ask. Thanks in advance.
Debug View
Disassembly
The code is placed at 0x08000000. There is no user code at 0x1fffecec. It system area and probably it boots the system bootloader. It shows that the BOOTx pin is incorrectly connected.
I want to pass sine wave data onto a pin (any possible one), so that my program would be able to read it when being run in an emulator.
How how can I pass data in the form of (time:value) or just pass a function float generatorForPinX(int time); to act as signal generator into the GNU ARM Eclipse (I use QEMU but if any other emulator is required I am willing to migrate) board emulator?
These instructions are for emulating an Olimex STM32 P103 Development Kit.
Download and build
First download and build Qemu STM32, which includes patches for emulating the ADC peripheral on the STM32:
wget https://github.com/beckus/qemu_stm32/archive/stm32.tar.gz
tar xf stm32.tar.gz
cd qemu_stm32-stm32
./configure --target-list="arm-softmmu"
make
cd ..
If the configure step fails, then install the missing requirements. See the README for more information.
Then download the Olimex STM32 P103 Development Kit Demos:
wget https://github.com/beckus/stm32_p103_demos/archive/master.tar.gz
tar xf master.tar.gz
Look in stm32_p103_demos-master/demos/adc_single/main.c for an example program which uses the ADC.
Run the demo application
To build and run the adc_single demo:
cd stm32_p103_demos-master
QEMU_ARM_DIR=../qemu_stm32-stm32/arm-softmmu/ make adc_single_QEMURUN_TEL
(from another terminal) telnet localhost 7777
UART2 is attached to the telnet server on port 7777, which you should see output from. See the README for more information on how to build and run the demo applications.
Looking at the source for the adc_single demo application, it has 3 different modes:
Mode 1 (the default) will read from the temperature sensor on ADC channel 16
Mode 2 will read the Vdd value from ADC channel 16
Mode 3 will read from ADC channel 8.
The modes can be selected by using a button, but since we are emulating the hardware with QEMU, the button is not available. I switched between the modes by changing the int mode = 1; value and recompiling the program.
ADC emulation
The method that QEMU uses to emulate each ADC channel is viewable in the stm32_adc_start_conv function in hw/arm/stm32_adc.c:
static void stm32_adc_start_conv(Stm32Adc *s)
{
uint64_t curr_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int channel_number=stm32_ADC_get_channel_number(s,1);
// Write result of conversion
if(channel_number==16){
s->Vdda=rand()%(1200+1) + 2400; //Vdda belongs to the interval [2400 3600] mv
s->Vref=rand()%(s->Vdda-2400+1) + 2400; //Vref belongs to the interval [2400 Vdda] mv
s->ADC_DR= s->Vdda - s->Vref;
}
else if(channel_number==17){
s->ADC_DR= (s->Vref=rand()%(s->Vdda-2400+1) + 2400); //Vref [2400 Vdda] mv
}
else{
s->ADC_DR=((int)(1024.*(sin(2*M_PI*qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)/1e9)+1.))&0xfff);
}
s->ADC_SR&=~ADC_SR_EOC; // jmf : indicates ongoing conversion
// calls conv_complete when expires
timer_mod(s->conv_timer, curr_time + stm32_ADC_get_nbr_cycle_per_sample(s,channel_number));
}
As you can see, ADC channel 16 will emulate a random Vdd input, ADC channel 17 will emulate a random temperature input, and all other channels will follow a sine wave from 0 to 2048. Here is a graph of the ADC values returned from all 3 modes:
If you want to have an ADC channel use a different emulation pattern, you can modify stm32_adc_start_conv and rebuild QEMU following the steps above.
This question may be so obvious it is stupid but I am failing to come up with an answer for it.
I am trying to make a simple makefile project for the sam4s xplained board from Atmel.
I am new to ARM and am feeling a bit lost in how to get stuff to work. Here is what I do trying to get the LEDs to work:
/* Enable clock for PIOC. */
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
PMC->PMC_PCER0 = PMC_PCER0_PID13; /* PIOC clock enable. */
/* Enable output for LED. */
PIOC->PIO_WPMR = PIO_WPMR_WPKEY_PASSWD; /* Enable writing to registers. */
PIOC->PIO_PER = PIO_PER_P10 | PIO_PER_P17; /* Enable pio 10, 17. */
PIOC->PIO_OER = PIO_OER_P10 | PIO_OER_P17; /* Set pio10 and 17 as output. */
PIOC->PIO_SODR = PIO_SODR_P10; /* Set pio10. */
PIOC->PIO_CODR = PIO_CODR_P17; /* Clear pio17 . */
But absolutely nothing happens. Am I missing something?
There should be user LEDs at PIOC 10 and 17.
Board schematics:
http://www.atmel.com/webdoc/sam4s16xplained/sam4s16xplained.boardScematics.section_ggo_tyg_xf.html
The problem was not in the code but in Atmel's tools used to program the board. I had been using SAM-BA In-system Programmer to program the board but for some reason it failed to change the contents of the flash. Even setting a single manually in the memory view fails.
I instead tried Seggers JLink software and did the following steps:
Update the JLink driver on the board using Atmel Studio 6 (this step requires windows).
Downloaded the J-Link software package for Linux from Segger: https://www.segger.com/jlink-software.html.
Using JLinkExe to program the board, like so:
Make sure JP25 is disconnected - only needed for sam-ba.
Connect via usb with the jtag connector.
Start JLinkExe
In the JLink terminal do:
JLink> device at91sam4s16c
JLink> loadbin <target.bin>, 0x400000
Sometimes I need to reset the board before it works after programming it. Using the Segger tools debugging also works now. Start gdb server with JLinkGDBServer and connect with arm-none-eabi-gdb using:
(gdb) target remote :2331
(gdb) file <target.elf>