Difference between revisions of "Nucleo Boards"

From RobolaboWiki
Jump to: navigation, search
m (Semihosting en STM32F4)
(Replaced content with "__TOC__ <h1> Installing the environment </h1> <h2> Linux </h2> <h2> Windows </h2> <h2> MAC </h2>")
Line 1: Line 1:
 
__TOC__
 
__TOC__
  
<h1> Configuring the environment </h1>
+
<h1> Installing the environment </h1>
 
+
<h2> Linux </h2>
<h2> Install Compiler gcc-arm-none-eabi </h2>
+
<h2> Windows </h2>
 
+
<h2> MAC </h2>
Install the following libraries:
+
 
+
<pre>
+
sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0
+
</pre>
+
 
+
Download last version of GCC ARM Embedded from:
+
https://launchpad.net/gcc-arm-embedded/+download
+
 
+
Untar the compiler:
+
<pre>
+
tar -xvjf gcc-arm-none-eabi-<VERSION>.tar.bz2
+
</pre>
+
 
+
Copy it to a common place:
+
 
+
<pre>
+
sudo cp -r gcc-arm-none-eabi-<VERSION> /opt/compilerNucleoST
+
</pre>
+
 
+
<h2> Install OpenOCD On-Chip Debugger</h2>
+
 
+
Instal dependencies:
+
<pre>
+
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
+
</pre>
+
 
+
Download last version of Openocd from:
+
http://openocd.org/
+
 
+
Untar openocd:
+
<pre>
+
tar -xvzf openocd-<VERSION>.tar.gz
+
</pre>
+
 
+
Go into the directory:
+
<pre>
+
cd openocd-<VERSION>
+
</pre>
+
 
+
Configure openocd compilation:
+
<pre>
+
./configure --prefix=/opt/openocdNucleoST --enable-maintainer-mode --enable-stlink
+
</pre>
+
 
+
Compile it:
+
<pre>
+
make
+
</pre>
+
 
+
Install:
+
<pre>
+
sudo make install
+
</pre>
+
 
+
Prepare its use according to udev:
+
<pre>
+
sudo cp -r contrib/99-openocd.rules /etc/udev/rules.d/
+
sudo udevadm control --reload-rules
+
</pre>
+
 
+
In order to run openocd as a non root user, you must to add your user name to plugdev group.
+
<ul>
+
<li> Edit /etc/group </li>
+
<li> Find plugdev </li>
+
<li> 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)
+
</ul>
+
 
+
For connection, check in [http://wiki.robolabo.etsit.upm.es/index.php/Nucleo_Boards#GDB_Debug  GDB Section]
+
 
+
 
+
<!-- In order to connect to the device:
+
<pre>
+
openocd -s /opt/openocdNucleoST/share/openocd/scripts/ -f openocd.cfg -c "init" -c "halt" -c "reset halt"
+
</pre>
+
where openocd.cfg should be on your working dir. -->
+
 
+
<h1> Hello World experiment  </h1>
+
 
+
<h2> Download STMCube </h2>
+
 
+
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:
+
 
+
<pre>
+
unzip stm32cubexx.zip
+
</pre>
+
 
+
This will create a Firmware directory which will be referred in this tutorial as <STM32_CUBE_FW_ROOTDIR>.
+
 
+
<h2> Create the experiment </h2>
+
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:
+
 
+
<pre>
+
mkdir helloWorld
+
mkdir helloWorld/bin
+
</pre>
+
 
+
Copy experiment sources:
+
 
+
<pre>
+
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
+
</pre>
+
 
+
Copy STM32 libraries:
+
 
+
<pre>
+
cp -r <STM32_CUBE_FW_ROODIR>/Drivers/ helloWorld/lib
+
</pre>
+
 
+
Copy startup code to src dir:
+
<pre>
+
cp <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Templates/SW4STM32/startup_<NUCLEO_BOARD>.s helloWorld/src
+
</pre>
+
 
+
where <NUCLE_BOARD> refers to your nucleo board model.
+
 
+
<b> Important</b> If SW4STM32 does not exists use TrueStudio instead.
+
 
+
<br>
+
Copy linker file:
+
 
+
<pre>
+
cp <STM32_CUBE_FW_ROOTDIR>/Projects/<BOARD>/Templates/SW4STM32/<BOARD>_Nucleo/<NUCLEO_BOARD>_FLASH.ld helloWorld/
+
</pre>
+
where <NUCLE_BOARD> refers to your nucleo board model.
+
 
+
<b> Important</b> If TrueStudio does not exists use SW4STM32 instead.
+
 
+
<br>
+
Create an environment file to export PATH:
+
<pre>
+
cd helloWorld
+
echo $PATH > env.sh
+
</pre>
+
Edit env.sh and at the begining of the line include:
+
 
+
<pre>
+
export PATH=/opt/openocdNucleoST/bin:/opt/compilerNucleoST/bin:
+
</pre>
+
 
+
Your file should look like this:
+
<pre>
+
export PATH=/opt/openocdNucleoST/bin:/opt/compilerNucleoST/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
+
</pre>
+
 
+
Download [[media:makefileNucleoST2.make | <i> Makefile</i>]], rename it as "Makefile" and copy it to <HELLOWORLD> dir.
+
 
+
Open makefile and substitute:
+
 
+
<ul>
+
<li> <b> <PROJECT_NAME> </b> with the name you want to give to your project
+
<li> <b> <STM32_NUCLEO_BOARD> </b> with the nucleo board name (e.g. STM32F4xx).
+
<li> <b> <STM32_LNKER_FILE> </b> with the name of the linker file in <HELLOWORLD> dir (e.g. STM32F446RETx_FLASH.ld)
+
<li> <b> <STM32_MICROCONTROLLER> </b> 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)
+
<li> <b> <CPU_INFO> </b> with the mcpu of the controller found in <i> src/startup_stm32XXX </i> file near the <i> .cpu </i> directive (e.g. cortex-m0plus)
+
<li> <b> <STARTUP_NAME> </b> with the name of your startup filename. (e.g. startup_stm32f446xx) found in src dir (important: name it without extension).
+
</ul>
+
 
