Skip to content

Basic LED Output and UART Communication Program. Startup Functionality is Modified Using Thumb Instruction Set on ARM Cortex-M4 Core Processor. Vector Table is Relocated to SRAM. Project is Built and Debugged with ARM GCC Tools on OpenOCD Server.

Notifications You must be signed in to change notification settings

Dipto9999/STM32_Cortex_M4-Startup_Test

Repository files navigation

STM32 and ARM Cortex-M4 Startup Test

Contents

Overview

A basic project is implemented to blink the LD2 LED pin on the STM32401RE and communicate with the computer via UART Serial Communication. This involved sending a simple "Hello World" message to a serial COM port at the press of the B1 User Button.

The startup functionality was modified using the Thumb Instruction Set on the ARM Cortex-M4 Core processor. This was done by going into the ASM and modifying it into C code and by relocating the Vector Table from flash memory to static random-access memory (i.e. SRAM).

Installations

STM32CubeMX

The project files were generated using the STM32CubeMX Graphical Tool Software. The project configuration can be viewed and modified in the (Startup_Test.ioc) file.

The USART2 peripheral is configured in Asynchronous Mode. We selected the Makefile toolchain to work with individually installed tools on the VSCode Editor.

Build Tools

Flashing the project onto the STM32 Nucleo Board required the ARM GCC C Compiler, Make Automation Tool, and the Open On-Chip Debugger (OpenOCD) Debugger for Embedded Devices.

These tools were added to the System Path on the Windows OS.

VSCode Editor

This project build and debug settings are specified in the (.vscode) directory. The (launch.json) and (c_cpp_properties.json) were modified to integrate the debug functionality into VSCode.

The Cortex-Debug Extension made it easier to look at register contents during runtime.

Importing the System View Description from the (STM32F401.svd) file in the launch settings gave the ability to view the peripheral register values during runtime as well.

Startup Modification

The startup of the project was later optimized by translating the relevant functionality of the (startup_stm32f401xe.s) ASM file in the (startup_stm32f401xe.c) C file.

This required importing externally defined constants for memory addresses from the linker script (STM32F401RETx_FLASH.ld).

// Start Address For the Initialization Values of the .data Section.
extern uint32_t _sidata;
// Start Address For the .data Section.
extern uint32_t _sdata;
// End Address For the .data Section.
extern uint32_t _edata;
// Start Address For the .bss Section.
extern uint32_t _sbss;
// End Address for the .bss Section.
extern uint32_t _ebss;
// Top of Stack.
extern uint32_t _estack;

Reset Handler

The void Reset_Handler(); function is run when the program is flashed onto the MCU. This acts as the real entry point of our program before continuing onto our int main(void); function. .

This initializes the data (i.e.initialized data) and bss (i.e. uninitialized data) segments of the flash memory. We explicitly run the void SystemInit(); function from the ST Board Support Package and void __libc_init_array(); to initialize the static objects and run their constructors.

Vector Table

We provide weak definitions for our Hardware Interrupts as function pointers as shown:

__weak void NMI_Handler(void) { Default_Handler(); }
__weak void HardFault_Handler(void) { Default_Handler(); }
__weak void MemManage_Handler(void) { Default_Handler(); }
__weak void BusFault_Handler(void) { Default_Handler(); }
...
...
__weak void SPI4_IRQHandler(void) { Default_Handler(); }

The functions defined here will be overwritten if there are other functions with the same name.

We allocate the Hardware Interrupts as a vector in a section in flash memory. This tells the processor where to jump in flash memory with the following lines of code:

__attribute__((section(".isr_vector")))
const void(*VectorTable[])(void) = { ... }

Based on the STM32F40x Datasheet, we fill in the Vector Table with the interrupt order specified in Table 43. Vector Table for STM32F40x and STM3241x.

The reference to the ASM startup file was removed and the reference to the C startup file was added in the (Makefile).

Memory Relocation

