为链接器指定外部存储器

编译代码时,即使自上次成功编译以来添加的所有额外变量都使用指向外部SRAM内存的指针声明,但仍出现数据内存溢出错误。

我找到了使用链接器标志指定外部存储器的示例,但是这些示例没有帮助。 (我的SRAM内存范围示例:0x1000-> 0x1FFF):

-Wl,-section-start,.data = 0x801000,-defsym = __ heap_end = 0x801FFF

在AVR / GNU通用/常规设置中选中“用于内存溢出的外部ram检查”复选框不能解决问题。

导致溢出的外部声明的代码: 头文件:


typedef struct menu_page menu_page;

typedef struct game_setting game_setting;
struct game_setting
{
    uint8_t* parameter;
    uint8_t alternatives[6];
    uint8_t alternatives_number;
};
struct menu_page
{
    char title[20];
    menu_page* submenu_pages[4];
    menu_page* parent_menu_page;
    uint8_t submenu_pages_number;
    //Used to set values for settings:
    game_setting* setting;
};
typedef enum {TEXBOX_LEFT,TEXTBOX_CENTER,TEXTBOX_RIGHT}TextBox_pos;

static volatile menu_page* menu_page_address_offset;
static volatile game_setting* game_setting_address_offset;
static uint8_t game_parameters_array[5];

//Indicates if the game should start/stop:
static volatile game_setting* game_status;
static volatile menu_page* start_game;

//***********************************
static volatile game_setting* solenoid_param;
static volatile menu_page* solenoid_control;

static volatile game_setting* servo_param;
static volatile menu_page* servo_control;   

static volatile game_setting* motor_param;      
static volatile menu_page* motor_control;                       //Controller layout
//***********************************
static volatile menu_page* controller_layout;

static volatile menu_page* settings_advanced;

static volatile game_setting* difficulty_param;
static volatile menu_page* settings_difficulty;

static volatile menu_page* menu_setting;


static volatile menu_page* main_menu;

源文件中的初始化函数:

void menu_init()
{


    menu_page_address_offset = 0x1C01;
    game_setting_address_offset = 0x1F01;

    game_status = game_setting_address_offset;
    game_setting_address_offset += 1;

    uint8_t alternatives[6];

    game_status->parameter =  &game_parameters_array[RUN_STATUS];
    game_status->alternatives[0] = OFF;
    game_status->alternatives[1] = ON;
    game_status->alternatives_number = 2;

    start_game = menu_page_address_offset;

    menu_page_address_offset += 1;

    strcpy(&start_game->title,"Start game");
    start_game->submenu_pages[0] =  NULL; 
    start_game->parent_menu_page = main_menu; 
    start_game->submenu_pages_number = 0; 
    start_game->setting = &game_status;

    solenoid_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    solenoid_param->parameter = &game_parameters_array[SOLENOID];
    solenoid_param->alternatives[0] = X_POSITION;
    solenoid_param->alternatives[1] = Y_POSITION;
    solenoid_param->alternatives[2] = LEFT_SLIDER;
    solenoid_param->alternatives[3] = RIGHT_SLIDER;
    solenoid_param->alternatives_number = 4;

    solenoid_control = menu_page_address_offset;
    menu_page_address_offset += 1;



    strcpy(&solenoid_control->title,"Solenoid");
    solenoid_control->submenu_pages[0] =  NULL;
    solenoid_control->parent_menu_page =  NULL;
    solenoid_control->submenu_pages_number =  0;
    solenoid_control->setting =  &solenoid_param;

    servo_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    servo_param->parameter = &game_parameters_array[SERVO];
    servo_param->alternatives[0] = X_POSITION;
    servo_param->alternatives[1] = Y_POSITION;
    servo_param->alternatives[2] = LEFT_SLIDER;
    servo_param->alternatives[3] = RIGHT_SLIDER;
    servo_param->alternatives_number = 4;

    servo_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&servo_control->title,"Servo");
    servo_control->submenu_pages[0] = NULL;
    servo_control->parent_menu_page = NULL;
    servo_control->submenu_pages_number =  0;
    servo_control->setting =  &servo_param;

    motor_param = game_setting_address_offset;
    game_setting_address_offset += 1;


    motor_param->parameter = &game_parameters_array[MOTOR]; 
    motor_param->alternatives[0] = X_POSITION;
    motor_param->alternatives[1] = Y_POSITION;
    motor_param->alternatives[2] = LEFT_SLIDER;
    motor_param->alternatives[3] = RIGHT_SLIDER;

    motor_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&motor_control->title,"Motor");
    motor_control->submenu_pages[0] = NULL; 
    motor_control->parent_menu_page = NULL;
    motor_control->submenu_pages_number =  0; 
    motor_control->setting = &motor_param;
    #ifdef OLED_MENU_INIT_DEBUG
    printf("Menu Title: %s\n",motor_control->title);
    #endif

    controller_layout = menu_page_address_offset;
    //printf("Controller_layout addr:,%d\n",(int)menu_page_address_offset);
    menu_page_address_offset += 1;


    strcpy(controller_layout->title,"Controller Layout");
    controller_layout->submenu_pages[0] = motor_control;
    printf("motor_control : %X\n",motor_control);
    controller_layout->submenu_pages[1] = servo_control;
    controller_layout->submenu_pages[2] = solenoid_control;
    controller_layout->parent_menu_page = NULL;
    controller_layout->submenu_pages_number = 3;
    controller_layout->setting =  NULL;

    settings_advanced = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_advanced->title,"Advanced Settings");
    settings_advanced->submenu_pages[0] = NULL;
    settings_advanced->parent_menu_page =  NULL;
    settings_advanced->submenu_pages_number =  0; 
    settings_advanced->setting = NULL;

    difficulty_param->parameter = &game_parameters_array[DIFFICULTY];
    difficulty_param->alternatives[0]  = DIFFICULTY_EASY;
    difficulty_param->alternatives[1]  = DIFFICULTY_NORMAL;
    difficulty_param->alternatives[2]  = DIFFICULTY_HARD;
    difficulty_param->alternatives_number = 3;

    settings_difficulty = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_difficulty->title,"Difficulty");
    settings_difficulty->submenu_pages[0] =  NULL;
    settings_difficulty->parent_menu_page =  NULL;
    settings_difficulty->submenu_pages_number =  0;
    settings_difficulty->setting =  &difficulty_param;

    menu_setting = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(menu_setting->title,"Settings");
    menu_setting->submenu_pages[0] = controller_layout;
    menu_setting->submenu_pages[1] = settings_difficulty;
    menu_setting->submenu_pages[2] = settings_advanced;
    //printf("Child 1 before: %d,%d",menu_setting->submenu_pages[0],controller_layout);
    menu_setting->parent_menu_page = NULL;
    menu_setting->submenu_pages_number = 3;
    menu_setting->setting = NULL;


        menu_setting = menu_page_address_offset;
        menu_page_address_offset += 1;
    main_menu = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(main_menu->title,"Main Menu");
    main_menu->submenu_pages[0] = start_game;
    main_menu->submenu_pages[1] = menu_setting;
    main_menu->parent_menu_page  = NULL;
    main_menu->submenu_pages_number =  2;
    main_menu->setting = NULL;
    menu_assign_parents(&main_menu);
}

使用这些附加声明,数据内存使用率从82%增加到102%。我认为应该占用更少的空间?我在做什么错了?

zjm550 回答:为链接器指定外部存储器

在这种情况下,不需要将指针保存在数据存储器中,因此我将它们更改为init()函数中的临时指针。我没有选择保留指针,而是选择创建一个menu_page **表来将指针保留在SRAM内存中。

新标题中的相关信息:

typedef enum {

    //Run status flag for the game (Turn on/off):
    GAME_STATUS,//Holds possible parameters for solenoid control selection:
    SOLENOID_PARAMETERS,//Holds possible parameters for servo control selection:
    SERVO_PARAMETERS,//Holds possible parameters for motor control selection:
    MOTOR_PARAMETERS,//Holds possible parameters for difficulty:
    DIFFICULTY_PARAMETERS,GAME_SETTING_ELEMENTS = 5       // <-Has to be adjusted to number of elements in this enum!
    }game_setting_data_index;