+
<b> Important </b> If working with Cortex-M4 add the following lines to the CFLAGS definition:
+
 
+
<pre>
+
-mfpu=fpv4-sp-d16 \
+
-mfloat-abi=softfp \
+
</pre>
+
 
+
After this, everything should be ready:
+
 
+
Export you <i>PATH</i>
+
<pre>
+
source env.sh
+
</pre>
+
 
+
Compile:
+
<pre>
+
make
+
</pre>
+
 
+
Copy the bin/<FILE>.bin to the disc that is created when the board is connected to the PC.
+
An LED should be blinking.
+
 
+
<b> NOTE </b> It is interesting to clean the project before submitting to any repository.
+
<i> lib </i> dir is full of unusfull information:
+
<ul>
+
<li> In <i> lib/BSP </i> keep only the dir that refers to your board
+
<li> In <i> lib/CMSIS </i> keep only the <i> Device </i> and <i> Include </i> dirs
+
<li> In <i> lib/HAL_DRIVER </i> dir, keep  only the <i> Inc </i> and <i> Src </i> dirs.
+
</ul>
+
 
+
<h1> FreeRTOS Port  </h1>
+
 
+
Before proceed with this section, you should have already implemented the [http://wiki.robolabo.etsit.upm.es/index.php/Nucleo_Boards#Hello_World_experiment previous section]
+
 
+
<h2> Download and prepare sources </h2>
+
 
+
Download last version of FreeRTOS from: http://www.freertos.org/
+
 
+
Unzip it:
+
<pre>
+
unzip FreeRTOS<VERSION>.zip
+
</pre>
+
 
+
Copy FreeRTOS source to your working dir
+
<pre>
+
cp -r <FREERTOS_DIR>/FreeRTOS/ helloWorld/
+
</pre>
+
 
+
Go in <i> helloworld/FreeRTOS </i> dir and remove all but <i> Source </i> dir
+
 
+
Go in <i> helloworld/FreeRTOS/Source/portable </i> dir and remove all but <i> GCC </i> dir and <i> <MemMag> </i> dir
+
 
+
Go in <i> helloworld/FreeRTOS/Source/portable/GCC </i> dir and remove all but your CPU related (e.g. ARM_C0 for Cortex-M0)
+
 
+
 
+
<h2> Configure FreeRTOS </h2>
+
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 <i> FreeRTOSConfig.h </i> found in those examples to your <i> helloworld/include </i> dir.
+
 
+
If not, download this [[media:FreeRTOSConfig_STM32L0.h | <i> FreeRTOSConfig.h </i>]], rename it as "FreeRTOSConfig.h", copy it to <i> <HELLOWORLD>/include </i> dir and work on it.
+
 
+
Go in your <i> helloworld/src/stmXXXX_it.c </i> file and comment the <i> SVC_Handler, PendSV_Handler and SysTick_Handler </i> functions
+
 
+
Download [[media:makefileNucleoST2FreeRTOS.make | <i> Makefile</i>]], rename it as "Makefile" and copy it to <HELLOWORLD> dir.
+
 
+
Open makefile and substitute:
+
 
+
<ul>
+
<li> <b> <PROJECT_NAME> </b> with the name you want to give to your project
+
<li> <b> <STM32_NUCLEO_BOARD> </b> with the nucleo board name (e.g. STM32F4xx).
+
<li> <b> <STM32_LNKER_FILE> </b> with the name of the linker file in <HELLOWORLD> dir (e.g. STM32F446RETx_FLASH.ld)
+
<li> <b> <STM32_MICROCONTROLLER> </b> 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)
+
<li> <b> <CPU_INFO> </b> with the mcpu of the controller found in <i> src/startup_stm32XXX </i> file near the <i> .cpu </i> directive (e.g. cortex-m0plus)
+
<li> <b> <STARTUP_NAME> </b> with the name of your startup filename. (e.g. startup_stm32f446xx) found in src dir (important: name it without extension).
+
<li> <b> <RTOS_GCC_CPUINFO> </b> with the name of the mcpu of the controller of the FreeRTOS dir (e.g. ARM_CM0) found in <i> RTOS_SOURCE_DIR/portable/GCC/ </i>
+
</ul>
+
 
