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 Normal View History

<!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>