typedef enum {
    //Pressing this option starts the game:
    START_GAME,//Menu for configuring which button to control solenoid:
    SOLENOID_CONTROL,// -||- which adc to control servo:
    SERVO_CONTROL,// -||- control motor:
    MOTOR_CONTROL,// Parent page for controller-configuration:
    CONTROLLER_LAYOUT,//More settings for the game:
    SETTINGS_ADVANCED,//Set difficulty:
    SETTINGS_DIFFIULTY,//Parent page for all settings,has previous pages as children: 
    MENU_SETTING,MAIN_MENU,MENU_PAGE_ELEMENTS = 9              //<--Has to be adjusted to number of elements in this enum!
    }menu_page_data_index;

新的初始化功能:

void menu_init()
{

    const volatile menu_page* MENU_PAGE_SRAM_BASE_OFFSET = 0x1C01;
    const volatile menu_page* GAME_SETTING_SRAM_BASE_OFFSET = 0x1E01;

    //The menu_pages will be stored right after the last menu_page_address in SRAM_memory:
    menu_page* menu_page_address_offset = MENU_PAGE_SRAM_BASE_OFFSET;
    game_setting* game_setting_address_offset = GAME_SETTING_SRAM_BASE_OFFSET;


    game_setting* game_status = game_setting_address_offset;
    game_setting_address_offset += 1;


    game_status->parameter =  &game_parameters_array[RUN_STATUS];
    game_status->alternatives[0] = OFF;
    game_status->alternatives[1] = ON;
    game_status->alternatives_number = 2;

    menu_page* start_game = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&start_game->title,"Start game");
    start_game->submenu_pages[0] =  NULL; 
    start_game->parent_menu_page = NULL; 
    start_game->submenu_pages_number = 0; 
    start_game->setting = &game_status;

    game_setting* solenoid_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    solenoid_param->parameter = &game_parameters_array[SOLENOID];
    solenoid_param->alternatives[0] = X_POSITION;
    solenoid_param->alternatives[1] = Y_POSITION;
    solenoid_param->alternatives[2] = LEFT_SLIDER;
    solenoid_param->alternatives[3] = RIGHT_SLIDER;
    solenoid_param->alternatives_number = 4;

    menu_page* solenoid_control = menu_page_address_offset;
    menu_page_address_offset += 1;



    strcpy(&solenoid_control->title,"Solenoid");
    solenoid_control->submenu_pages[0] =  NULL;
    solenoid_control->parent_menu_page =  NULL;
    solenoid_control->submenu_pages_number =  0;
    solenoid_control->setting =  &solenoid_param;

    game_setting* servo_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    servo_param->parameter = &game_parameters_array[SERVO];
    servo_param->alternatives[0] = X_POSITION;
    servo_param->alternatives[1] = Y_POSITION;
    servo_param->alternatives[2] = LEFT_SLIDER;
    servo_param->alternatives[3] = RIGHT_SLIDER;
    servo_param->alternatives_number = 4;

    menu_page* servo_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&servo_control->title,"Servo");
    servo_control->submenu_pages[0] = NULL;
    servo_control->parent_menu_page = NULL;
    servo_control->submenu_pages_number =  0;
    servo_control->setting =  &servo_param;

    game_setting* motor_param = game_setting_address_offset;
    game_setting_address_offset += 1;


    motor_param->parameter = &game_parameters_array[MOTOR]; 
    motor_param->alternatives[0] = X_POSITION;
    motor_param->alternatives[1] = Y_POSITION;
    motor_param->alternatives[2] = LEFT_SLIDER;
    motor_param->alternatives[3] = RIGHT_SLIDER;

    menu_page* motor_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&motor_control->title,"Motor");
    motor_control->submenu_pages[0] = NULL; 
    motor_control->parent_menu_page = NULL;
    motor_control->submenu_pages_number =  0; 
    motor_control->setting = &motor_param;
    #ifdef OLED_MENU_INIT_DEBUG
    printf("Menu Title: %s\n",motor_control->title);
    #endif

    menu_page* controller_layout = menu_page_address_offset;
    //printf("Controller_layout addr:,%d\n",(int)menu_page_address_offset);
    menu_page_address_offset += 1;


    strcpy(controller_layout->title,"Controller Layout");
    controller_layout->submenu_pages[0] = motor_control;
    printf("motor_control : %X\n",motor_control);
    controller_layout->submenu_pages[1] = servo_control;
    controller_layout->submenu_pages[2] = solenoid_control;
    controller_layout->parent_menu_page = NULL;
    controller_layout->submenu_pages_number = 3;
    controller_layout->setting =  NULL;

    menu_page* settings_advanced = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_advanced->title,"Advanced Settings");
    settings_advanced->submenu_pages[0] = NULL;
    settings_advanced->parent_menu_page =  NULL;
    settings_advanced->submenu_pages_number =  0; 
    settings_advanced->setting = NULL;

    game_setting* difficulty_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    difficulty_param->parameter = &game_parameters_array[DIFFICULTY];
    difficulty_param->alternatives[0]  = DIFFICULTY_EASY;
    difficulty_param->alternatives[1]  = DIFFICULTY_NORMAL;
    difficulty_param->alternatives[2]  = DIFFICULTY_HARD;
    difficulty_param->alternatives_number = 3;

    menu_page* settings_difficulty = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_difficulty->title,"Difficulty");
    settings_difficulty->submenu_pages[0] =  NULL;
    settings_difficulty->parent_menu_page =  NULL;
    settings_difficulty->submenu_pages_number =  0;
    settings_difficulty->setting =  &difficulty_param;

    menu_page *menu_setting = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(menu_setting->title,"Settings");
    menu_setting->submenu_pages[0] = controller_layout;
    menu_setting->submenu_pages[1] = settings_difficulty;
    menu_setting->submenu_pages[2] = settings_advanced;
    //printf("Child 1 before: %d,%d",menu_setting->submenu_pages[0],controller_layout);
    menu_setting->parent_menu_page = NULL;
    menu_setting->submenu_pages_number = 3;
    menu_setting->setting = NULL;


    menu_setting = menu_page_address_offset;
    menu_page_address_offset += 1;


    menu_page* main_menu = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(main_menu->title,"Main Menu");
    main_menu->submenu_pages[0] = start_game;
    main_menu->submenu_pages[1] = menu_setting;
    main_menu->parent_menu_page  = NULL;
    main_menu->submenu_pages_number =  2;
    main_menu->setting = NULL;
    //menu_assign_parents(&main_menu);
    printf("Offsets: menupage: %X,game_setting: %X\n",menu_page_address_offset,game_setting_address_offset);
    printf("Bytes per page: %d,sizeof(menu_page),((int)menu_page_address_offset-0x1C01)/10);
    //Create address table at end of menu_page entries:
    menu_page_address_table = menu_page_address_offset;

    //Create address table at end of game_setting entries:
    game_setting_address_table = game_setting_address_offset;

    /*Game settings and pages have been placed in the order
    of the menu_page_data_index-enum,address-tables should 
    be updated accordingly: */
        printf("Menu address table: \n");
    for (int i; i < MENU_PAGE_ELEMENTS; i++)
    {
        menu_page_address_table[i] = MENU_PAGE_SRAM_BASE_OFFSET + i;
        printf("%X  ",menu_page_address_table[i]);
    }
    printf("\nGame setting address table: \n");
    for (int i; i < GAME_SETTING_ELEMENTS; i++)
    {
        game_setting_address_table[i] = GAME_SETTING_SRAM_BASE_OFFSET + i;
        printf("%X  ",game_setting_address_table[i]);
    }
    printf("\n");

}

初始化每个结构成员似乎没有必要,我将尝试为每个结构创建一个初始化函数。

本文链接:https://www.f2er.com/3166270.html

大家都在问