+
<b> Important </b> If working with Cortex-M4 add the following lines to the CFLAGS definition:
+
 
+
<pre>
+
-mfpu=fpv4-sp-d16 \
+
-mfloat-abi=softfp \
+
</pre>
+
 
+
<h2> Create a Basic Task </h2>
+
 
+
Open your <i> main.c </i>
+
 
+
Include FreeRTOS libs:
+
 
+
<pre>
+
/* Scheduler includes. */
+
#include "FreeRTOS.h"
+
#include "task.h"
+
#include "queue.h"
+
#include "semphr.h"
+
</pre>
+
 
+
Define a task and its handler
+
 
+
<pre>
+
xTaskHandle ledpTask_Handle;
+
void Ledp_Task();
+
</pre>
+
 
+
In the <i>main</i> function, comment the while loop and provide instead the following code to create a task and start the scheduler:
+
 
+
<pre>
+
xTaskCreate(Ledp_Task, "Ledp_Task", 70, NULL, 1, &ledpTask_Handle);
+
vTaskStartScheduler();
+
</pre>
+
 
+
Create a Task (function) with the following code:
+
<pre>
+
void Ledp_Task (void * pvParams)
+
{
+
  while(1)
+
  {
+
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
+
    vTaskDelay(1000);
+
  }
+
}
+
 
+
</pre>
+
 
+
After this, everything should be ready:
+
 
+
Export you <i>PATH</i>
+
<pre>
+
source env.sh
+
</pre>
+
 
+
Compile:
+
<pre>
+
make
+
</pre>
+
 
+
Copy the bin/<FILE>.bin to the disc that is created when the board is connected to the PC.
+
An LED should be blinking.
+
 
+
<h1> GDB Debug </h1>
+
 
