STM32 dev: Difference between revisions

From SGMK-SSAM-WIKI
Jump to navigation Jump to search
Line 76: Line 76:
</pre>
</pre>


Now [http://openocd.org/ openocd] and (arm-none-eabi-)gdb can be used to program and debug the MCU! - For example, the [http://www.st.com/st-web-ui/static/active/jp/resource/technical/document/user_manual/DM00099401.pdf STM32 F072 Discovery] has a [http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf STM32F072RBT6] MCU on it. All discovery boards also come with an ST-LINK/V2 programmer right on board speaking over USB to the host and over JTAG/[http://www.arm.com/products/system-ip/debug-trace/coresight-soc-components/serial-wire-debug.php SWD] to the target (note: only two pins are actually required for SWD debugging/flashing! (SWDIO/SWCLK), but that for later (see also [[#Hardware]])). It should show up in the lsusb list like that:
Now [http://openocd.org/ openocd] and (arm-none-eabi-)gdb can be used to program and debug the MCU. All discovery boards also come with an ST-LINK/V2 programmer right built in speaking over USB to the host and over JTAG/[http://www.arm.com/products/system-ip/debug-trace/coresight-soc-components/serial-wire-debug.php SWD] to the target (note: only two pins are actually required for SWD debugging/flashing (SWDIO/SWCLK), but that for later (see also [[#Hardware]])). STM32 Discovery Boards should show up in the lsusb list like that:


$ lsusb
$ lsusb
Line 83: Line 83:
(...)
(...)


OpenOCD can now act as a "middleman" between the ST-LINK programmer and the user, as a server on the host to which you can connect with GDB, telnet etc.
OpenOCD can now act as a "middleman" between the ST-LINK programmer and the user, as a server on the host. And you can now connect to that localhost server with GDB, telnet etc.


To configure OpenOCD put this configuration file into the project folder and start OpenOCD in that terminal, and let it run in the foreground, to see all the logs:
To configure OpenOCD put a configuration file called opencd.cfg needs to be put into the project folder. Start OpenOCD in the project folder, and let it run in the foreground, to see all the logs...
 
For example for the STM32 F072 Discovery board, this should work:
<pre>
<pre>
$ cd <project_directory>
$ cd <project_directory>
Line 108: Line 110:
</pre>
</pre>


(Note that the warnings about the wrong clock speed need to be investigated further...)
(Don't worry about those the warnings about the wrong clock speed for now, needs to be investigated further...)




Line 141: Line 143:


This should write the binary to the flash memory and start the program.
This should write the binary to the flash memory and start the program.
Of course, that can be automated and integrated into an IDE, but that for later...
Of course, that can be automated and integrated into an IDE, but that's for later...




The exported STM32CubeMX main.c was slightly modified to let the user LEDs flash and react to the user pushbutton. Note that pins -- among various other things -- can be customized in the CubeMX editor. Reexporting code to an existing project is straight forward, and can be done easily, while the old Makefile keeps valid for minor changes...
The exported STM32CubeMX main.c was slightly modified to let the user LEDs flash and react to the user pushbutton. Note that pins -- among various other things -- can be customized in the CubeMX editor. Reexporting code to an existing project is straight forward, and can be done easily while the old Makefile keeps valid for minor changes...


<pre>
<pre>
Line 349: Line 351:
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
</pre>
</pre>


=== Debugging ===
=== Debugging ===

Revision as of 23:41, 21 January 2016

Overview

Notes on STM32 microcontrollers and on how to get them working in DIY projects.

/// this is a work in progress draft ///

Software Tools

All about software tools for STM32 dev. Development environments, compilers, debuggers, IDEs etc.

STM32CubeMX on Linux

STM32CubeMX is a code generator for STM32 micros that can come in handy when you start a new project. It generates all the necessary init and HAL code, library and custom pin mux code etc for that specific MCU.

Unfortunately, it comes as a Windows EXE and ST doesn't mention that it is actually a Java application. So, luckily it can be installed on Linux by hand (thanks to 5V Joe's great note there):

  • Download STM32CubeMX.
  • Install the application (tested in January 2016):
$ unzip SetupSTM32CubeMX-4.12.0.exe -d stm32cube
$ cd stm32cube
$ java -cp . com.izforge.izpack.installer.bootstrap.Installer
  • Run:
$ cd <install_dir>
$ java -cp . java -cp . com.st.microxplorer.maingui.STM32CubeMX


Convert STM32CubeMX generated project to GCC/Makefile

For whatever reason, STM32CubeMX does not export plain GCC/Makefiles along with the initialization code. But instead, it supports an unpopular IDE called SW4STM32, which is also based on free GNU tools. So after installing STM32CubeMX, these are the steps to get the GCC/Makefile project running:

  • Install arm-gnu-none-eabi- toolchain for your OS. On Arch Linux:
$ sudo pacman -S arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-binutils arm-none-eabi-newlib
  • Get this nice Python script by Baoshi to generate the Makefile for an exported SW4STM32 project:
$ git clone https://github.com/baoshi/CubeMX2Makefile
$ cd CubeMX2Makefile
$ python2 CubeMX2Makefile.py <your_sw4stm32_prject_dir>
$ cd <your_sw4stm32_prject_dir>


  • Modify the Makefile (tested in January 2016). Look for __weak and remove the backslashes (needed, at least in Bash). More can be read here.
$ grep __weak Makefile 
C_DEFS = -D__weak="__attribute__\(\(weak\)\)" -D__packed="__attribute__\(\(__packed__\)\)" -DUSE_HAL_DRIVER -DSTM32F072xB
$ sed -i 's/\\(\\(weak\\)\\)/((weak))/g' Makefile 
$ sed -i 's/\\(\\(packed\\)\\)/((packed))/g' Makefile 
$ grep __weak Makefile 
C_DEFS = -D__weak="__attribute__((weak))" -D__packed="__attribute__\(\(__packed__\)\)" -DUSE_HAL_DRIVER -DSTM32F072xB
  • Then make the binary:
$ make
(...)
arm-none-eabi-size build/STM32F072RBT6.elf
   text	   data	    bss	    dec	    hex	filename
   4568	     12	   1572	   6152	   1808	build/STM32F072RBT6.elf
arm-none-eabi-objcopy -O ihex build/STM32F072RBT6.elf build/STM32F072RBT6.hex
arm-none-eabi-objcopy -O binary -S build/STM32F072RBT6.elf build/STM32F072RBT6.bin	

Flash

Install OpenOCD and STLINK. On Arch Linux:

sudo pacman -S stlink openocd

Now openocd and (arm-none-eabi-)gdb can be used to program and debug the MCU. All discovery boards also come with an ST-LINK/V2 programmer right built in speaking over USB to the host and over JTAG/SWD to the target (note: only two pins are actually required for SWD debugging/flashing (SWDIO/SWCLK), but that for later (see also #Hardware)). STM32 Discovery Boards should show up in the lsusb list like that:

$ lsusb (...) Bus 003 Device 006: ID 0483:3748 STMicroelectronics ST-LINK/V2 (...)

OpenOCD can now act as a "middleman" between the ST-LINK programmer and the user, as a server on the host. And you can now connect to that localhost server with GDB, telnet etc.

To configure OpenOCD put a configuration file called opencd.cfg needs to be put into the project folder. Start OpenOCD in the project folder, and let it run in the foreground, to see all the logs...

For example for the STM32 F072 Discovery board, this should work:

$ cd <project_directory>
$ echo "source [find board/stm32f0discovery.cfg]" > openocd.cfg
$ openocd
Open On-Chip Debugger 0.9.0 (2015-05-19-13:50)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.896454
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints

(Don't worry about those the warnings about the wrong clock speed for now, needs to be investigated further...)


Now, in another console, connect to OpenOCD via telnet:

$ telnet localhost 4444
Trying ::1...
Connection failed: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset halt
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0x080014d0 msp: 0x20004000
> flash probe 0
device id = 0x20016448
flash size = 128kbytes
flash 'stm32f1x' found at 0x08000000
> flash write_image erase build/STM32F072RBT6.elf
auto erase enabled
target state: halted
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20004000
wrote 6144 bytes from file build/STM32F072RBT6.elf in 0.503961s (11.906 KiB/s)
> reset run
> exit
Connection closed by foreign host.
$

This should write the binary to the flash memory and start the program. Of course, that can be automated and integrated into an IDE, but that's for later...


The exported STM32CubeMX main.c was slightly modified to let the user LEDs flash and react to the user pushbutton. Note that pins -- among various other things -- can be customized in the CubeMX editor. Reexporting code to an existing project is straight forward, and can be done easily while the old Makefile keeps valid for minor changes...

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

    uint32_t delay;
    if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_SET )
      delay = 50;
    else
      delay = 250;

    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_9 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_8 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_7 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_6 );
    HAL_Delay( delay );

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __GPIOA_CLK_ENABLE();
  __GPIOC_CLK_ENABLE();

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PC6 PC7 PC8 PC9 */
  GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Debugging

GDB can be used to debug the code right on the hardware. While OpenOCD is running, you can connect to the target like this and step through the program:

$ arm-none-eabi-gdb -tui build/STM32F072RBT6.elf
(...)
Reading symbols from build/STM32F072RBT6.elf...done.

(gdb) target remote :3333
Remote debugging using :3333
Python Exception <type 'exceptions.NameError'> Installation error: gdb.execute_u
nwinders function is missing:
HAL_GetTick () at Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c:298

(gdb) c
Continuing.

Program received signal SIGINT, Interrupt.
0x080002f6 in HAL_Delay (Python Exception <type 'exceptions.NameError'> Installa
tion error: gdb.execute_unwinders function is missing:
Delay=250)
    at Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c:317

(gdb) break main.c:91
Breakpoint 1 at 0x8001392: file Src/main.c, line 91.

(gdb) c
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Python Exception <type 'exceptions.NameError'> Installation error: gdb.execute_u
nwinders function is missing:

Breakpoint 1, main () at Src/main.c:91

(...)
(gdb) detach
(qdb) quit
$

(Note: the -tui option is really great to inspect the code...)


Links


Hardware

/todo

  • Minimal STM32
  • JTAG
  • Serial

.....


Projects

/todo

  • bare metal hello blink
  • I2C peripherals
  • I2S peripherals
  • SPI peripherals
  • touch
  • usb

.....