Application not loading after DFU:Leave - stm32

I am trying to program the STM32F401 flash on our board in DFU mode. I am using the dfu-util tool in my linux computer.For my project requirements the BOOT 0 pin is always kept high throughout the process.
I am using the following command to flash and jump to application code.
dfu-util -a 0 -s 0x08000000:leave -D <location-to-binary>.bin
After the flashing is done I can see through 'lsusb' command that sometimes the MCU is not out of DFU boot loader, and sometimes out of it. Either way the application does not start.
When I further try to use the leave command when it's in bootloader, it shows the following log and the above situation continues,
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
Opening DFU capable USB device...
Device ID 0483:df11
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(10) = dfuERROR, status(10) = Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations
Clearing status
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash "
DfuSe command mode
Submitting leave request...
Transitioning to dfuMANIFEST state
Thanks in advance for any advice or help.

I found the issue. I had to uncomment the define USER_VECT_TAB_ADDRESS in the system_stm32f4xx.c file.
Basically what was happening was that bootloader was looking for a loadable vector address from the flash application. With the USER_VECT_TAB_ADDRESS commented the pointer to the vector address kept pointing to the bootloader vector table effectively crashing the flash application resetting the controller. With the BOOT 0 pin high it kept loading into bootloader with each reset.
More information about this is available in this similar question:
STM32G474 bootloader exit

Related

How can I debug program startup on an STM32F205?

I have an embedded board with an STM32 microcontroller, and an ST-Link v2. This setup generally works: I can program the flash, and connect with ST's CubeProgrammer tool or with openocd. I can attach gdb to the latter, and step through code. So far, so good. It does not appear there is any problem with my physical or electrical setup.
I have a program which is... not so good. Something early in initialization is hanging up the chip to the point where I can no longer connect to it with any tools. I can rescue it by using the "Under reset" mode of CubeProgrammer, holding the reset switch on the board at boot, then connecting before the bad program can wedge the chip.
After connecting this way, the chip is halted. I can flash a known good program. Or, I can use the MCU core screen of CubeProgrammer to "Step" one instruction at a time through the bad program's startup. That works, until I hit "Run", and then I quickly get a dialog "Warning: Connection to device 0x411 is lost", and the chip is no longer usable until I flash it as above. It appears the code is configuring the necessary pins into the alt mode to enable serial wire debugging, so I don't think that's the problem, but it's hard to verify.
So, it appears something in this program is behaving badly. What I'd like to do is set up gdb via openocd to debug startup. With a good program, I can connect with openocd while the program is running, attach gdb, and everything works normally. But I don't know how to get openocd to do what CubeProgrammer does with the "Under reset" mode, so I can execute initialization of the chip under gdb control.
How can I do this? Or, is there some other tool I should be trying than openocd+gdb? I'm familiar with gdb, but I can try other tools. The host environment is macOS.
Create an openOCD config file like this:
#
# stlink to stm32f2xx by swd with system reset and no test reset
#
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f2x.cfg]
reset_config srst_only connect_assert_srst
And use the -f flag to openOCD to use it.

How to setup STM32f103c8T Bluepill + Platformio + UART the right way?

I've been trying to figure out how to upload a code to a STM32103c8T bulepill board.
My setup is
1- MacOs Catalina
2- STM32103c8T bulepill board
3- SLAB UART USB-TTL CP2012 V3.0
4- Platformio IDE
5- STM32 CUBE Programmer software which detects and connects to my board through UART.
meaning that It has no problem connecting but there are issue with setting up the Platformio
BTW I am new to the ARM world and I bought this board to examine its speed and deep sleep and interrupt, I mean all the things that an Arduino Uno can't do.
The thing is I have no idea on how to setup the platformio.ini File to comunicate with the board
using the UART method and not requesting ST-link dongle!
What I have now in Platformio.ini is:
[env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
framework = arduino
upload_protocol = stlink
upload_port = tty.slab_usbtoUART
and when trying to upload the program i get:
Uploading .pio/build/bluepill_f103c8/firmware.elf
xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-12:31)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 1
hla_swd
none separate
Error: open failed
in procedure 'program'
OpenOCD init failed
shutdown command invoked
[upload] Error 1
I just need help getting the system talk to each-other and see each-other
P.S.
I want to go as bareMetal as possible and not to use arduino firmware HAL
You can use the following configurations:
upload_protocol = serial
upload_port = COMX/ttyx //whichever applies

Regulator configuration for RTC backup battery in i.MX6 PMIC