+
It is mandatory openocd is installed in your system (see [http://wiki.robolabo.etsit.upm.es/index.php/Nucleo_Boards#Install_OpenOCD_On-Chip_Debugger OpenOCD section])
+
 
+
You need an openocd.cfg file which is related to your board and jtag.
+
 
+
[[media:openocdL0.cfg | <i> Here</i>]] we provide a file with the configuration of an stlink and a STM32L053 mcu:
+
 
+
<pre>
+
source [find interface/stlink-v2-1.cfg]
+
 
+
transport select hla_swd
+
 
+
set WORKAREASIZE 0x2000
+
source [find target/stm32l0.cfg]
+
 
+
reset_config srst_only
+
</pre>
+
 
+
However, find your jtag filename in <i>interface</i> of your openocd sources and your mcu filename on the <i>target</i> dir.
+
 
+
Once the file is configured, load the PATH
+
 
+
<pre>
+
source env.sh
+
</pre>
+
 
+
Connect to your board:
+
 
+
<pre>
+
openocd -s /opt/openocdNucleoST/share/openocd/scripts/ -f openocd.cfg -c "init" -c "halt" -c "reset halt"
+
</pre>
+
 
+
Output should be something similar to:
+
 
+
<pre>
+
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
+
</pre>
+
 
+
If the terminal gets there and does not return, you are now connected to the board.
+
 
+
Open a new terminal and load the PATH
+
 
+
<pre>
+
source env.sh
+
</pre>
+
 
+
Launch ARM GDB
+
<pre>
+
arm-none-eabi-gdb
+
</pre>
+
 
+
Connect GDB to openocd
+
<pre>
+
target remote :3333
+
</pre>
+
 
+
Reset the board
+
<pre>
+
monitor reset halt
+
</pre>
+
 
+
Import the file
+
<pre>
+
file bin/ledp.elf
+
</pre>
+
 
+
Load the binaries into the mcu
+
 
+
<pre>
+
load
+
</pre>
+
 
+
Reset the board
+
<pre>
+
monitor reset halt
+
</pre>
+
 
+
 
+
Run the board
+
<pre>
+
continue
+
</pre>
+
 
+
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>
+
It is mandatory to install the Base Environment first
+
 
+
<h2> Install Eclipse </h2>
+
(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:
+
<pre>
+
tar -xvzf eclipse-cpp-mars-1-linux-gtk-x86_64.tar.gz
+
</pre>
+
 
+
Go into directory and execute eclipse:
+
 
+
<pre>
+
cd eclipse
+
./eclipse
+
</pre>
+
 
+
Define workspace (e.g. /home/<USER>/stm32EclipseWorkspace)
+
 
+
<h3> Install C/C++ Developping tools </h3>
+
 
+
Go to Help -> Install New Sofware -> add <br>
+
- Name: CDT-Mars <br>
+
- Location: http://download.eclipse.org/tools/cdt/releases/8.8 <br>
+
 
+
 
+
- Click Ok <br>
+
- Select: CDT Optional Features -> C/C++ GDB Hardware Debugging <br>
+
- Next, Next, Agree, Finish <br>
+
- Restart <br>
+
 
+
<br>
+
<h3> Install GNU ARM Plugins </h3>
+
 
+
Go to Help -> Install New Sofware -> add <br>
+
- Name: GNU ARM Eclipse Plugins <br>
+
- Location: http://gnuarmeclipse.sourceforge.net/updates <br>
+
 
+
 
+
- Click Ok <br>
+
- Select All <br>
+
- Next, Next, Agree, Finish <br>
+
- You will be asked to accept some specific not known content, do it <br>
+
- Restart <br>
+
 
+
 
+
<h2> Import Project </h2>
+
(More info at: http://gnuarmeclipse.github.io/plugins/install/)
+
 
+
Go to File -> New -> C Project <br>
+
- Name: test <br>
+
- Location: Select where the code is <br>
+
- Project type -> Makefile project -> Empty Project -> Cross ARM GCC <br>
+
 
+
- Next, Next <br>
+
 
+
Toolchain: <br>
+
- Name: GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc) <br>
+
- Path: /opt/compilerNucleoST (if installed as in previous section, if not check where did you do it!!) <br>
+
 
+
- Finish <br>
+
 
+
If everything ok, you are able to compile with the hammer.
+
 
+
<h2> Set OpenOCD </h2>
+
(More info at: https://balau82.wordpress.com/2014/02/23/stm32-p152-development-with-eclipse-on-linux/)
+
 
+
- Run -> External tools -> External Tools Configurations <br>
+
- Program -> New <br>
+
- Location: /opt/openocdNucleoST/bin/openocd (if installed as in previous section, if not check where did you do it!!) <br>
+
- Working Directory: A Dir where there is the openocd.cfg (typically where our porject is) <br>
+
- Arguments: -f openocd.cfg -c "init" -c "halt" -c "reset halt"
+
- Apply
+
 
+
<h2> Set GDB </h2>
+
(More info at: https://pixhawk.org/dev/jtag/gdb_eclipse)
+
 
+
Go to Run -> Debug Configurations <br>
+
Create a GDB Hardware Debugging <br>
+
In Main: <br>
+
- Application: The .elf file that will be generated by the project (e.g. helloWorld.elf) <br>
+
- Project: The project location <br>
+
- Use workspace settings <br>
+
- Select legacy GDB Hardware Debugging Launcher by clinking Select other <br>
+
 
+
In Debugger: <br>
+
- GDB Command: /opt/compilerNucleoST/bin/arm-none-eabi-gdb <br>
+
- Standard(Linux) <br>
+
- Version: mi <br>
+
- Use remote target <br>
+
- JTag: TCP/IP <br>
+
- IP: localhost <br>
+
- Port: 3333 <br>
+
 
+
In Startup: <br>
+
- Un-click Reset and Delay <br>
+
- Un-click Halt <br>
+
- In command box type:  <br>
+
- monitor reset halt <br>
+
- Click Load Image <br>
+
- Click Load symbols <br>
+
- In Run Commands write: <br>
+
- set $pc = Reset_Handler <br>
+
- stepi <br>
+
 
+
Finally click Apply
+

Revision as of 08:06, 29 July 2019

Installing the environment

Linux

Windows

MAC