STM32G4xx

Porting Paulus on STM32G4xx

File structure

After installation of Paulus the source code is stored in the file structure shown in Table 1 describes the contents.

directory

description

/paulus_stm32g4xx

project folder with all necessary Keil uVision project files

/bootloader

target independent CANopen sources for Paulus

/eds

Design Tool project of Paulus with all generated files, e.g. the EDS file and documentation files

/stm32g4xx/

target-specific sources of Paulus, e.g. CAN-driver, and low-level drivers and supporting services from STM Corporation e.g. startup, clock, flash-service, usart (HAL-layer)

/stm32g4xx/stm32g4xx_flash.[ch]

target-specific flash routines

/stm32g4xx/stm32g4xx_can.[ch]

CAN routines

/stm32g4xx/stm32g4xx_init.c

CPU initialization

/stm32g4xx/environ.h

header file for the environment definition

/stm32g4xx/bl_config.h

Paulus configuration file

/stm32g4xx/stm32cubeg4_v1_1

STM32cubeG4 HAL-layer v1.1, CMSIS Cortex-M core layer

/stm32g4xx/mdk_keil

Startup file STM32G474xx devices for MDK-Toolchain

/examples

example application for a CANopen slave with all sources and project files

/tools

checksum generator tool for Paulus

main.c

main loop of Paulus

Table 1: description of directories

The initialization of the CAN controller is done in module stm32g4xx / can.c.

In module stm32g4xx / init.c the I/O pins for the CAN interface have to be initialized.

In module stm32g4xx / init.c there must be the functions getBitRate() and getNodeId() available. Usually the CANopen network parameters are provided by reading jumpers or by loading from flash memory.

Development environment

Paulus on the platform of STM32G4xx was developed with the workbench Keil-µVision MDK-ARM v5.26 on a ST Nucleo board STM32G474RE.

Paulus configuration

In general the initialization function initializes only the absolutely necessary peripherals like clock system, CAN controller, memory management as needed by Paulus and a timer for Heartbeat or LSS. Nevertheless, there might be situations where it makes sense that Paulus initializes other functionalities which are later used by the application as well. As an example consider the serial interface for debug messages.

CAN bit rate

The CAN bit rate is coded by the index of the CAN bit timing table according to /CiA-305/. The index of the default CAN bit rate is specified about the compiler-define BITRATE_INDEX_<bit_rate> in / stm32g4xx /bl_config.h:

#define BL_USED_BITRATE_INDEX   BITRATE_INDEX_125K

The default CAN bit rate is 125 kbit/s and can be changed by LSS services. The LSS services are described in /Paulus_man/ and base on /CiA-305/. The supported CAN bit rates are depending on the clock of the CAN controller and are listed in / stm32g4xx/ stm32g4xx_can.c. The value FFh for segment2 marks unsupported CAN bit rates. The clock for the activation of the CAN bit rate is generated by timer Systick with a period of 1 ms.

Heartbeat producer

Timer Systick is also used for the generation of Heartbeat producer messages.

Debug output

By the compiler-define DEBUG a debug output can be activated about the serial interface usart2. The compiler-define is set in file /stm32g4xx/bl_config.h:

#define DEBUG 1

In general the initialization function will initialize only the absolutely necessary peripherals like clock system, CAN controller, memory management as needed by Paulus. Nevertheless, there might be situations where it makes sense that Paulus initializes other functionalities which are later used by the application as well. As an example consider the serial interface for debug messages.

Generating application software

The application software consists of an application header and an application program, see Figure 2.

Figure 1: structure of application software

The application program has to be prepared for download by the following steps:

  •      build the application program in binary format

  • calculate the CRC of the application program, build the application header and generate the application software to download

  • configure the start address of the application software in Paulus

Paulus checksum

The program paulus_cksum calculates the CRC checksum of the binary application program generates the application header and stores the application header and the application program in a new file. This file can be loaded in the device by Paulus. The application must be a binary file. They could e.g. use the tool

hex2bin to convert a created hex file to binary.

Unused bytes in the application header are set to 0x00 with the STM32G4xx. The length of the application header is 256 bytes.

Example: The download file for the application program s1_stm32g4xx_download.bin is generated about Windows console:

C:\jsc\Paulus_STM32G4xx\software\tools>paulus_cksum -v -C -l 256 -x 0x08008800 s1_stm32g4xx.bin -O s1_stm32g4xx_download.bin reduce Flash end to file end: 0x000053bc reduce EndAddr to the Flash end 0x000053bb address - crc: 0x00000000, start: 0x00000000, end: 0x000053bb, exec 0x08008800 Flash end: 0x000053bc out: >s1_stm32g4xx_download.bin< input: >s1_stm32g4xx.bin< calc CRC from 0x00000000 to 0x000053bb size: 0x000053bc, crc: 0x0166 Writing Appl. to >s1_stm32g4xx_download.bin<: length: 21436/0x53bc, crc: 0x0166, execadr: 0x08008800

Besides checking the CRC Paulus checks also the size of the application header. A size of 0 is invalid. An application may destroy the ’valid’ information by overwriting the size with 0. That is always possible on the STM32G4xx FLASH, because the byte content is 0xFF after erasing.