I'm switching with the phycore i.MX6 som from phytec's dev kit to an own board. The usermanuals for both the som and devkit can be found on phytec's page. Now I want to configure the rtc to keep the time during reboot's and poweroffs.
The battery (in my case supercap) is connected to the VDD_BAT pin of the phycore i.MX6 som (page 10). The internal PMIC is the da9062 connected via the i2c bus which is configured in the som dtsi file as rtc1.
imx6qdl-phytec-phycore-som.dtsi:
...
aliases {
rtc1 = &da9062_rtc;
};
...
&i2c3 {
pmic#58 {
da9062_rtc: rtc {
compatible = "dlg,da9062-rtc";
};
};
};
This file I didn't touch at all.
Next, I told the kernel to take his hwclock and systime time from rtc1 instead of rtc0:
CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
CONFIG_RTC_SYSTOHC_DEVICE="rtc1"
The driver is being loaded correctly as far as I can tell:
dmesg | grep rtc
[ 2.489836] da9063-rtc da9062-rtc: rtc core: registered da9063-rtc as rtc1
[ 2.499713] snvs_rtc 20cc000.snvs:snvs-rtc-lp: rtc core: registered 20cc000.snvs:snvs-rtc-lp as rtc2
[ 3.260348] da9063-rtc da9062-rtc: setting system clock to 2000-01-01 02:37:55 UTC (946694275)
and
cat /sys/class/rtc/rtc1/name
da9063-rtc da9062-rtc
Now, I can set the time via date and transfer it to the hwclock via
hwclock --systohc
.
After rebooting the system and hwclock is set to the previously set date which is fine. After cutting the power the clock gets reset.
I've measured the voltage of the supercap which is around 220mV. The datasheet of the da9062 tells me the chip does have an regulator for the battery which needs to be configured (Table 127: BBAT_CONT (0x0C5)).
As far as I understand the kernel/rtc subsystem, the driver for the rtc should take care of the charging of the battery or provide an userspace interface so I can do it myself. But I can't find anything on this topic.
I am using yocto to build the kernel/image for my board.
Is there something I'm missing or do I need to patch the driver myself in order to charge the supercap? Maybe there's an option in the devicetree to set the charging voltage and current for the cap?
I appreciate any ideas and suggestions, thanks.
Aparently the driver does not support charging a battery/supercap out of the box and it has exclusive access rights to the i2c device address which prevents userspace applications to access the device.
My solution to this problem is to set those values before the driver takes over:
Since this i2c bus is already configured in my barebox devicetree, I can access it before I boot the kernel (provided barebox is compiled with the i2c subsystem enabled in menuconfig). Here I can run a script which sets the BBAT and PD registers to enable charging the supercap.
Though, the cleaner solution would be to extend the driver and provide a userspace interface for this functionality.
Another possible solution I did not investigate would be to check if the driver can be compiled as a module, so I could unload the module, set the registers and load it again.

iMX6: MSI-X not working in Linux PCIe device driver

I'm trying to get MSI-X working on an iMX6 (Freescale/NXP/Qualcomm) CPU in Linux v4.1 for a PCIe character device driver. Whenever I call either pci_enable_msix() or pci_enable_msix_range() or pci_enable_msix_exact() I get an EINVAL value returned. I do have the CONFIG_PCI_MSI option selected in the kernel configuration and I am also able to get single MSI working with pci_enable_msi(), but I cannot get multiple MSI working either.
I have tested my driver code on an Intel i7 running kernel v3 with the same PCIe hardware attached and I was able to get MSI-X working without any problems so I know my code is correctly written and the hardware is correctly functioning.
When running on the iMX6 I can use lspci -v to view that the hardware has MSI-X capabilities and see the number of IRQs it allows. I can even get the same correct number in my driver when calling pci_msix_vec_count().Questions
Are there any other kernel configuration flags I need to set?
Is there anything specific to the iMX6 CPU I need to consider?
Does anyone have any experience with the iMX6 and either MSI-X or
multiple MSI?

STM32 GDB/OpenOCD Commands and Initialization for Flash and Ram Debugging

