Difference between revisions of "Nucleo Boards"

From RobolaboWiki
Jump to: navigation, search
m (Semihosting en STM32F4)
Line 422: Line 422:
  
 
The board should be blinking at this point
 
The board should be blinking at this point
 +
 +
<h1> Semihosting on STM32F4 </h1>
 +
Semihosting is a neat way to redirect STDOUT and STDIN from an embedded system to a debug window on a PC. This allows you to output messages using printf functions without having to use/configure an RS232 or USB Virtual COM Port, and can also read input from the PC's keyboard via scanf functions.
 +
 +
<h2> Configuration </h2>
 +
 +
Add the following linker flags to the Makefile file:
 +
<pre>
 +
--specs=rdimon.specs  -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group \
 +
</pre>
 +
 +
Include the library "stdio.h" to the main.h file.
 +
 +
Add the following function prototype to the main.c file and call the function at the begining of the main, previous to any printf() statement:
 +
<pre>
 +
extern void initialise_monitor_handles(void);
 +
</pre>
 +
 +
Enable de semihosting option at the GDB terminal:
 +
<pre>
 +
monitor arm semihosting enable
 +
</pre>
 +
 +
Finally, add printf() statements in your code, compile with make and execute.
 +
 +
<b> Important </b> Output window will be the terminal executing the OpenOCD GDB Server, not the GDB terminal.
 +
 +
<b> Important </b> Semihosting is not compatible with the use of FreeRTOS.
 +
 +
<h2> Example of GDB connection </h2>
 +
 +
<pre>
 +
(gdb) target remote :3333
 +
Remote debugging using :3333
 +
0x08001154 in ?? ()
 +
(gdb) monitor reset halt
 +
target state: halted
 +
target halted due to debug-request, current mode: Thread
 +
xPSR: 0x01000000 pc: 0x08001154 msp: 0x20020000
 +
(gdb) monitor arm semihosting enable
 +
semihosting is enabled
 +
(gdb) file bin/Semihosting.elf
 +
A program is being debugged already.
 +
Are you sure you want to change the file? (y or n) y
 +
Load new symbol table from "bin/ControladorP.elf"? (y or n) y
 +
Reading symbols from bin/Semihosting.elf...done.
 +
(gdb) load
 +
Loading section .isr_vector, size 0x1c4 lma 0x8000000
 +
Loading section .text, size 0x2e60 lma 0x80001c4
 +
Loading section .rodata, size 0x14 lma 0x8003024
 +
Loading section .init_array, size 0x8 lma 0x8003038
 +
Loading section .fini_array, size 0x4 lma 0x8003040
 +
Loading section .data, size 0x430 lma 0x8003044
 +
Start address 0x8000220, load size 13428
 +
Transfer rate: 17 KB/sec, 2238 bytes/write.
 +
(gdb) monitor reset halt
 +
target state: halted
 +
target halted due to debug-request, current mode: Thread
 +
xPSR: 0x01000000 pc: 0x08000220 msp: 0x20020000
 +
(gdb) c
 +
Continuing.
 +
</pre>
 +
 +
<h2> Example of use </h2>
 +
 +
<pre>
 +
#include "main.h"
 +
 +
extern void initialise_motor_handles(void);
 +
uint32_t a;
 +
 +
int main(void)
 +
{
 +
  initialise_motor_handles();
 +
  a = 0;
 +
  while(1)
 +
  {
 +
    a++;
 +
    printf("Current value for a is: %d\n", a);
 +
    HAL_Delay(1000);
 +
  }
 +
}
 +
</pre>
  
 
<h1> Eclipse Environment  </h1>
 
<h1> Eclipse Environment  </h1>

Revision as of 13:03, 3 February 2017

Configuring the environment

Install Compiler gcc-arm-none-eabi

Install the following libraries:

sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0

Download last version of GCC ARM Embedded from: https://launchpad.net/gcc-arm-embedded/+download

Untar the compiler:

tar -xvjf gcc-arm-none-eabi-<VERSION>.tar.bz2

Copy it to a common place:

sudo cp -r gcc-arm-none-eabi-<VERSION> /opt/compilerNucleoST

Install OpenOCD On-Chip Debugger

Instal dependencies:

sudo apt-get install flex bison libgmp3-dev libmpfr-dev libncurses5-dev libmpc-dev autoconf texinfo build-essential \\
libftdi-dev libusb-1.0-0-dev libexpat1-dev

Download last version of Openocd from: http://openocd.org/

Untar openocd:

tar -xvzf openocd-<VERSION>.tar.gz

Go into the directory:

cd openocd-<VERSION>

Configure openocd compilation:

./configure --prefix=/opt/openocdNucleoST --enable-maintainer-mode --enable-stlink