More detailed information from this tool can find in /Paulus_CRC/.

Start address

It is important that the start address of the application software in the flash memory and the information in the Paulus configuration in /stm32g4xx/stm32g4xx_flash.h are identical. The application software is stored as a separate program in the flash memory additionally to the bootloader program. Therefore the application software is flashed to:

#define FLASH_PROGRAM_START_ADR   0x08008700

The length of the application header is 256 byte. The program start of the application is at address (FLASH_PROGRAM_START_ADR + 256 bytes).

Memory

Shared RAM

The shared RAM for data exchange between bootloader and application starts at address 0x2001FFF0. The size of the shared RAM is specified in /stm32g4xx/bl_interface.h by the compiler-define BL_JUMPCODE_SIZE. The shared memory is installed in /stm32g4xx/bl_interface.h as follow:

/* jumpcode placed on ram adress 0x2001FFF0 */

UNSIGNED8 jumpcode[BL_JUMPCODE_SIZE] __attribute__((at(0x2001FFF0)));

The keyword for the re-start of the application program is set in byte 0-3 of jumpcode. Paulus uses the keyword “APPL” or “BOOT” to start the application program, see /Paulus_man/.

Flash

The total size of the STM32G474x flash is 512Kb. The current implementation of Paulus occupies a memory area of 32Kb from this. Therefore, 480Kb (less 0x100 byte crc header and offset) flash memory area available for the application software. The additional memory offset is necessary for the address alignment when moving vector table.

Figure 2: Flash memory mapping

The optionally CANopen service LSS from Paulus used just additional Flash Sector 1 for saving config data (nodeID and bitrate index). This is only a possible design example. But it’s alternatively possible to store this data in an eeprom or other NVM area to get the Sector 1 for the application software free.

The flash area for configuration data of Paulus is current located at address 0x08020000. On this address and the following Paulus stores the node-ID and the CAN bit rate index during the execution of the LSS service “LSS store configuration“. The addresses are configurable in stm32g4xx/bl_interface.h:

#define FLASH_ADDRESS_NODEID 0x08007800 #define FLASH_ADDRESS_BITRATE_INDEX 0x08007804 /* configurations data for Paulus BL */ UNSIGNED8 flashNodeId __attribute__((at(FLASH_ADDRESS_NODEID))); UNSIGNED8 bitrateIndex __attribute__((at(FLASH_ADDRESS_BITRATE_INDEX)));

After the next re-start Paulus uses this node-ID and this CAN bit rate index for communication. The new CAN bit rate cannot be activated by NMT-Command Reset Application. If the LSS services are not used, Paulus uses the node-ID and CAN bit rate index configured in stm32g4xx/bl_config.h.

If the optionally feature used “BL_IDENTITY_OBJECT_1018_READ_FROM_NVM” additional flash area needed. As default last sector from Bank2 at the end of the flash is used. (adaptable by user)

For this additional feature the following sruct is in the Paulus prepared:

/* address of identity (object 0x1018) Block in FLASH */ /* DESIGN EXAMPLE! */ typedef struct {     UNSIGNED32 VendorId;        /* u32 hex - object 0x1018:1  */     UNSIGNED32 ProductCode;     /* u32 hex - object 0x1018:2  */     UNSIGNED32 RevisionNumber;  /* u32 hex - object 0x1018:3  */     UNSIGNED32 SerialNumber;    /* u32 hex - object 0x1018:4  */ } BL_IDENTIY_BLOCK_T; static BL_IDENTIY_BLOCK_T identity_block;

The Paulus fills this struct in startup with the data from the predefined flash area. Starting at address

0x08007000 and following (4 x u32 values). Previously the data was written e.g. via the STM32 ST-Link Utility:

Filled with example data:

After reading the data in the struct these are used for CANopen communication (e.g read items from object 0x1018 - especially for the LSS service).

Example application 

CANopenSlave1 is an example for an application program. The directory example/ CANopenSlave1_STM32g4xx contain the compiler project and the application-specific functions. For compilation the CANopen Library and the suitable driver package is necessary. The CANopen Library and the driver package belong not to the delivery scope of Paulus. The binary application software in example/ CANopenSlave1_STM32g4xx/bin/ s1_stm32g4xx_download.bin can be used for a quick start.

The linker file of this example project is adapted on these memory requirements with the Target dialog from the Keil µVision-IDE.

See settings in scatter-file (s1_stm32g4xx.sct) as output from linker:

This example has included source files bl_interface.c, bl_interface.h from bootloader. The application program can request an update by jumping back into Paulus by writing of the program control command start application program (value 1) on object 1F51h/1. The application program calls the macro BOOTLOADER_JUMP(APPL). This call is implemented in usr_301.c /sdoWrInd(). The application program stores the keyword “APPL” in the shared RAM and jumps into Paulus. Paulus is re-started and stays running until the application program is started by command.

References

/CiA-305/

CANopen Layer Setting Services and Protocols, CiA

/Paulus_CRC/

manual “Paulus Checksum Tool”, see file  tools/manual_cksum.pdf

/Paulus_man/

manual “Paulus User Manual”, see file  UserMan_Paulus_Bootloader_e.pdf

 Table 2: References