I am looking for assistance with the proper GDB / OpenOCD initializion and running commands (external tools) to use within Eclipse for flash and RAM debugging, as well as the proper modifications or additions that need to be incorporated in a makefile for flash vs RAM building for this MCU, if this matters of course.
MCU: STM32F103VET6
I am using Eclipse Helios with Zylin Embedded CDT, Yagarto Tools and Bins, OpenOCD 0.4, and have an Olimex ARM-USB-OCD JTAG adapter.
I have already configured the ARM-USB-OCD and added it as an external tool in Eclipse. For initializing OpenOCD I used the following command in Eclipse. The board config file references the stm32 MCU:
openocd -f interface/olimex-arm-usb-ocd-h.cfg -f board/stm32f10x_128k_eval.cfg
When I run this within Eclipse everything appears to be working (GDB Interface, OpenOCD finds the MCU, etc). I can also telnet into OpenOCD and run commands.
So, I am stuck on the next part; initialization and commands for flash and RAM debugging, as well as erasing flash.
I read through several tutorials, and scoured the net, but have not been able to find anything particular to this processor. I am new to this, so I might not be recognizing an equivalent product for an example.
I'm working with the same tool chain to program and debug a STM32F107 board. Following are my observations to get an STM32Fxxx chip programmed and debugged under this toolchain.
Initial Starting Point
So at this point you've got a working OpenOCD to ARM-USB-OCD connection and so you should be all set on that end. Now the work is on getting Eclipse/Zylin/Yagarto GDB combination to properly talk to the STM32Fxxx through the OpenOCD/Olimex connection. One thing to keep in mind is that all the OpenOCD commands to issue are the run mode commands. The configuration scripts and command-line options to invoke the OpenOCD server are configuration mode commands. Once you issue the init command then the server enters run mode which opens up the set of commands you'll need next. You've probably done it somewhere else but I tack on a '-c "init"' option when I call the OpenOCD server like so:
openocd -f /path to scripts/olimex-arm-usb-ocd-h.cfg -f /path to targets/stm32f107.cfg -c "init"
The following commands I issue next are done by the Eclipse Debug Configurations dialogue. Under the Zylin Embedded debug (Native) section, I create a new configuration, give it a name, Project (optional), and absolute path to the binary that I want to program. Under the Debugger tab I set the debugger to Embedded GDB, point to the Yagarto GDB binary path, don't set a GDB command file, set GDB command set to Standard, and the protocol to mi.
The Commands Tab - Connect GDB to OpenOCD
So the next tab is the Commands tab and that's where the meat of the issue lies. You have two spaces Initialize and Run. Not sure exactly what the difference is except to guess that they occur pre- and post-invocation of GDB. Either way I haven't noticed a difference in how my commands are run.
But anyway, following the examples I found on the net, I filled the Initialize box with the following commands:
set remote hardware-breakpoint limit 6
set remote hardware-watchoint-limit 4
target remote localhost:3333
monitor halt
monitor poll
First two lines tell GDB how many breakpoints and watchpoints you have. Open OCD Manual Section 20.3 says GDB can't query for that information so I tell it myself. Next line commands GDB to connect to the remote target at the localhost over port 3333. The last line is a monitor command which tells GDB to pass the command on to the target without taking any action itself. In this case the target is OpenOCD and I'm giving it the command halt. After that I tell OpenOCD to switch to asynchronous mode of operation. As some of the following operations take a while, it's useful not to have OpenOCD block and wait for every operation.
Sidenote #1: If you're ever in doubt about the state of GDB or OpenOCD then you can use the Eclipse debug console to send commands to GDB or OpenOCD (via GDB monitor commands) after invoking this debug configuration.
The Commands Tab - Setting up the User Flash
Next are commands I give in the Run commands section:
monitor flash probe 0
monitor flash protect 0 0 127 off
monitor reset halt
monitor stm32x mass_erase 0
monitor flash write_image STM3210CTest/test_rom.elf
monitor flash protect 0 0 127 on
disconnect
target remote localhost:3333
monitor soft_reset_halt
to be explained in the following sections...
Setting up Access to User Flash Memory
First I issue an OpenOCD query to see if it can find the flash module and report the proper address. If it responds that it found the flash at address 0x08000000 then we're good. The 0 at the end specifies to get information about flash bank 0.
Sidenote #2: The STM32Fxxx part-specific data sheets have a memory map in section 4. Very useful to keep on hand as you work with the chip. Also as everything is accessed as a memory address, you'll come to know this layout like the back of your hand after a little programming time!
So after confirming that the flash has been properly configured we invoke the command to turn off write protection to the flash bank. PM0075 describes everything you need to know about programming the flash memory. What you need to know for this command is the flash bank, starting sector, ending sector, and whether to enable or disable write protection. The flash bank is defined in the configuration files you passed to OpenOCD and was confirmed by the previous command. Since I want to disable protection for the entire flash space I specify sectors 0 to 127. PM0075 explains how I got that number as it refers to how the flash memory is organized into 2KB pages for my (and your) device. My device has 256KB of flash so that means I have 128 pages. Your device has 512KB of flash so you'll have 256 pages. To confirm that your device's write-protection has been disabled properly, you can check the FLASH_WRPR register at address 0x40022020 using the OpenOCD command:
monitor mdw 0x40022020
The resulting word that it prints will be 0xffffffff which means all pages have their write protection disabled. 0x00000000 means all pages have write protection enabled.
Sidenote #3: On the subject of the memory commands, I bricked my chip twice as I was messing with the option bytes at the block starting at address 0x1ffff800. First time I set the read protection on the flash (kind of hard to figure out what your doing if you do that), second time I set the hardware watchdog which prevented me from doing anything afterwards since the watchdog kept firing off! Fixed it by using the OpenOCD memory access commands. Moral of the story is: With great power comes great responsibility.... Or another take is that if I shoot myself in the foot I can still fix things via JTAG.
Sidenote #4: One thing that'll happen if you try to write to protected flash memory is the FLASH_SR:WRPRTERR bit will be set. OpenOCD will report a more user-friendly error message.
Erasing the Flash
So after disabling the write protection, we need to erase the memory that you want to program. I do a mass erase which erases everything, you also have the option to erase by sector or address (I think). Either way you need to erase first before programming as the hardware checks for erasure first before allowing a write to occur. If the FLASH_SR:PGERR bit (0x4002200c) ever gets set during programming then you know you haven't erased that chunk of memory yet.
Sidenote #5: Erasing a bit in flash memory means setting it to 1.
Programming Your Binary
The next two lines after erasure writes the binary image to the flash and reenables the write protection. There isn't much more to say that isn't covered by PM0075. Basically any error that occurs when you issue flash write_image is probably related to the flash protection not being disabled. It's probably NOT OpenOCD though if you're curious you can take enable the debug output and follow what it does.
GDB Debugging
So finally after programming I disconnect GDB from the remote connection and then reconnect it to the target, do a soft-reset, and my GDB is now ready to debug. This last part I just figured out last night as I was trying to figure out why, after programming, GDB wouldn't properly stop at main() after reset. It kept going off into the weeds and blowing up.
My current thinking and from what I read in the OpenOCD and GDB manuals is that the remote connection is, first and foremost, meant to be used between GDB and a target that has already been configured and running. Well I'm using GDB to configure before I run so I think the symbol table or some other important info gets messed up during the programming. The OpenOCD manual says that the server automatically reports the memory and symbols when GDB connects but all that info probably becomes invalid when the chip gets programmed. Disconnecting and reconnecting I think refreshes the info GDB needs to debug properly. So that has led me to create another Debug Configuration, this one just connects and resets the target since I don't necessarily need to program the chip every time I want to use GDB.
Whew! Done! Kind of long but this took me 3 weekends to figure out so isn't too terribly bad I think...
Final sidenote: During my time debugging I found that OpenOCD debug output to be invaluable to me understanding what OpenOCD was doing under the covers. To program a STM32x chip you need to unlock the flash registers, flip the right bits, and can only write a half-word at a time. For a while I was questioning whether OpenOCD was doing this properly but after looking through the OpenOCD debug output and comparing it against what the PM0075 instructions were, I was able to confirm that it did indeed follow the proper steps to do each operation. I also found I was duplicating steps that OpenOCD was already doing so I was able to cut out instructions that weren't helping! So moral of the story: Debug output is your friend!
I struggled getting JLink to work with a STM3240XX and found a statement in the JLink GDB server documentation saying that after loading flash you must issue a "target reset":
"When debugging in flash the stack pointer and the PC are set automatically when the target is reset after the flash download. Without reset after download, the stack pointer and the PC need to be initialized correctly, typically in the .gdbinit file."
When I added a "target reset" in the Run box of the debugger Setup of Eclipse, suddenly everything worked. I did not have this problem with a Kinetis K60.
The document also explains how to manually set the stack pointer and pc directly if you don't want to issue a reset. It may not be the disconnect/connect that solves the problem but the reset.
What i use after the last sentence in the Comannd Tab - 'Run' Commands, is:
symbol-file STM3210CTest/test_rom.elf
thbreak main
continue
The thbreak main sentence is what makes gdb stop at main.