cstartup code

09 Aug 2010

I have been looking at various compilers for the ARM Cortex M3 controller and when I have investigating compilers like IAR and GCC I noticed that the example codes use an assembly file in their project called cstartup_M or just cstartup.

I googled and found the following explanation:

Most chips basded on the ARM architecture are comlex on-chip systems, in which most of the hardware modules, whose working statuses are set by softwares, are configurable. Right after the system starts up, before running applications, a block of codes has to be executed to initialize the system. Generally speaking, the initialization should consist of the following steps:
* Interrupt vector table
* Initializing storage system
* Initializing stack
* Initializing the ports and devices that have special requirements
* Initializing excution environment for  user's applications
* Changing the processor mode
* Running main applications

 

Does the mbed compiler (which is gcc based) have a similar startup code linked automatically with each project??

 

Cheers

09 Aug 2010

I'm sure the mbed compiler has similar startup code, but it is not gcc-based. It's rvct - the back-end for Keil's MDK.

09 Aug 2010

@Romilly, Thanks for your response.

 

Can we find out what the start up code looks like for the the mbed compiler??

10 Aug 2010

Just download the CMSIS sample pack from nxp and check the Keil examples. Here's one:

;/*****************************************************************************
; * @file:    startup_LPC17xx.s
; * @purpose: CMSIS Cortex-M3 Core Device Startup File 
; *           for the NXP LPC17xx Device Series 
; * @version: V1.0
; * @date:    25. Nov. 2008
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; * Copyright (C) 2008 ARM Limited. All rights reserved.
; * ARM Limited (ARM) is supplying this software for use with Cortex-M3 
; * processor based microcontrollers.  This file can be freely distributed 
; * within development tools that are supporting such ARM based processors. 
; *
; * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
; *
; *****************************************************************************/


;  Stack Configuration
;    Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; 

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp


;  Heap Configuration
;     Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; 

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit


                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset

                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; NMI Handler
                DCD     HardFault_Handler         ; Hard Fault Handler
                DCD     MemManage_Handler         ; MPU Fault Handler
                DCD     BusFault_Handler          ; Bus Fault Handler
                DCD     UsageFault_Handler        ; Usage Fault Handler
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     SVC_Handler               ; SVCall Handler
                DCD     DebugMon_Handler          ; Debug Monitor Handler
                DCD     0                         ; Reserved
                DCD     PendSV_Handler            ; PendSV Handler
                DCD     SysTick_Handler           ; SysTick Handler

                ; External Interrupts
                DCD     WDT_IRQHandler            ; 16: Watchdog Timer
                DCD     TIMER0_IRQHandler         ; 17: Timer0
                DCD     TIMER1_IRQHandler         ; 18: Timer1
                DCD     TIMER2_IRQHandler         ; 19: Timer2
                DCD     TIMER3_IRQHandler         ; 20: Timer3
                DCD     UART0_IRQHandler          ; 21: UART0
                DCD     UART1_IRQHandler          ; 22: UART1
                DCD     UART2_IRQHandler          ; 23: UART2
                DCD     UART3_IRQHandler          ; 24: UART3
                DCD     PWM1_IRQHandler           ; 25: PWM1
                DCD     I2C0_IRQHandler           ; 26: I2C0
                DCD     I2C1_IRQHandler           ; 27: I2C1
                DCD     I2C2_IRQHandler           ; 28: I2C2
                DCD     SPI_IRQHandler            ; 29: SPI
                DCD     SSP0_IRQHandler           ; 30: SSP0
                DCD     SSP1_IRQHandler           ; 31: SSP1
                DCD     PLL0_IRQHandler           ; 32: PLL0 Lock (Main PLL)
                DCD     RTC_IRQHandler            ; 33: Real Time Clock
                DCD     EINT0_IRQHandler          ; 34: External Interrupt 0
                DCD     EINT1_IRQHandler          ; 35: External Interrupt 1
                DCD     EINT2_IRQHandler          ; 36: External Interrupt 2
                DCD     EINT3_IRQHandler          ; 37: External Interrupt 3
                DCD     ADC_IRQHandler            ; 38: A/D Converter
                DCD     BOD_IRQHandler            ; 39: Brown-Out Detect
                DCD     USB_IRQHandler            ; 40: USB
                DCD     CAN_IRQHandler            ; 41: CAN
                DCD     DMA_IRQHandler            ; 42: General Purpose DMA
                DCD     I2S_IRQHandler            ; 43: I2S
                DCD     ENET_IRQHandler           ; 44: Ethernet
                DCD     RIT_IRQHandler            ; 45: Repetitive Interrupt Timer
                DCD     MCPWM_IRQHandler          ; 46: Motor Control PWM
                DCD     QEI_IRQHandler            ; 47: Quadrature Encoder Interface
                DCD     PLL1_IRQHandler           ; 48: PLL1 Lock (USB PLL)


                IF      :LNOT::DEF:NO_CRP
                AREA    |.ARM.__at_0x02FC|, CODE, READONLY
