I have a problem writing data to flash memory. If I use int main
, programming runs normally, but if I use __attribute__((naked)) __attribute__((section(".ctors"))) void boot(void)
, programming can't write to address memory I want to page.
#include "libcomp.h"
const flash_adr_t address = 0x1fc00;
#ifndef MAIN_TEST
/*
* Main boot function
* It represents the enter point for the device to start execution
* It represents the enter point for the device to start execution
* Naked attribute instructs the compiler to omit the function prologue and epilogue
*/
__attribute__((naked)) __attribute__((section(".ctors"))) void boot(void)
#else
int main(void)
#endif
{
int value;
/* Initialize system for AVR GCC support, expects r1 = 0 */
asm volatile("clr r1");
SYSTEM_Initialize();
uint8_t buffer[PROGMEM_PAGE_SIZE];
uint8_t data_flash[PROGMEM_PAGE_SIZE] = "Main boot function. It represents the enter point for the device to start execution.";
value = strlen((char)data_flash);
FLASH_WriteFlashPage(address, data_flash);
_delay_ms(500);
BLD_Init();
uint16_t i = 0;
while (1)
{
if (USART0_IsTxReady()) {
for (int k = 0; k < value; k++) {
USART0_Write(FLASH_ReadFlashByte(address + k));
}
USART0_Write('\n');
}
ClrWdt();
BLD_Tasks();
if (++i == 0)
LED3_Toggle();
}
#ifdef MAIN_TEST
return 0;
#endif
}
I use
__attribute__((naked)) __attribute__((section(".ctors"))) void boot(void)
These attributes make no sense. Section .ctors
contains addresses of static constructors; it does not contain executable code.
asm volatile("clr r1");
This is hack and might not work as you expect. Avoid it or move it to the assembly part of your startup code.
If you need custom start-up code, you can use
This feature is specific to GCC. The syntax is like
__attribute__((__constructor__))
static void init (void)
{
// C/C++ code
}
Notice that the static
in the code limits visibility of the constructor, it has nothing to do with the constructor being static. The generated code will be something like:
.global __do_global_ctors
.section .ctors,"a",@progbits
.p2align 1
.word gs(init)
__do_global_ctors
will traverse .ctors
and call the static constructors. It lives in libgcc and avr-gcc references it so it is dragged from libgcc.
.init
SectionsThis feature is specfic to avr-gcc. The syntax is like
__attribute__((__used__,__unused__,__naked__,__section__(".init8")))
static void init8 (void)
{
__asm volatile ("; code");
}
.initN
section contains more than one function, the order of execution is unspecified.The following sections have library resp. start-up code located / attached to to them:
.init0
: Implements vector0: Set up __zero_reg__
, SP
, EIND
, and RAMP*
registers (from AVR-LibC)..init4
: Run __do_copy_data
and __do_clear_bss
as needed (from libgcc)..init6
: Run __do_global_ctors
as needed (from libgcc)..init9
: Call main
and exit
(from AVR-LibC).If you prefer own startup code altogether, then
-nostartfiles
.__do_copy_data
, __do_clear_bss
, __do_global_ctors
.-nostartfiles
you'll have to provide your own vectab.