Wednesday, January 15, 2014

Developing STM32 microcontroller code on Linux (Part 7 of 8, building and running a simple STM32 program)

The first post of this series covered the steps to build and run code for the STM32. The second post covered how to build a cross-compiler for the STM32. The third post covered how to build a debugger for the STM32. The fourth post covered building and configuring OpenOCD for your development environment. The fifth post covered building the device library, libopencm3. The sixth post covered linker scripts and command-line options necessary for building and linking programs to run on the STM32. This post will cover building and running a program on the STM32.

In the previous posts we dealt with all of the set up necessary to build programs for the STM32. It is finally time to take advantage of all of those tools and build and run something. Recall that from previous posts, we already have an OpenOCD configuration file setup, a linker script setup, and a Makefile setup. All that really remains is for us to write the code, build it, and flash it to our device. The code below is very STM32F3DISCOVERY specific; that is, it very much requires that the GPIO for the LED be on GPIO bank E, pin 12 on the board. If you have one of the other STM32 DISCOVERY boards, you'll need to look at the schematics and find one of the GPIOs that are hooked to an LED.

We are going to take an extremely simple example from libopencm3. This example does nothing more than blink one of the LEDs on the board on and off continuously. While this is simple, it will validate that everything that we've done before is actually correct.

Here is the code:

$ cd ~/stm32-project
$ cat <<EOF > tut.c
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

static void gpio_setup(void)
{
        /* Enable GPIOE clock. */
        rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_IOPEEN);

        /* Set GPIO12 (in GPIO port E) to 'output push-pull'. */
        gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
                        GPIO12);
}

int main(void)
{
        int i;

        gpio_setup();

        /* Blink the LED (PC8) on the board. */
        while (1) {
                /* Using API function gpio_toggle(): */
                gpio_toggle(GPIOE, GPIO12);     /* LED on/off */
                for (i = 0; i < 2000000; i++) /* Wait a bit. */
                        __asm__("nop");
        }

        return 0;
}
EOF
You should now be able to type "make", and the thing should build. Typing "make flash" should run OpenOCD, install the program to the board, and start blinking an LED. Remember that our Makefile required sudo access to actually run openocd. If you don't have sudo access, you can either add sudo access (by adding your user to the wheel group), or just su to root and run the openocd command by hand.

16 comments:

  1. Hi Chris,

    Thanks a million for your blog.
    I was trying to compile the blink code using the Make file you created, however I am using the STM32F100xx series and after making the required changes related to the GPIO during the linking stage I got the following error.
    tut.elf uses VFP register arguments, /home/bibinb/cross_src/libopencm3/lib/libopencm3_stm32f1.a(gpio.o) does not
    Please suggest what to do. Do I need to recompile newlib and gcc with some other flags??

    Thanks
    Bibin

    ReplyDelete
  2. Ohh...I just found something ...makefile for stm32f3 contains the following FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16...but it is not present in stm32f1 ...Could that be the reason..?? if yes then can I just compile libopencm3 with these flags or should I recompile the rest of the things without these flags? Please let me know!!
    thanks
    Bibin

    ReplyDelete
    Replies
    1. Right, that is the problem. Basically the F1 doesn't have FPU support, and also probably doesn't support the hard float ABI. If you remove both of those and then build, it should probably work then.

      Delete
    2. Hi Chris,
      How do I get rid of this flag in my gcc?

      Regards
      Bibin

      Delete
  3. No worries...I found the header files in gcc which are enabling it by default and changed the code..
    Code compiled!! :)
    Will try flashing the same and let you know...Thanks a lot anyway..

    ReplyDelete
  4. Strangely gcc compiler doesn't respond to -mfloat-abi=soft flag. It still produces the code with VFP instructions. Is this a bug or I'm missing something???

    ReplyDelete
    Replies
    1. Hi Anton,

      I apologize if i sound amateur but I feel that if you want to get rid of a VFP instructions error then you need to avoid the -mfloat-abi flag altogether. You will need to go to the file ./gcc/config/arm/t-rtems-eabi and remove the option from MULTILIB_OPTIONS.
      Regards
      Bibin

      Delete
  5. make flash gives me the following error..
    For bug reports, read
    http://openocd.sourceforge.net/doc/doxygen/bugs.html
    srst_only separate srst_nogate srst_open_drain connect_deassert_srst
    Info : This adapter doesn't support configurable speed
    Error: open failed
    in procedure 'transport'
    in procedure 'init'
    make: *** [flash] Error 1

    Any Suggestions????

    ReplyDelete
    Replies
    1. Hi Bibin,
      Did you know that, "ST-LINK causes issues" (a quote from Openocd User's Guide)? Maybe because of this openocd can't communicate with the device board. Just run the command 'dmesg' in terminal and if you see among the other messages something like:
      usb-storage 2-1.2:1.0: USB Mass Storage device detected
      scsi7 : usb-storage 2-1.2:1.0
      - then yes, it is because of this issue openocd can't communicate with the board. Just do as it says in the Openocd User's Guide: 'modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i' (under root!). Again, using 'dmesg' you should see the message change:
      usb-storage 2-1.2:1.0: USB Mass Storage device detected
      usb-storage 2-1.2:1.0: device ignored

      Delete
    2. Hi Anton,

      Thanks a ton for your suggestion. That issue was resolved by your suggestion.
      However now I am getting ...
      stlink_usb.c:238 stlink_usb_xfer_rw(): bulk read failed
      Sorry to bug you but any suggestions???
      Regards
      Bibin

      Delete
    3. On running openocd using telnet I am getting the following error!!!
      Open On-Chip Debugger
      > init
      > stm32f1x mass_erase 0
      device id = 0x10016420
      flash size = 128kbytes
      Target not halted
      stm32x mass erase failed
      in procedure 'stm32f1x

      I have even tried with 2 different boards...
      Any ideas???

      Delete
    4. If I recall correctly, first it is necessary to halt the target device before you wish to do something with it. I'm not sure about the 'init' command, but try with the 'reset halt'. It worked for me.

      Delete
    5. Hi Anton,

      Thanks again.
      Halting seems to be the answer.After simply giving halt I am able to erase my flash but running the code seems to be a problem.

      However reset halt / reset run is giving me the following error :
      jtag status contains invalid mode value - communication failure
      Polling target stm32f1x.cpu failed, GDB will be halted. Polling again in 3100ms

      Would it be possible to send me your entire list of commands you use to flash code to your micro controller?Please forgive me if im being too much of a bugger :)

      Delete
  6. Hi Bibin,

    You mean you were trying to write the .bin file on flash and it didn't work out? Or you were just trying to use the gdb to debug the code and some errors popped out? Well, in any case try to do it as it says here . It's a simple tutorial, helped me out some time ago. Just try to write the tut.bin file on flash and restart the device. In theory it should blink.

    ReplyDelete
    Replies
    1. Hi Anton,

      Thanks a lot for all your help. A treat for you whenever you come to India (Delhi) from me..You have my word :). But like I said,any reset command causes a problem for me and gives me this error..
      jtag status contains invalid mode value - communication failure
      Polling target stm32f1x.cpu failed, GDB will be halted. Polling again in 3100ms. DOnt know how to fix it!!
      Anyway thanks whether you are able to help or not with this issue:)

      Regards
      Bibin

      Delete
  7. Dear Chris, just approaching STM32 MCUs and found your blog.
    I see you didn't post last 8th part.
    I also see you didn't update the blog since long ago but I try anyway to ask you if there is still any chance you post the 8th part.
    In case, thank you very much in advance!

    ReplyDelete