CRP_Key         DCD     0xFFFFFFFF
                ENDIF


                AREA    |.text|, CODE, READONLY


; Reset Handler

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                LDR     R0, =__main
                BX      R0
                ENDP


; Dummy Exception Handlers (infinite loops which can be modified)                

NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler         [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler         [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler          [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler        [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler               [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler          [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler            [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler           [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WDT_IRQHandler            [WEAK]
                EXPORT  TIMER0_IRQHandler         [WEAK]
                EXPORT  TIMER1_IRQHandler         [WEAK]
                EXPORT  TIMER2_IRQHandler         [WEAK]
                EXPORT  TIMER3_IRQHandler         [WEAK]
                EXPORT  UART0_IRQHandler          [WEAK]
                EXPORT  UART1_IRQHandler          [WEAK]
                EXPORT  UART2_IRQHandler          [WEAK]
                EXPORT  UART3_IRQHandler          [WEAK]
                EXPORT  PWM1_IRQHandler           [WEAK]
                EXPORT  I2C0_IRQHandler           [WEAK]
                EXPORT  I2C1_IRQHandler           [WEAK]
                EXPORT  I2C2_IRQHandler           [WEAK]
                EXPORT  SPI_IRQHandler            [WEAK]
                EXPORT  SSP0_IRQHandler           [WEAK]
                EXPORT  SSP1_IRQHandler           [WEAK]
                EXPORT  PLL0_IRQHandler           [WEAK]
                EXPORT  RTC_IRQHandler            [WEAK]
                EXPORT  EINT0_IRQHandler          [WEAK]
                EXPORT  EINT1_IRQHandler          [WEAK]
                EXPORT  EINT2_IRQHandler          [WEAK]
                EXPORT  EINT3_IRQHandler          [WEAK]
                EXPORT  ADC_IRQHandler            [WEAK]
                EXPORT  BOD_IRQHandler            [WEAK]
                EXPORT  USB_IRQHandler            [WEAK]
                EXPORT  CAN_IRQHandler            [WEAK]
                EXPORT  DMA_IRQHandler            [WEAK]
                EXPORT  I2S_IRQHandler            [WEAK]
                EXPORT  ENET_IRQHandler           [WEAK]
                EXPORT  RIT_IRQHandler            [WEAK]
                EXPORT  MCPWM_IRQHandler          [WEAK]
                EXPORT  QEI_IRQHandler            [WEAK]
                EXPORT  PLL1_IRQHandler           [WEAK]

WDT_IRQHandler           
TIMER0_IRQHandler         
TIMER1_IRQHandler         
TIMER2_IRQHandler         
TIMER3_IRQHandler         
UART0_IRQHandler          
UART1_IRQHandler          
UART2_IRQHandler          
UART3_IRQHandler          
PWM1_IRQHandler           
I2C0_IRQHandler           
I2C1_IRQHandler           
I2C2_IRQHandler           
SPI_IRQHandler            
SSP0_IRQHandler           
SSP1_IRQHandler           
PLL0_IRQHandler           
RTC_IRQHandler            
EINT0_IRQHandler          
EINT1_IRQHandler          
EINT2_IRQHandler          
EINT3_IRQHandler          
ADC_IRQHandler            
BOD_IRQHandler            
USB_IRQHandler            
CAN_IRQHandler            
DMA_IRQHandler          
I2S_IRQHandler            
ENET_IRQHandler       
RIT_IRQHandler          
MCPWM_IRQHandler             
QEI_IRQHandler            
PLL1_IRQHandler           

                B       .

                ENDP


                ALIGN


; User Initial Stack & Heap

                IF      :DEF:__MICROLIB
                
                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit
                
                ELSE
                
                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap
__user_initial_stackheap

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + Stack_Size)
                LDR     R2, = (Heap_Mem +  Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR

                ALIGN

                ENDIF


                END

10 Aug 2010

Cortex-M3 can also use startup code written in C, for example http://github.com/hugovincent/mbed-freertos/blob/master/mach/cpu-lpc1768/crt0.c

If you shy away from assembler (like me), you might find the C version more readable. Note also that if you're doing this yourself and not using the mbed compiler you'll also likely need to think about the linker script. Many examples for that can be easily found too.

19 Aug 2010

@Hugo,

 

Thanks for the reply mate...I am just getting my head around the cstartup script, and yes the linker script is also of interest. So if I have this partly figured out, the cstartup script will initialize all the peripherals of the chip to default.

I followed the link you have provided, and when I tried to follow the project link for the Free RTOS implementation for M3, I was asked for a username and password and was told that the project can be viewed by invitation only. Any chance I can get an invite?? My email id is aquibf at gmail.com

 

Cheers

Aquib

20 Aug 2010 . Edited: 20 Aug 2010

Hi Aquib,

Not sure what happened there... the github page should be wide open, there is no way for me even to host private repositories because I only have a free github account. I've copied and pasted it in here anyway:

 

#include <stdint.h>
#include <string.h>

#include "cmsis.h"
#include "os_init.h"

extern void Reset_Handler();
extern void NMI_Handler();
extern void HardFault_Handler();
extern void MemManage_Handler();
extern void BusFault_Handler();
extern void UsageFault_Handler();
extern void SVC_Handler();
extern void DebugMon_Handler();
extern void PendSV_Handler();
extern void SysTick_Handler();
extern void UnhandledIRQ_Handler();

// Symbols defined by the linker:
extern unsigned int __data_init_start__, __stacks_top__,
					__data_start__, __data_end__,
					__bss_start__,  __bss_end__;


/*****************************************************************************/

// Vector table:
void (* const vectors[])(void)
		__attribute__ ((section(".vectors"))) =
{
	(void (*)())&__stacks_top__,	// Initial stack pointer
	Reset_Handler,
	NMI_Handler,
	HardFault_Handler,
	MemManage_Handler,				// MPU faults handler
	BusFault_Handler,
	UsageFault_Handler,
	0, 0, 0, 0, 					// (reserved)
	SVC_Handler,
	DebugMon_Handler,
	0,								// (reserved)
	PendSV_Handler,
	SysTick_Handler,
};


#define VECTORS_LEN_CORE	(sizeof(vectors) / sizeof(void(*)(void)))
#define VECTORS_LEN_LPC17XX	(35)
#define VECTORS_LEN			(VECTORS_LEN_CORE + VECTORS_LEN_LPC17XX)

// Vector table in RAM (after relocation):
void (* __ram_vectors[VECTORS_LEN])(void) __attribute__ ((section(".ram_vectors")));

__attribute__ ((noreturn)) void Reset_Handler(void)
{
	// Copy the data segment initializers from flash to RAM
	unsigned int *src  = &__data_init_start__;
	unsigned int *dest = &__data_start__;
	while (dest < &__data_end__)
		*(dest++) = *(src++);

	// Zero fill the bss segment
	dest = &__bss_start__;
	while (dest < &__bss_end__)
		*(dest++) = 0;

	// Copy the initial vector table from flash to RAM and then fill the
	// remaining vectors with calls to UnhandledIRQ_Handler.
	for (int i = 0; i < VECTORS_LEN_CORE; i++)
		__ram_vectors[i] = vectors[i];
	for (int i = VECTORS_LEN_CORE; i < VECTORS_LEN; i++)
		__ram_vectors[i] = UnhandledIRQ_Handler;

	// Perform the relocation
	SCB->VTOR = (unsigned int)__ram_vectors;

	// Enable Bus and Usage faults (MPU faults enabled when MPU is inited)
	SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk;

	// Enable div-by-0 and unaligned access faults
	SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk | SCB_CCR_UNALIGN_TRP_Msk;

	// Boot the system: hardware initialisation etc., eventually calls main()
	Boot_Init();
}

After this (in Boot_Init()) the CMSIS SystemInit gets run. This only replaces the assembler bit like what Igor showed above. It also puts a copy of the vector table in RAM so it can be modified at run time. Note that there are a bunch of symbols for addresses that have to be defined by the linker script. If you want to use this code as is, you'll need to use my linker script and so on as well.

 

 

Hope that helps,

Hugo

21 Sep 2010

Hi Hugo

Sorry for the late reply, my work is driving me crazy. Was not able to work on my mbed project for a while. Appreciate your response and help.

 

Cheers

Aquib