Help getting a custom MBED board to work (can't flash a binary)

02 Oct 2014

I just received some PCBs back from fabrication and assembly, and I'm trying to flash over a basic "hello world" type application to verify its functionality. I'm having trouble flashing the binary, however. The design is based on the STM32F030 Nucleo Board. It's worth mentioning that I'm using the 32 pin version of the STM32F030 MCU (STM32F030K6), and not the 64 pin version, which is what's on board the Nucleo. I'm not sure if that means I need to change some things in mbed.h because of the slightly different pinout.

According to section 5.3.4 of the user manual for the Nucleo boards UM1724, it *should* be as simple as removing the jumpers on CN2, and connecting the ST-Link Header to the ST-Link Header on my board. It's worth noting that the SWO signal is 'reserved for future use', and there wasn't anywhere to connect it to on the STM32 chip.

I connected everything as indicated in UM1724. Here's a few pictures. PCB with header connected, PCB and ST-Link

Note that the LEDs on the green PCB (my board) are just power/battery charger indicators. The LEDs connected to the STM32F030 are along the center of the board.

Typically when I flash a program to a Nucleo board, I drag the binary over to the Nucleo drive that shows up like a USB. The drive will typically close, and when I open, the binary no longer appears on the 'drive', as it has been flashed over to the Nucleo MCU. I've been having no such luck with the ST-Link header from the Nucleo Board and my custom PCB. When I drag the binary over, it just sits there. The window doesn't automatically close, and nothing happens on my PCB. I checked the terminal window, and nothing is being sent over UART either. Here's a video of what I mean.

Here's the program, for reference. It's just supposed to flash an LED (I have an LED connected to PB_5), and send something over via serial.

#include "mbed.h"

//------------------------------------
// Hyperterminal configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------

Serial pc(PA_2, PA_3);
 
DigitalOut myled(PB_5);
 
int main() {
  int i = 1;
  pc.printf("Hello World !\n");
  while(1) { 
      wait(1);
      pc.printf("This program runs since %d seconds.\n", i++);
      myled = !myled;
  }
}

Here's my schematic of the MCU portion of my design along with the programming header. Schematic. The data sheet for the STM32F030K6 is located here.

Any advice would be helpful in debugging this problem, I'm not sure why it's not flashing over. Maybe it's not resetting or something?

Thanks.

02 Oct 2014

Is the target processor getting any power? Perhaps the reset switch is mounted incorrectly (it has 4 pins, these are shorted 2 by 2) and nreset is permanently low? Did not check but maybe the nucleo has different memory config than your 32pin device. That may prevent the code from booting.

02 Oct 2014

Target MCU has power, I'll check the switch now. I'm not sure how to check into the memory config stuff, could you elaborate on that a bit more? Thanks for the response.

02 Oct 2014

I removed the button, still no luck.

02 Oct 2014

Ended up getting a program to flash over. It was a bad JTAG header. Tried it with a different nucleo board and it worked. I'm seeing serial data being passed back to the PC. The GPIO pins still aren't working though (LED not flashing on PB_5).

02 Oct 2014

Mike Tomovich wrote:

Ended up getting a program to flash over. It was a bad JTAG header. Tried it with a different nucleo board and it worked. I'm seeing serial data being passed back to the PC. The GPIO pins still aren't working though (LED not flashing on PB_5).

Good. Maybe the LED is reverse connected. I assume you have serial resistors. Did you measure voltage on the pins?

02 Oct 2014

Wim, thanks again for the help! I'm looking at the pin with a scope, and it's just staying low. I do have serial resistors. I put power on the LED through a resistor externally to check if it works, and it lit up when i touched it with 3.3V through a 470ohm resistor, so they're on the board correctly.

I have 5 LEDs on the board, and this is happening to all 5 of them. The GPIO pins just don't go high for some reason. (PB_5, PB_6, PA_7, PA_8, and PA_9).

There's really not much going on in this program, no idea where something could be going wrong. Any thoughts? The pin names are supposed to have underscores, could something be strange in initializing them with DigitalOut for some reason?

#include "mbed.h"

Serial pc(PA_2, PA_3);
 
 //initialize GPIO pin
DigitalOut myled(PA_8);
 
int main() {
  int i = 1;
  pc.printf("Hello World !\n");
  while(1) { 
      wait(1);
      pc.printf("This program runs since %d seconds.\n", i++);
      //set pin high (pin never actually goes high)
      myled = 1;
  }
}
 
02 Oct 2014

Pins could end up in open drain mode and not be capable of sourcing current but dont see how that could happen. Maybe it is some issue between 64/32K versions. Are you sure your code is running. Can you observe the correct data on the serial port. Do you have any control on the I2C pins. I think the boot0 pin should be pulled low through 10K otherwise you might end up in the serial bootloader.

02 Oct 2014

Your device has 4k RAM, the NUCLEO f030 has 8k RAM. And of course less flash, but flash is easy, if it fits it fits. RAM is a different story: Even if it fits, it needs to have to correct amount of RAM setup, otherwise nothing will happen. See: http://developer.mbed.org/handbook/Memory-Model, the stack starts at the end of the memory, which on your device doesn't exist. For what to do see: http://developer.mbed.org/questions/4643/Does-mbed-support-STM32F030F4/

02 Oct 2014

Bad news, looks like something wasn't working after all. I had removed the jumpers from CN2 so that it the SWD signals would be sent over to my custom PCB and not the nucleo MCU. However, the nucleo had apparently been flashed already, and that's what I was seeing show up on my serial monitor on the PC. Back to square 1.

From the pc side of things, it appears that the program is flashing over correctly. The window pops up, I drag a binary into it, the window closes and reopens with no binary in it and no fail.txt in it. I tried this exercise with the 'broken off' nucleo board, and was able to successfully program it and turn LED1 on and off through changing the main.cpp file. This 'broken off' nucleo board was connected to the JTAG header exactly like my custom PCB was connected to the JTAG header.

I tried soldering a 10k between BOOT0 and GND, and still had the same results on my PCB (appears to flash, but no activity on my PCB).

03 Oct 2014

It is much better, in this situation, to use the ST-Link Utility, not Nucleo mode virtual disk. This will give a clear indication whether the connection between your board and the programmer is correct (proper Device Information field after "Connect to target" ), independently of other factors (type of chip, option bytes, BOOT0 pin, etc.). With this tool, you can also easily program the target using the binary file received from the mbed online compiler. Then you read the memory at address 0x08000000, you can see which address is to the top of the stack. If it is larger than the size of the RAM (+1), the program certainly will not work, as mentioned above. Using ST-Link Utility can reprogram this memory location manually, but I do not know if all this if you are using processors other than native to Nucleo.

03 Oct 2014

Great advice, it shed some light on the problem. For one, the device ID of the Nucleo board running the STM32F030R8 is 0x440, and the device ID of the 32 pin version of that chip (STM32F030K6) that is on my custom PCB is 0x444. (Yes, my PCB was recognized by the ST-Link Utility) Also, the flash and ram sizes of the two chips are different. I think the compiler needs to know these changes, otherwise the binary just won't work with the STM32F030K6 on my PCB.

Is there a way to change these type of things in the MBED compiler? Some looking around tells me no... Otherwise, will I have to export things to Keil or IAR or something?

03 Oct 2014

See my earlier post, with links on what you need to change in the mbed compiler.

You cannot actually change the flash size the compiler thinks is there, but that doesn't matter as long as it fits. Similar it doesn't matter how much RAM the compiler thinks there is, as long as it sets the initial stackpointer to the correct value. So that one needs to be modified.

03 Oct 2014

Missed your earlier post somehow, I'll try that and report my findings here. Thanks Erik. What about the device ID?

03 Oct 2014

Erik, I'm a bit confused about how to modify the startup_stm32f030.s file you mention in that post located here and then use the modified file in the online MBED IDE. Is that possible, or will I have to export anyway?

03 Oct 2014

See the first half of the answer here: http://developer.mbed.org/questions/4643/Does-mbed-support-STM32F030F4/. You need to delete your mbed lib, and instead import mbed-src. That is the same (pretty much, only it is a bit the beta branch of the mbed lib), but it includes all the source files, including that startup file. You can jsut navigate to it from the online IDE, modify it, and compile the entire thing.

03 Oct 2014

UPDATE: I was able to figure out what Erik meant and modify the startup_STM32F030.s file in mbed-src and import it into my project, and also compile it. I made this modification.

Stack_Mem       SPACE   Stack_Size
;__initial_sp    EQU     0x20002000 ; Top of RAM (8 KB for STM32F030R8)
__initial_sp    EQU     0x20001000 ; Top of RAM (4 KB for STM32F030K6)

The STM32F030K6 has 4kb of RAM just like the STM32F030F4, so 0x20001000 is the right number to use here.

I also modified stm32f030xx.sct to reflect the 32kb flash size and 4kb RAM size

; STM32F030R8: 64KB FLASH (0x10000) + 8KB RAM (0x2000)
; STM32F030K6: 32KB FLASH (0x8000) + 4KB RAM (0x1000)

 ;LR_IROM1 0x08000000 0x10000  {    ; load region size_region
 ; ER_IROM1 0x08000000 0x10000  {  ; load address = execution address 
 LR_IROM1 0x08000000 0x8000  {    ; load region size_region
  ER_IROM1 0x08000000 0x8000  {  ; load address = execution address 
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }

  ; 45 vectors = 180 bytes (0xB4) to be reserved in RAM
 ; RW_IRAM1 (0x20000000+0xB4) (0x2000-0xB4)  {  ; RW data
  RW_IRAM1 (0x20000000+0xB4) (0x1000-0xB4)  {  ; RW data
   .ANY (+RW +ZI)
  }

And then it finally ended up working! For anyone who was confused like I was, you have to import mbed-src into your program located here via the import button, and make sure that you're not using the traditional 'mbed' library. You then make the modifications to the files noted above in the folder targets/cmsis/TARGET_STM/TARGET_NUCLEO_F030R8/TOOLCHAIN_ARM_MICRO/ . I was a bit confused because the post that Erik had linked to talked about exporting the program. Thanks for the help guys.

03 Oct 2014

Ah yeah true. But indeed you can do such changes also in the online compiler :).

Glad you managed to get it to work.

03 Oct 2014

Thanks Mike and Eric very informative thread. Major stress reliever WRT to proceeding with my board :).

03 Oct 2014

One more thing worth noting, I was having some trouble with the Serial port right after I got the LED blinky working. As soon as I included a printf in my code, the whole thing would hang! LED stopped blinking, nothing was happening on the serial port. After checking the data sheet, this was because PA_2 and PA_3 (tx and rx) were set up to be UART_2 on the Nucleo board, but with my STM32F030K6, PA_2 and PA_3 were set up to be UART_1. I was able to change this in the serial_api.c file in the mbed-src directory.

The file was located at /mbed-src/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8

The changes were as follows

static const PinMap PinMap_UART_TX[] = {
    //{PA_2,  UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
    {PA_2,  UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},//new
    {PA_9,  UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
    {PB_6,  UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_0)},
    {NC,    NC,     0}
};

static const PinMap PinMap_UART_RX[] = {
    //{PA_3,  UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
    {PA_3,  UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},//new
    {PA_10, UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
    {PA_15, UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
    {PB_7,  UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_0)},
    {NC,    NC,     0}
};

I also had to make sure that GPIO_AF_1 was the right 'alternate function' to select for PA_2 and PA_3 to be configured as UARTs. I'm assuming I'll have to make similar changes for SPI and I2C. Hopefully this helps someone down the road.

15 Oct 2014

Thanks! i am using the same chip and was wondering about how to use the mbed library for it.

21 Jul 2015

Erik - wrote:

You need to delete your mbed lib, and instead import mbed-src. That is the same (pretty much, only it is a bit the beta branch of the mbed lib), but it includes all the source files, including that startup file. You can jsut navigate to it from the online IDE, modify it, and compile the entire thing.

I've imported mbed-src but I don't seem to be able to actually edit the startup and sct files. When I try to open the startup file, the mbed editor tells me the file isn't compatible. I'm able to open the .sct but I can't edit it.

I downloaded the lib and edited it locally, but I don't seem to be able to import my modified library as a zip file, even though mbed documentation says this is a preferred method of importing full directories.

Any idea what I'm missing here?

21 Jul 2015

You were able to modify .s files (don't really see why they disabled it, since it is just an assembly file). Sct files were in the past editable, although it didn't (always) accept them after editting.

You can try if you can import just a zip file of the .s and .sct file, and then drag them in the correct folder (if that is even required).