Compile it:

make

Install:

sudo make install

Prepare its use according to udev:

sudo cp -r contrib/99-openocd.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules

In order to run openocd as a non root user, you must to add your user name to plugdev group.

  • Edit /etc/group
  • Find plugdev
  • Add your user after the colon symbol (e.g. plugdev:x:46:user1), or after the last user by adding a coma in between (e.g. plugdev:x:46:user1,user2,user3)

For connection, check in GDB Section


Hello World experiment

Download STMCube

STMicroelectronics introduces STMCube as an initiative to ease developers life. They are sharing packages containing libraries, documentation and examples. Packages are delivered per series (such as STM32CubeF4 for STM32F4 series)

Go to: http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897?icmp=tt2930_gl_pron_oct2015&sc=stm32cube-pr14

and select the STMCubeXX according to your microcontroller (e.g. STM32CubeL4 for STM32L4 series) and load it in a prefered directory:

Untar STM32CubeXX:

unzip stm32cubexx.zip

This will create a Firmware directory which will be referred in this tutorial as <STM32_CUBE_FW_ROOTDIR>.

Create the experiment

The example is done for a toggle led experiment. It will be compiled for a specific nucleo board, named in this tutoral as <BOARD>.

Create experiment dir in your prefered directory:

mkdir helloWorld
mkdir helloWorld/bin

Copy experiment sources:

cp -r <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Examples/GPIO/GPIO_IOToggle/Src helloWorld/src
cp -r <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Examples/GPIO/GPIO_IOToggle/Inc helloWorld/include

Copy STM32 libraries:

cp -r <STM32_CUBE_FW_ROODIR>/Drivers/ helloWorld/lib

Copy startup code to src dir:

cp <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Templates/SW4STM32/startup_<NUCLEO_BOARD>.s helloWorld/src

where <NUCLE_BOARD> refers to your nucleo board model.

Important If SW4STM32 does not exists use TrueStudio instead.


Copy linker file:

cp <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Templates/SW4STM32/<BOARD>_Nucleo/<NUCLEO_BOARD>_FLASH.ld helloWorld/

where <NUCLE_BOARD> refers to your nucleo board model.

Important If TrueStudio does not exists use SW4STM32 instead.


Create an environment file to export PATH:

cd helloWorld
echo $PATH > env.sh

Edit env.sh and at the begining of the line include:

export PATH=/opt/openocdNucleoST/bin:/opt/compilerNucleoST/bin:

Your file should look like this:

export PATH=/opt/openocdNucleoST/bin:/opt/compilerNucleoST/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Download Makefile, rename it as "Makefile" and copy it to <HELLOWORLD> dir.

Open makefile and substitute:

  • <PROJECT_NAME> with the name you want to give to your project
  • <STM32_NUCLEO_BOARD> with the nucleo board name (e.g. STM32F4xx).
  • <STM32_LNKER_FILE> with the name of the linker file in <HELLOWORLD> dir (e.g. STM32F446RETx_FLASH.ld)
  • <STM32_MICROCONTROLLER> with the compilation directive of your specific microcontroller (e.g. STM32L053xx) found in your CMSIS STincludes dir (e.g. lib/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h)
  • <CPU_INFO> with the mcpu of the controller found in src/startup_stm32XXX file near the .cpu directive (e.g. cortex-m0plus)
  • <STARTUP_NAME> with the name of your startup filename. (e.g. startup_stm32f446xx) found in src dir (important: name it without extension).

Important If working with Cortex-M4 add the following lines to the CFLAGS definition:

-mfpu=fpv4-sp-d16 \
-mfloat-abi=softfp \

After this, everything should be ready:

Export you PATH

source env.sh

Compile:

make

Copy the bin/<FILE>.bin to the disc that is created when the board is connected to the PC. An LED should be blinking.

NOTE It is interesting to clean the project before submitting to any repository. lib dir is full of unusfull information:

  • In lib/BSP keep only the dir that refers to your board
  • In lib/CMSIS keep only the Device and Include dirs
  • In lib/HAL_DRIVER dir, keep only the Inc and Src dirs.

FreeRTOS Port

Before proceed with this section, you should have already implemented the previous section

Download and prepare sources

Download last version of FreeRTOS from: http://www.freertos.org/

Unzip it:

unzip FreeRTOS<VERSION>.zip

Copy FreeRTOS source to your working dir

cp -r <FREERTOS_DIR>/FreeRTOS/ helloWorld/

Go in helloworld/FreeRTOS dir and remove all but Source dir

Go in helloworld/FreeRTOS/Source/portable dir and remove all but GCC dir and <MemMag> dir

