I was surprised to see various compilers that were shipping with assembly startup code
This is a very annoying practice of carrying legacy code and legacy thinking.
Hardware was designed to do something - take advantage of it.
I don't know. Having the interrupt controller behavior match the C abi, so you don't need special compiler behavior for ISRs, is really nice. But eliminating a half page of assembly start-up code by allowing the same thing in C seems a bit gimmicky. Especially since most of that is just a big table of ISR vectors, which is equally opaque (or not) in either C or ASM.
FWIW, it looks like the startup code for ATMEL ARM chips is written entirely in C.
(Hmm. I think a big factor might be that it's pretty important for startup code to be published in a form that users can use without having to buy an expensive compiler. Most vendors have some sort of free assembler, but not all of them distribute a free C compiler, so having the startup code be in ASM is a bit of an advantage...) (?)
Here's the entire Atmel SAMD10 startup code, not including most of the vector table, or the magic commands that make symbols weak and otherwise easy to manipulate:
* Copyright (c) 2014 Atmel Corporation. All rights reserved.
/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {
/* Configure Initial Stack Pointer, using linker-generated symbols */
(void*) (&_estack),
(void*) Reset_Handler,
(void*) NMI_Handler,
: // Bunch of vector omitted.
(void*) ADC_Handler, /* 15 Analog Digital Converter */
(void*) AC_Handler, /* 16 Analog Comparators */
(void*) DAC_Handler, /* 17 Digital Analog Converter */
(void*) PTC_Handler /* 18 Peripheral Touch Controller */
};
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
*/
void Reset_Handler(void)
{
uint32_t *pSrc, *pDest;
/* Initialize the relocate segment */
pSrc = &_etext;
pDest = &_srelocate;
if (pSrc != pDest) {
for (; pDest < &_erelocate;) {
*pDest++ = *pSrc++;
}
}
/* Clear the zero segment */
for (pDest = &_szero; pDest < &_ezero;) {
*pDest++ = 0;
}
/* Set the vector table base address */
pSrc = (uint32_t *) & _sfixed;
SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);
/* Initialize the C library */
__libc_init_array();
/* Branch to main function */
main();
/* Infinite loop */
while (1);
}
void Dummy_Handler(void)
{
while (1) {
}
}