Указание внешней памяти для компоновщика - PullRequest
2 голосов
/ 04 ноября 2019

При компиляции моего кода я получаю ошибку переполнения Data Memory, хотя все дополнительные переменные, добавленные с момента последней успешной компиляции, объявляются с указателями на внешнюю память SRAM.

Я нашел примеры указания внешней памяти с флагами компоновщика, однако они не помогли. (Пример для моего диапазона памяти SRAM: 0x1000 -> 0x1FFF):

-Wl, - начало раздела, .data = 0x801000, - defsym = __ heap_end = 0x801FFF

Установка флажка«Внешняя проверка оперативной памяти на предмет переполнения памяти» в общих / общих настройках AVR не решила проблему.

Код внешних объявлений, вызывающих переполнение: Файл заголовка:


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;

init-функция в исходном файле:

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%. Я полагаю, это должно занять меньше места? Что я делаю не так?

1 Ответ

0 голосов
/ 04 ноября 2019

В этом случае указатели не нужно было хранить в памяти данных, поэтому я изменил их на временные в функции 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, %d\n", 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");

}

Инициализация каждого члена структуры кажется немного ненужной, вместо этого я попытаюсь создать функцию init для каждой структуры.

...