Go in helloworld/FreeRTOS/Source/portable/GCC dir and remove all but your CPU related (e.g. ARM_C0 for Cortex-M0)


Configure FreeRTOS

This is the most complex task, but this manual is not intended for it.

If you have a board already supported by FreeRTOS which is provided in the Demo examples, copy the FreeRTOSConfig.h found in those examples to your helloworld/include dir.

If not, download this FreeRTOSConfig.h , rename it as "FreeRTOSConfig.h", copy it to <HELLOWORLD>/include dir and work on it.

Go in your helloworld/src/stmXXXX_it.c file and comment the SVC_Handler, PendSV_Handler and SysTick_Handler functions

Download Makefile, rename it as "Makefile" and copy it to <HELLOWORLD> dir.

Open makefile and substitute:

  • <PROJECT_NAME> with the name you want to give to your project
  • <STM32_NUCLEO_BOARD> with the nucleo board name (e.g. STM32F4xx).
  • <STM32_LNKER_FILE> with the name of the linker file in <HELLOWORLD> dir (e.g. STM32F446RETx_FLASH.ld)
  • <STM32_MICROCONTROLLER> with the compilation directive of your specific microcontroller (e.g. STM32L053xx) found in your CMSIS STincludes dir (e.g. lib/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h)
  • <CPU_INFO> with the mcpu of the controller found in src/startup_stm32XXX file near the .cpu directive (e.g. cortex-m0plus)
  • <STARTUP_NAME> with the name of your startup filename. (e.g. startup_stm32f446xx) found in src dir (important: name it without extension).
  • <RTOS_GCC_CPUINFO> with the name of the mcpu of the controller of the FreeRTOS dir (e.g. ARM_CM0) found in RTOS_SOURCE_DIR/portable/GCC/

Important If working with Cortex-M4 add the following lines to the CFLAGS definition:

-mfpu=fpv4-sp-d16 \
-mfloat-abi=softfp \

Create a Basic Task

Open your main.c

Include FreeRTOS libs:

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

Define a task and its handler

xTaskHandle ledpTask_Handle;
void Ledp_Task();

In the main function, comment the while loop and provide instead the following code to create a task and start the scheduler:

xTaskCreate(Ledp_Task, "Ledp_Task", 70, NULL, 1, &ledpTask_Handle);
vTaskStartScheduler();

Create a Task (function) with the following code:

void Ledp_Task (void * pvParams)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    vTaskDelay(1000);
  }
}

After this, everything should be ready:

Export you PATH

source env.sh

Compile:

make

Copy the bin/<FILE>.bin to the disc that is created when the board is connected to the PC. An LED should be blinking.

GDB Debug

It is mandatory openocd is installed in your system (see OpenOCD section)

You need an openocd.cfg file which is related to your board and jtag.

Here we provide a file with the configuration of an stlink and a STM32L053 mcu:

source [find interface/stlink-v2-1.cfg]

transport select hla_swd

set WORKAREASIZE 0x2000
source [find target/stm32l0.cfg]

reset_config srst_only

However, find your jtag filename in interface of your openocd sources and your mcu filename on the target dir.

Once the file is configured, load the PATH

source env.sh

Connect to your board:

openocd -s /opt/openocdNucleoST/share/openocd/scripts/ -f openocd.cfg -c "init" -c "halt" -c "reset halt"

Output should be something similar to:

Open On-Chip Debugger 0.9.0 (2016-07-05-21:42)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
adapter speed: 300 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 300 kHz, using 240 kHz
Info : Unable to match requested speed 300 kHz, using 240 kHz
Info : clock speed 240 kHz
Info : STLINK v2 JTAG v24 API v2 SWIM v11 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.246505
Info : stm32l0.cpu: hardware has 4 breakpoints, 2 watchpoints
Info : Unable to match requested speed 300 kHz, using 240 kHz
Info : Unable to match requested speed 300 kHz, using 240 kHz
adapter speed: 240 kHz
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x08000244 msp: 0x20002000

If the terminal gets there and does not return, you are now connected to the board.

Open a new terminal and load the PATH

source env.sh

Launch ARM GDB

arm-none-eabi-gdb

Connect GDB to openocd

target remote :3333

Reset the board

monitor reset halt

Import the file

file bin/ledp.elf

Load the binaries into the mcu

load

Reset the board

monitor reset halt


Run the board

continue

The board should be blinking at this point

Semihosting on STM32F4

Semihosting is a neat way to redirect STDOUT and STDIN from an embedded system to a debug window on a PC. This allows you to output messages using printf functions without having to use/configure an RS232 or USB Virtual COM Port, and can also read input from the PC's keyboard via scanf functions.

Configuration

Add the following linker flags to the Makefile file:

--specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group \

Include the library "stdio.h" to the main.h file.

