1
0
mirror of https://github.com/rfivet/stm32bringup.git synced 2024-12-20 15:58:44 -05:00
stm32bringup/docs/18_3stages.html

266 lines
7.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1.8 Three-stage Rocket</title>
<link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>
<h1>1.8 Three-stage Rocket</h1>
As I merge the cstartup with the ledtick code, I split the
functionalities between three files according to the three phases: boot,
initialization and main execution.
<ul>
<li> <b>startup.c</b> is mainly concerned with the early set up of the board:
initializing the memory, calling system initialization and then
executing the main C function if initialization is successful.
</ul><ul>
<li> <b>init.c</b> holds the middleware implementation and will abstract the
peripherals into higher level interfaces. Its entry point is the
<code>init()</code> function.
</ul><ul>
<li> the <code>main()</code> C function will be the focus of the last file and
it should be written in a subset of standard C. As an example I will use
<b>success.c</b>.
</ul>
<pre>
/* success.c -- success does nothing, successfully */
#include &lt;stdlib.h>
int main( void) {
return EXIT_SUCCESS ;
}
</pre>
<h2>startup.c</h2>
Beside the interrupt vector and the <code>Reset_Handler()</code> that calls
<code>init()</code> and <code>main()</code>, I have created stubs for all the
System Exceptions listed in the Programming Manual. For those, if there is no
implementation avalable in <b>init.c</b>, the linker will use the
<code>Default_Handler()</code> provided with the <code>__attribute__()</code>
Gnu C extension.
<pre>
/* Memory locations defined by linker script */
extern long __StackTop ; /* &__StackTop points after end of stack */
void Reset_Handler( void) ; /* Entry point for execution */
extern const long __etext[] ; /* start of initialized data copy in flash */
extern long __data_start__[] ;
extern long __bss_start__[] ;
extern long __bss_end__ ; /* &__bss_end__ points after end of bss */
/* Stubs for System Exception Handler */
void Default_Handler( void) ;
#define dflt_hndlr( fun) void fun##_Handler( void) \
__attribute__((weak,alias("Default_Handler")))
dflt_hndlr( NMI) ;
dflt_hndlr( HardFault) ;
dflt_hndlr( SVCall) ;
dflt_hndlr( PendSV) ;
dflt_hndlr( SysTick) ;
/* Interrupt vector table:
* 1 Stack Pointer reset value
* 15 System Exceptions
* NN Device specific Interrupts
*/
typedef void (*isr_p)( void) ;
isr_p const isr_vector[ 16] __attribute__((section(".isr_vector"))) = {
(isr_p) &__StackTop,
/* System Exceptions */
Reset_Handler,
NMI_Handler,
HardFault_Handler,
0, 0, 0, 0, 0, 0, 0,
SVCall_Handler,
0, 0,
PendSV_Handler,
SysTick_Handler
} ;
extern int init( void) ;
extern int main( void) ;
void Reset_Handler( void) {
const long *f ; /* from, source constant data from FLASH */
long *t ; /* to, destination in RAM */
/* Assume:
** __bss_start__ == __data_end__
** All sections are 4 bytes aligned
*/
f = __etext ;
for( t = __data_start__ ; t < __bss_start__ ; t += 1)
*t = *f++ ;
while( t < &__bss_end__)
*t++ = 0 ;
if( init() == 0)
main() ;
for( ;;)
__asm( "WFI") ; /* Wait for interrupt */
}
void Default_Handler( void) {
for( ;;) ;
}
</pre>
Except for the future addition of stubs to handle the device specific
interrupts, this file will not grow much anymore.
<h2>init.c</h2>
This is the embryo of an hardware abstraction layer where most of the
device specific code will be added. The current code is the peripherals
part of <b>ledtick.c</b>.
<pre>
#define SYSTICK ((volatile long *) 0xE000E010)
#define SYSTICK_CSR SYSTICK[ 0]
#define SYSTICK_RVR SYSTICK[ 1]
#define SYSTICK_CVR SYSTICK[ 2]
#define RCC ((volatile long *) 0x40021000)
#define RCC_AHBENR RCC[ 5]
#define RCC_AHBENR_IOPBEN 0x00040000 /* 18: I/O port B clock enable */
#define GPIOB ((volatile long *) 0x48000400)
#define GPIOB_MODER GPIOB[ 0]
#define GPIOB_ODR GPIOB[ 5]
int init( void) {
/* By default SYSCLK == HSI [8MHZ] */
/* SYSTICK */
SYSTICK_RVR = 1000000 - 1 ; /* HBA / 8 */
SYSTICK_CVR = 0 ;
SYSTICK_CSR = 3 ; /* HBA / 8, Interrupt ON, Enable */
/* SysTick_Handler will execute every 1s from now on */
/* User LED ON */
RCC_AHBENR |= RCC_AHBENR_IOPBEN ; /* Enable IOPB periph */
GPIOB_MODER |= 1 << (1 * 2) ; /* PB1 Output [01], over default 00 */
/* OTYPER Push-Pull by default */
/* PB1 output default LOW at reset */
return 0 ;
}
void SysTick_Handler( void) {
GPIOB_ODR ^= 1 << 1 ; /* Toggle PB1 (User LED) */
}
</pre>
<h2>Makefile</h2>
As I now build from multiple source files, I have modified the
<b>Makefile</b> to list the sources that combine together. All steps I have
done so far can be found in the commented <code>SRCS</code> lines. Single file
steps can be build explicitly (<code>make ledon.hex</code>) or implicitly
(<code>make</code>) after removing the comment on the corresponding
<code>SRCS</code> line. Multiple file steps can only be build implicitly when
their <code>SRCS</code> line is uncommented.
<pre>
### Build environment selection
ifeq (linux, $(findstring linux, $(MAKE_HOST)))
GCCDIR = $(HOME)/Packages/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi
else
GCCDIR = "D:/Program Files (x86)/GNU Arm Embedded Toolchain/arm-gnu-toolchain-13.3.rel1-mingw-w64-i686-arm-none-eabi"
endif
BINPFX = @$(GCCDIR)/bin/arm-none-eabi-
CC = $(BINPFX)gcc
LD = $(BINPFX)ld
OBJCOPY = $(BINPFX)objcopy
OBJDUMP = $(BINPFX)objdump
SIZE = $(BINPFX)size
### STM32F030F4P6 based board
PROJECT = f030f4
#SRCS = boot.c
#SRCS = ledon.c
#SRCS = blink.c
#SRCS = ledtick.c
#SRCS = cstartup.c
SRCS = startup.c init.c success.c
OBJS = $(SRCS:.c=.o)
CPU = -mthumb -mcpu=cortex-m0
CFLAGS = $(CPU) -g -Wall -Wextra -Os
LD_SCRIPT = $(PROJECT).ld
### Build rules
.PHONY: clean all
all: $(PROJECT).hex $(PROJECT).bin
clean:
@echo CLEAN
@rm -f *.o *.elf *.map *.lst *.bin *.hex
$(PROJECT).elf: $(OBJS)
@echo $@
$(LD) -T$(LD_SCRIPT) -Map=$(PROJECT).map -cref -o $@ $(OBJS)
$(SIZE) $@
$(OBJDUMP) -hS $@ > $(PROJECT).lst
%.elf: %.o
@echo $@
$(LD) -T$(LD_SCRIPT) -Map=$*.map -cref -o $@ $<
$(SIZE) $@
$(OBJDUMP) -hS $@ > $*.lst
%.bin: %.elf
@echo $@
$(OBJCOPY) -O binary $< $@
%.hex: %.elf
@echo $@
$(OBJCOPY) -O ihex $< $@
</pre>
A successful build will generate the files <b>f030f4.hex</b>, <b>f030f4.bin</b>,
<b>f030f4.map</b>, <b>f030f4.lst</b>.
<h2>Build and Test</h2>
Even if <b>stdlib.h</b> is included in <b>success.c</b>, there is no C
libraries needed to complete the build as only the constant
<code>EXIT_SUCCESS</code> from that header is used. Furthermore, default
location of the header files is derived by the compiler from the location of
gcc.
<pre>
$ make
f030f4.elf
text data bss dec hex filename
216 0 0 216 d8 f030f4.elf
f030f4.hex
f030f4.bin
</pre>
Building shows an increase in code, still no data.
<p>
Once <b>f030f4.hex</b> is loaded into the board, the behavior is the same
as <b>ledtick.hex</b>. The new file structure and data initialization
didnt introduce any <del>bugs</del> changes, just code overhead.
<h2>Checkpoint</h2>
This step was mainly to achieve a better structure for future evolution.
<p>
<a href="19_publish.html">Next</a>, I will make the code available in a
public git repository.
<hr>© 2020-2024 Renaud Fivet
</body>
</html>