Openocd how to write option bytes to STM32F4 - stm32f4
I have two boards with a STM32F437 (IGH6 7BA4S VQ PHL 7B 542) processor. We program these with openocd and a jtag, however lately one card stopped working. It is no longer possible to program the card and one of the differences we have found is that the user option bytes differ between the cards.
0x0EC On the working card
0xCFC On the broken
What I tried to do is using the options_write command. Note that the STM32F4 apparently goes under the "stm32f2x" command.
openocd -f openocd.cfg -c "reset halt; stm32f2x unlock 0; reset halt; stm32f2x options_write 0 0x0EC"
This resulted in the error message: "Error: stm32x device protected"
In the STM32F437 Reference manual RM0090 under "3.7.2 Programming user option bytes" it says:
To run any operation on this sector, the option lock bit (OPTLOCK) in the Flash option
control register (FLASH_OPTCR) must be cleared. To be allowed to clear this bit, you have
to perform the following sequence: \n
Write OPTKEY1 = 0x0819 2A3B in the Flash option key register (FLASH_OPTKEYR)
Write OPTKEY2 = 0x4C5D 6E7F in the Flash option key register (FLASH_OPTKEYR)
The user option bytes can be protected against unwanted erase/program operations by
setting the OPTLOCK bit by software.
To do that I tried the following in a telnet session:
mww 0x08 0x08192A3B
mww 0x08 0x04C5D6E7F
mdw 0x0C
mww 0x18 0x0EC
mww 0x14 0x0EC
The 0x08 on line 1 is FLASH_OPTKEYR, 0x0C on line 3 is FLASH_SR to check if BSY bit is not set, 0x14 on line 4 is FLASH_OPTCR1, and 0x14 on line 5 is FLASH_OPTCR.
Then a reboot and trying to program the application
openocd -f openocd.cfg -c "program HCF-220_07_010_PA2.hex reset exit"
This results in the error:
Error: stm32x device protected.
I also tried to do the following command to unlock before programming:
openocd -f openocd.cfg -c "openocd -f openocd.cfg -c "reset halt; stm32f2x unlock 0; program HCF-220_07_010_PA2.hex reset exit"
Same result:
Error: stm32x device protected.
Update
I tried the following in telnet without luck, the user option is still 0xCFC:
mww 0x40023C08 0x08192A3B
mww 0x40023C08 0x04C5D6E7F
mdw 0x40023c0c
mww 0x40023C18 0x0EC
mww 0x40023C14 0x0EC
mww 0x40023C08 0x02
Power Cycle
In RM0090 chapter 3.7.2 it also says: 4. Set the option start bit (OPTSTRT) in the FLASH_OPTCR register
Hence the nr 6. above.
The working solution for me was as follows:
stm32f2x lock 0 Yes lock not unlock.
Do a power cycle
reset init
mww 0x40023C08 0x08192A3B
mww 0x40023C08 0x04C5D6E7F
mdw 0x40023c0c Wait for flash write to finish, make sure we receive 00000000
mww 0x40023C18 0x0FFF0000
mww 0x40023C14 0x0FFFAAEC Write user_options to same as a working
mww 0x40023C14 0x0FFFAAEE Set option start bit, step "4." in rm0090.
mdw 0x40023c0c Wait for flash erase to finish, make sure we receive 00000. This takes about 10 seconds.
Do a power cycle
The reason why it did not work with OpenOCD command "options_write", can be found in the manual for OpenOCD. The "user_options" argument takes the bits 31-28 and 7-0 from FLASH_OPTCR.
Flash register base address is 0x40023C00 (as per RM0090). 0x08 is offset from base, so you should write to 0x40023C08
Related
shell script Bluetoothctl WRITE
#!/usr/bin/expect -f set prompt "#" set address 34:85:18:6a:52:52 spawn bluetoothctl expect -re $prompt send "connect $address\r" expect "Connection successful" sleep 2 send "list-attributes\r" sleep 2 send "menu gatt\r" sleep 2 send "select-attribute /org/bluez/hci0/dev_34_85_18_6A_52_52/service002e/char002f\r" sleep 2 send "list-attributes\r" sleep 2 send "write 0xa5 0x00 0x00 0x08 0x00 0x53 0x6f 0x0e 0x00 0x03 0x10 0x01 0x02 0x12 0x01 0x0a 0xff 0x01 0x20 0x9a\r" send "quit\r" expect eof i need to be able to have " " quotations around th value being sent or else bluetoothctl write will not accept the value it works in terminal as write "0xa5 0x00 0x00 0x08 0x00 0x53 0x6f 0x0e 0x00 0x03 0x10 0x01 0x02 0x12 0x01 0x0a 0xff 0x01 0x20 0x9a" but script will not allow me to input quotations around value without throwing an error... ive tred breaking write and value apart and using a \ between them, i really dont have a good grasp of scripting to know how to make it work. maybe a variable with intended code inside but again i dont have the knowledge to get this completed solo
The first line #!/usr/bin/expect -f shows that this is an Expect script, not a shell script. Expect is based on Tcl, so the Tcl rules for quoting apply. These can be found at http://www.tcl-lang.org/man/tcl8.6/TclCmd/Tcl.htm . The first part of #akathimi's answer is still applicable - backslashes can be used to insert double-quotes in a double-quoted string. However the second part does not apply - single-quotes have no significance in Tcl syntax. However the same effect can be achieved by enclosing the whole string in braces {} like this, e.g. puts {test test is "test"} but note that this will also disable the substitution of a carriage-return character for the sequence \r.
in bash in general, use \" to echo the ". e.g.: $echo "test test is test" test test is test $echo "test test is \"test\"" test test is "test" You can also use single quotes ', e.g.: echo 'test test is "test"' test test is "test"
Very strange SIGQUIT when try to switch from ring 0 to ring 3
I am working on enabling Intel SGX on a unikernel that does not have a native ring 3 support. Hence in order to invoke the user-mode SGX instruction I need to implement a ring switch routine. I followed the JamesM's tutorial( 10.-User Mode (jamesmolloy.co.uk) , which is a 32-bit solution) to drafted a long-mode version: void switch_to_ring3() { asm volatile(" \ mov $0x23, %rax; \ mov %rax, %ds; \ mov %rax, %es; \ mov %rsp, %rax; \ push $0x23; \ push %rax; \ pushf; \ push $0x1B; \ push $1f; \ iretq; \ 1: \ "); return; } I am sure that I have set up GDT entries properly and 0x23/0x1B is exactly the indexes of user-mode code/data descriptors, in which the code descriptor value is 0xaffb000000ffff and the data descriptor value is 0xaff3000000ffff. What's strange is that the iretq can be executed successfully, and the rip register could go to the next instruction of the iretq, which is a nop if I disabled the optimization and a ret if I enabled the optimization. However, when executing the next instruction, it will die without any output (my unikernel has an exception handler, even if for unhandled exceptions, it will output something). I try to use GDB to debug and GDB said that the program received SIGQUIT. I checked the registers but find nothing wrong, cs is 0x1b, ss, ds and es are 0x23, and rip points correctly to the next instruction of iretq. I am really confused about why it receives SIGQUIT. If some exception happened, it should output the dump message, or at least qemu log will track some 'check_exception' message, but the log is empty. Everything seems okay, correct segment registers, correct rsp/rbp/rip, the kernel code segment is user-accessible by setting the conformed bit of its descriptor, and the high/low base address in all descriptors are pointed to 0x0. Being trapped in this problem for a whole day but cannot find any solution. I hope someone here could save my life T_T
I finally fixed it by setting U/S bit for all kernel code/data pages. Thanks for all of your comments #prl #PeterCordes !
How to debug a windows driver with IDA and use its corresponding IDB?
I am familiar with using windbg or IDA for remote kernel debugging, but right now i have extracted a kernel driver from an executable, and have done static analysis on its IDB and renamed a lot of variables, what is the easiest way of using my IDB file to debug the driver on the remote debugee when it gets loaded by the executable? I know how to attach to remote kernel using IDA, but how can i use my current IDB file, and put breakpoint on some of its functions so it they get hit when the driver is loaded? (I dont have the corresponding pdb file for the driver so i can't use symbols for breakpoint)
this is a vanilla windbg answer to break on any DriverInit once you have Broken on DriverInit You Can Lookup and Set bp on all MajorFunctions Assuming you have a regular kd Connection use sxe -ibp;.reboot to reboot the target on reconnection the target will break very Early as below kd> sxe ibp;.reboot Shutdown occurred at (Sun Oct 18 02:58:09.077 2020 )...unloading all symbol tables. Waiting to reconnect... Connected to Windows 7 7601 x86 compatible target at (xxx), ptr64 FALSE Kernel Debugger connection established. (Initial Breakpoint requested) once broken set a breakpoint on nt!IopLoadDriver inside this function search for an indirect Call that Calls the _DRIVER_OBJECT->DriverInit kd> ?? #FIELD_OFFSET(nt!_DRIVER_OBJECT , DriverInit) long 0x2c like nt!IopLoadDriver+0x7ea: 829d5355 ff562c call dword ptr[esi+2Ch] ds:84f2928c={cdrom!FxDriverEntry (87eb53cf)} set a break point here to you are now set to enter almost every driver that is loaded once you are on entrypoint of any Driver use the DriverObject (an argument the DriverEntry Takes ) and Set Breakpoints on each MAJORFunction kd> bp . "du poi(#esi+1c+4);gc" kd> bl 0 e Disable Clear 829d4b6a 0001 (0001) nt!IopLoadDriver 1 e Disable Clear 829d5355 0001 (0001) nt!IopLoadDriver+0x7ea "du poi(#esi+1c+4);gc" kd> bd 0 kd> bl 0 d Enable Clear 829d4b6a 0001 (0001) nt!IopLoadDriver 1 e Disable Clear 829d5355 0001 (0001) nt!IopLoadDriver+0x7ea "du poi(#esi+1c+4);gc" kd> g 841bd1d0 "\Driver\Null.Ѕ捁印䍁䥐停偎〰〰" 84f18718 "\Driver\Beep.Б浍摌䂈蓶䈸蓶...." 84eef210 "\Driver\VgaSave" 84eb2860 "\Driver\RDPCDDᛛ..В浍慃憠褎.蓫菌蓲" 84e903c0 "\Driver\RDPENCDD..浍摌읨蓤潤獷獜獹整.尲牤癩牥" 84e90400 "屳摲数据摤献獹" 84ef15c0 "\Driver\RDPREFMP..牉..蓧" 84ef4a78 "\FileSystem\Msfs.В浍慃冀褘蝴蓳荤蓶" 84f191f0 "\FileSystem\Npfs.З獍䑆.°"
Xmega-A1 Xplained doesn't respond after disabling JTAG fuse
I have an XMEGA-A1 Xplained and a JTAG ICE mkII. I just tried to use avrdude on Linux. The first thing I did was to try to set the JTAG fuse off to use PDI (since the Hardware User's Guide said JTAG and PDI can't be used together - section 9.3), but now all I have is 8 rapidly flashing LEDs and no ability to communicate with the device. The LED by the USB connector is solid green/red, though the red flashes when you replug the USB. If I press SW0, the LEDs stop flashing, but they start again as soon as I let go, and pressing any of the 7 other buttons seems to have no effect. When I try to communicate with the device now, all I get is: $ avrdude -p x128a1 -c jtag2pdi -P usb -v avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_FAILED avrdude: jtagmkII_close(): bad response to GO command: RSP_ILLEGAL_EMULATOR_MODE avrdude done. Thank you. If I use jtag2slow (which worked before), I get: avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_FAILED avrdude: initialization failed, rc=-1 Double check connections and try again, or use -F to override this check. avrdude: jtagmkII_close(): bad response to GO command: RSP_ILLEGAL_EMULATOR_MODE avrdude done. Thank you. The command I used to set the fuses was taken from what Eclipse generated: -Ufuse4:w:0x1:m Is there a way to "break into" the device and re-establish communication?
This was caused by a failure of the JTAGICE mkII to communicate over the PDI connection due to a bad connection in the (homemade) squid cable. I made a new one and all is OK. It took a bit of messing around to work out the right connections again, since no-one seems to have put the two connection tables together (i.e. the "Connecting to a PDI target" in AVR Help and "Table 4.1: Programming Headers" in the Xplained user Guide), my squid cable is all grey, and I disconnected it before writing down the connections (don't do this!). So, here it is. How to connect XMega-A1 Xplained via PDI with JTAGICE mkII ------------------------------------------------------ | JTAGICE mkII | XMEGA-A1 Xplained | |--------------------------------+-------------------| | Pin | JTAG Name | Squid Colour | Pin | PDI Name | |-----------------+--------------+-------------------| | 2 | GND | White | 2 | GND | | 4 | VTref | Purple | 4 | VCC | | 6 | nSRST | Green | 6 | PCI_CLK | | 9 | TDI | Red | 3 | PDI_DATA | ------------------------------------------------------ Setting fuses This is mentioned in the documentation, but it's worth repeating here: once you set the JTAGEN fuse to 1 (i.e. disable JTAG) the only way to get back to JTAG is to make a PDI connection and set the fuse back to 0. Be very careful when setting the fuse if you can't program by PDI, as if you set fuse byte 4 to 0x01, as well as setting JTAGEN, you will also disable external reset (bit 4) and be unable to use ISP programming. If you look above, you will see this is what I did. Apparently, not all JTAGICE mkII's can do PDI (mine can), so make sure before you blow this fuse!
I had the same problem and it was induces because I was flashing the .elf file instead the .hex. To solve it I did the next: Disconnect the xplained usb cable in order to Unpowered the micro. Reconnect the USB cable and as fast as you can send the command to reprogramm the micro. If someone can help is better. It worked for me.
atmega8 program size limit?
I am new to atmega8. I convert some old freesacle code into atmega8. but seems my chip can not hold code more than 2400 bytes? below is result, when code is 2412 bytes... all things become mess. code below avrdude is comes from "cat /dev/ttyUSB0". my debug informations. avrdude: verifying ... avrdude: 2412 bytes of flash verified avrdude: safemode: Fuses OK avrdude done. Thank you. 55432111001-0000 6Gn�H(�h�X0443234554321190 6Gn�H (�h�X0443234554321100-FD-90-6F55432111001-0000 6Gn�H (�h�X0443234554321190 6Gn�H(�h�X0443234554321100-FD-90-6F^C but if i reduced code(only audio data), i got right result. avrdude: verifying ... avrdude: 2312 bytes of flash verified avrdude: safemode: Fuses OK avrdude done. Thank you. AVR-IrDA-Tone-Audio start. version 1.2 --IrDA-- Bin: 1001-0000 Hex: 90 Complete Hex: 00-FD-90-6F all hfuse, lfuse, lock bits are original value. my code might be 6k with some audio data. if it is due to boot flash section? Addtion: -------------------------------------------------------------------------------------------------- I change crystal to 8M now. ● ll h8-* -rw-rw-r-- 1 eexp eexp 933 9月 22 00:27 h8-reduce.c -rw-rw-r-- 1 eexp eexp 14K 9月 22 00:26 h8-org.c ● cp h8-org.c h8.c ● avr.sh main.c ...... avrdude: 5272 bytes of flash verified now all goes mess. ● cp h8-reduce.c h8.c ● avr.sh main.c ..... avrdude: 1872 bytes of flash verified now all goes right, but i lost almost all audio data. below is h8.c. ● head h8.c const unsigned char h8[] = { 36,14,0,0,129,129,128,129,130,127,126,128,128,127,128,130,131,128,127,127,127,126,127,129,130,130,129,129,128,128,128,128,128,126,126,129,128,127,127,130,133,130,126,126,129,128,125,127,128,129,128,127,129,128,127,127,127,128,128,129,127,127,129,128,130,130,128,128,127,126,128,128,128,130,129,128,129,126,126,125,127,132,130,127,126,129,131,127,127,133,133,127,122,125,129,130,127,127,130,129, 126,125,127,128,129,128,128,128,128,127,127,129,128,129,129,128,126,127,129,127,128,127,128,130,129,129,128,128,127,127,129,130,128,128,129,129,127,127,128,128,128,128,128,128,126,126,129,129,127,129,130,130,126,126,128,128,127,128,131,130,127,126,126,128,129,125,128,130,131,128,126,129,128,129,125,126,130,129,131,130,131,129,125,128,129,131,130,127,130,129,127,128,127,129,128,126,126,127,128,126, 127,127,128,128,128,127,127,127,127,127,129,128,129,128,128,129,129,128,128,129,128,128,128,129,0xff, };
i guess you are loading the audio data into the ram. a variable declaration like char* data = "somerandomdata"; is putting all the data in the SRAM, and you just have 1kbyte of SRAM in the mega8 (which also contains the stack etc). if the lock bits are in their original state, the bootloader mechanism should not cause this error. you should specify the audio data as program space, here is the description how: Avr LibC PGM Space here is how your code should look like: h4.c #include <avr/pgmspace.h> const unsigned char h4[] PROGMEM = { 18,7,0,0,128,128,128,127,127,129,129,127,126,128,130,129,128,129,127,127,128,128,132,127,129,126,128,128,127,127,127,129,127,127,130,129,127,127,129,130,129,125, you need to adjust your set_audio function, every reading of the pointer h4 shall be done in this way: change for example value = *h4_copy++; to value = pgm_read_byte(h4_copy); h4_copy++;