Add the following function prototype to the main.c file and call the function at the begining of the main, previous to any printf() statement:

extern void initialise_monitor_handles(void);

Enable de semihosting option at the GDB terminal:

monitor arm semihosting enable

Finally, add printf() statements in your code, compile with make and execute.

Important Output window will be the terminal executing the OpenOCD GDB Server, not the GDB terminal.

Important Semihosting is not compatible with the use of FreeRTOS.

Example of GDB connection

(gdb) target remote :3333
Remote debugging using :3333
0x08001154 in ?? ()
(gdb) monitor reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08001154 msp: 0x20020000
(gdb) monitor arm semihosting enable
semihosting is enabled
(gdb) file bin/Semihosting.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "bin/ControladorP.elf"? (y or n) y
Reading symbols from bin/Semihosting.elf...done.
(gdb) load
Loading section .isr_vector, size 0x1c4 lma 0x8000000
Loading section .text, size 0x2e60 lma 0x80001c4
Loading section .rodata, size 0x14 lma 0x8003024
Loading section .init_array, size 0x8 lma 0x8003038
Loading section .fini_array, size 0x4 lma 0x8003040
Loading section .data, size 0x430 lma 0x8003044
Start address 0x8000220, load size 13428
Transfer rate: 17 KB/sec, 2238 bytes/write.
(gdb) monitor reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000220 msp: 0x20020000
(gdb) c
Continuing.

Example of use

#include "main.h"

extern void initialise_motor_handles(void);
uint32_t a;

int main(void)
{
  initialise_motor_handles();
  a = 0;
  while(1)
  {
    a++;
    printf("Current value for a is: %d\n", a);
    HAL_Delay(1000);
  }
}

Eclipse Environment

It is mandatory to install the Base Environment first

Install Eclipse

(More info at: http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Fgetting_started%2Fcdt_w_import.htm)

Download last version of Eclipse IDE for C/C++ Developers from: http://www.eclipse.org/downloads/

Untar eclipse:

tar -xvzf eclipse-cpp-mars-1-linux-gtk-x86_64.tar.gz

Go into directory and execute eclipse:

cd eclipse
./eclipse

Define workspace (e.g. /home/<USER>/stm32EclipseWorkspace)

Install C/C++ Developping tools

Go to Help -> Install New Sofware -> add
- Name: CDT-Mars
- Location: http://download.eclipse.org/tools/cdt/releases/8.8


- Click Ok
- Select: CDT Optional Features -> C/C++ GDB Hardware Debugging
- Next, Next, Agree, Finish
- Restart


Install GNU ARM Plugins

Go to Help -> Install New Sofware -> add
- Name: GNU ARM Eclipse Plugins
- Location: http://gnuarmeclipse.sourceforge.net/updates


- Click Ok
- Select All
- Next, Next, Agree, Finish
- You will be asked to accept some specific not known content, do it
- Restart


Import Project

(More info at: http://gnuarmeclipse.github.io/plugins/install/)

Go to File -> New -> C Project
- Name: test
- Location: Select where the code is
- Project type -> Makefile project -> Empty Project -> Cross ARM GCC

- Next, Next

Toolchain:
- Name: GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc)
- Path: /opt/compilerNucleoST (if installed as in previous section, if not check where did you do it!!)

- Finish

If everything ok, you are able to compile with the hammer.

Set OpenOCD

(More info at: https://balau82.wordpress.com/2014/02/23/stm32-p152-development-with-eclipse-on-linux/)

- Run -> External tools -> External Tools Configurations
- Program -> New
- Location: /opt/openocdNucleoST/bin/openocd (if installed as in previous section, if not check where did you do it!!)
- Working Directory: A Dir where there is the openocd.cfg (typically where our porject is)
- Arguments: -f openocd.cfg -c "init" -c "halt" -c "reset halt" - Apply

Set GDB

(More info at: https://pixhawk.org/dev/jtag/gdb_eclipse)

Go to Run -> Debug Configurations
Create a GDB Hardware Debugging
In Main:
- Application: The .elf file that will be generated by the project (e.g. helloWorld.elf)
- Project: The project location
- Use workspace settings
- Select legacy GDB Hardware Debugging Launcher by clinking Select other

In Debugger:
- GDB Command: /opt/compilerNucleoST/bin/arm-none-eabi-gdb
- Standard(Linux)
- Version: mi
- Use remote target
- JTag: TCP/IP
- IP: localhost
- Port: 3333

In Startup:
- Un-click Reset and Delay
- Un-click Halt
- In command box type:
- monitor reset halt
- Click Load Image
- Click Load symbols
- In Run Commands write:
- set $pc = Reset_Handler
- stepi

Finally click Apply