The Vector Table was later relocated from flash memory to static random-access memory (i.e. SRAM). This was done by modifying the Vector Table Offset Register (i.e. VTOR) in the (system_stm32f4xx.c) source file.

We modify the System Control Block (i.e. SCB), which provides system implementation information and system control. It can be accessed only from a privileged thread. This is done with the following line of code.

SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;

SRAM

SRAM is volatile memory, which means that data is lost when the power is removed. Due to this, we copy the Vector Table from the flash memory to SRAM.

This allows dynamically changing Exception Handler entrance points during runtime. Also, if the flash memory is very slow, this allows for faster vector fetch.

For ARM Cortex-M4 Core processors, the Vector Table is of the format below, where IRQ0 ... IRQ239 are the starting addresses for Device Specific Interrupt Service Routines (i.e. ISR).

We use the GDB Debug Console to set breakpoints in the void SystemInit(); function. We write the command x/256xw 0x08000000 and view 256 Words of memory written at the starting address of the flash memory.

We see that the Vector Table occupies memory addresses from 0x08000000 to 0x0800019C in flash memory. This is equivalent to 412 Bytes occupied by 104 unique entries in the Vector Table. From this, we know to copy 104 Words of data in the void CopyVectTab(...); function.

Now, we use the GDB Debug Console to write the command x/104xw 0x20000200 and view 104 Words of memory written at the offset address in SRAM.

SysTick Handler

The Cortex-M4 Programming Manual provided by STMicroelectronics states that SysTick Exception is generated when the 24-Bit SysTick Timer (i.e. STK) counts down from the reload value to 0. The SysTick Timer (i.e. STK) reloads this value on the subsequent clock edge and counts down again.

Let's use our Debug Console to see if the SysTick Vector holds the starting address of its Exception Handler. We first run the GDB command x/xw 0x2000023C to determine the intended starting address, 0x80006B8. Note that the starting address is stored in the Vector Table as 0x80006B9 to inform the processor that it's executing a Thumb Instruction.

Then we run command disassemble 0x80006B8 to verify this is the starting address of the void SysTick_Handler(void); function as shown below.

We see that the Vector Table copied to SRAM matches that in flash memory and that it maps the starting addresses of the Exception Handlers. From this, we assume we are successful at this stage.

Dynamic Relocation

The PendSV Exception Type is a request for system-level service that's used for context switching between threads when other exceptions are inactive. As for the SysTick Vector, we determine the PendSV Vector to be located at address 0x20000238. From this, we determine the PendSV Handler starting address to be 0x80006B6.

While debugging, we can write the command set {int}0x2000023C = 0x80006B7. This will instead store the starting address of the PendSV Handler at the SysTick Vector, with the Least Significant Bit (i.e. LSB) set to 1 to indicate the Thumb Instruction. By setting a breakpoint in the void PendSV_Handler(void); function, we can see this on the next system tick.

Flash Executable

Flashing the (Startup_Test.elf) executable onto the STM32 Nucleo Board required modifying the (Makefile) to include the make flash command.

#######################################
# flash
#######################################
flash: all
	openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program $(BUILD_DIR)/$(TARGET).elf verify reset exit"

Serial Communication

The PuTTY SSH client is used to establish a terminal connection with the STM32 device as shown below.

Demonstration

The videos in the Demonstration directory show the UART Communication as well as the output on the STM32 Nucleo Board. I have embedded a low resolution compressed version below.

Compressed_Flash_Board.mp4

Credit

This project was created and tested following tutorials from the EmbeddedGeek Youtube Channel as well as the Foundations of Embedded Systems with ARM Cortex and STM32 Udemy Course.

About

Basic LED Output and UART Communication Program. Startup Functionality is Modified Using Thumb Instruction Set on ARM Cortex-M4 Core Processor. Vector Table is Relocated to SRAM. Project is Built and Debugged with ARM GCC Tools on OpenOCD Server.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages