У меня проблемы с инициализацией определенных структур, которые объявлены как статические в заголовке моей библиотеки
Заголовочный файл:
struct game_setting
{
uint8_t parameter;
uint8_t alternatives[6];
uint8_t alternatives_number;
};
static game_setting game_status;
Функция инициализации в .c-файле:
void menu_init()
{
static uint8_t game_parameters_array[6];
static game_setting game_status = {&game_parameters_array[RUN_STATUS],{OFF,ON},2}
Что возвращает 'Элемент Initializer не вычисляется во время загрузки'
Я ищу эффективный способ присвоения значений статической структуре, что не так?
Основной скрипт
#define F_CPU 4915200UL
#define OFFSET 0x2000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include "SPI.h"
#include "MCP2515.h"
#include "MCP2515_Commands.h"
#include "adc.h"
#include "multiboard.h"
#include "OLED.h"
#include "OLED_menu.h"
#include "CAN.h"
#include "USART.h"
#define SPI_DEBUG
#define CAN_MESSAGE_DEBUG
#define UPDATEMESSAGES 255
// Define baud rate
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int main(void){
FILE fileHandle = USART_Init();
init_xMem();
stdout = &fileHandle;
stdin = &fileHandle;
printf("start of init\n\r");
menu_init();
printf("menu_init completed\n");
OLED_init();
CAN_init();
ADCInit();
initController();
can_message msg;
msg.id = 1;
controller C;
int i = 1;
while (1) {
menu_page_print_data();
_delay_ms(1000);
}
}
Полный файл .c OLED_menu (соответствующие функции работают без определений OLED.h):
#include "OLED.h"
#include "OLED_menu.h"
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;
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);
}
void game_setting_init(game_setting* setting, uint8_t* parameter, uint8_t* alternatives, uint8_t elements)
{
setting->parameter = parameter;
for (int i; i < elements; i++)
{
setting->alternatives[i] = alternatives[i];
}
}
int menu_assign_parents(menu_page* parent)
{
if(parent->submenu_pages_number > 6)
{
return -1;
}
for (int i; i < parent->submenu_pages_number; i++)
{
parent->submenu_pages[i]->parent_menu_page = parent;
if(menu_assign_parents(parent->submenu_pages[i]) == -1)
{
return -1;
}
}
return 0;
}
int menu_page_print(menu_page* page)
{
OLED_SRAM_Position_reset();
OLED_TextBox_clear((boundary) {0,127,0,7});
OLED_Goto_position(0,40);
//printf("%d parent, ", page->submenu_pages_number);
OLED_String_print(page->title, FONT_LARGE);
for (int i = 0; i < page->submenu_pages_number; i++)
{
OLED_Goto_position(i+1,5);
OLED_String_print(page->submenu_pages[i]->title, FONT_NORMAL);
//printf("%s\n", page->submenu_pages[i].title);
}
return 0;
}
menu_page* menu_page_select(menu_page* page,controller* C)
{
menu_page_print(page);
if(page->submenu_pages_number <= 0)
{
return (menu_page*)-1;
}
int submenu_number = -1;
int submenu_result = -1;
controller_direction generalDirection_prev;
while(!C->rightButton)
{
updateController(C);
if(generalDirection_prev != C->J.generalDirection)
{
switch(C->J.generalDirection)
{
case (DOWN):
submenu_number = (submenu_number + 1)%page->submenu_pages_number;
break;
case (UP):
submenu_number--;
if(submenu_number < 0)
{
submenu_number = page->submenu_pages_number-1;
}
break;
}
menu_page_selection_mark(submenu_number+1, page);
generalDirection_prev = C->J.generalDirection;
}
}
return &(page->submenu_pages[submenu_number]);
}
int TextBox_init(OLED_TextBox** box, char* str, TextBox_pos position, uint8_t line)
{
uint8_t StringLength = strlen(str);
printf("%d\n\r", StringLength);
if (118 / StringLength >= FONT_LARGE)
{
(*box)->FontSize = FONT_LARGE;
}
else if (118 / StringLength >= FONT_NORMAL)
{
(*box)->FontSize = FONT_NORMAL;
}
else if (118 / StringLength >= FONT_SMALL)
{
(*box)->FontSize = FONT_SMALL;
}
printf("%d\n\r", (*box)->FontSize);
switch (position)
{
case TEXBOX_LEFT:
(*box)->Boundaries = (boundary){5,5+StringLength*(*box)->FontSize,line,line};
case TEXTBOX_CENTER:
printf("%d\n\r", (128-(*box)->FontSize*StringLength)/2);
(*box)->Boundaries = (boundary){(128-(*box)->FontSize*StringLength)/2, (128+StringLength*(*box)->FontSize+1)/2,line,line};
printf("%d, %d, %d, %d nr1\n\r", (*box)->Boundaries.Left, (*box)->Boundaries.Right, (*box)->Boundaries.Top, (*box)->Boundaries.Bottom);
//printf("%d\n\r", (*box)->FontSize);
case TEXTBOX_RIGHT:
(*box)->Boundaries =(boundary){128-5-StringLength*(*box)->FontSize, 128-5,line,line};
}
(*box)->string = str;
return 0;
}
int menu_page_selection_mark(uint8_t rowIndex, menu_page* menu)
{
if(rowIndex < 1)
{
return -1;
}
//printf("Current index: %s\n", menu->submenu_pages[rowIndex].title);
static int rowIndex_prev = -1;
if(rowIndex_prev > -1)
{
OLED_Clear_line(rowIndex_prev);
OLED_Goto_position(rowIndex_prev, 5);
printf("title: %s\n", menu->submenu_pages[rowIndex_prev-1]->title);
OLED_String_print(menu->submenu_pages[rowIndex_prev-1]->title, FONT_LARGE);
}
OLED_Clear_line(rowIndex);
OLED_Goto_position(rowIndex, 7);
OLED_String_print(menu->submenu_pages[rowIndex-1]->title, FONT_LARGE);
OLED_String_print(" <-", FONT_LARGE);
rowIndex_prev = rowIndex;
return rowIndex;
}
void menu_page_print_data()
{
menu_page* page = main_menu;
printf("Menu page %s: Children: ", page->title);
for (int i; i < page->submenu_pages_number; i++)
{
printf("%s ", page->submenu_pages[i]->title);
}
printf("Parent: %s", page->parent_menu_page->title);
}
int menu_print_parameters(game_setting* settings, controller* C)
{
static uint8_t current_position = 1;
controller_direction generalDirection_prev;
menu_print_parameter_line(settings, LEFT, current_position);
while(!C->leftButton)
{
if(C->J.generalDirection != generalDirection_prev)
{
if (C->J.generalDirection == LEFT)
{
current_position = menu_print_parameter_line(settings, LEFT, current_position);
}
else if(C->J.generalDirection == RIGHT)
{
current_position = menu_print_parameter_line(settings, RIGHT, current_position);
}
}
}
}
int menu_print_parameter_line(game_setting* setting, controller_direction direction, uint8_t position)
{
char* string;
uint8_t next_position;
if(setting->alternatives_number == 0)
{
return -1;
}
if(direction == LEFT)
{
next_position = position -1;
}
else if(direction == RIGHT)
{
next_position = position +1;
}
OLED_Clear_line(6);
OLED_Goto_position(6,127);
OLED_String_print("<-", FONT_LARGE);
sprintf(&string, setting->alternatives[next_position]);
OLED_String_print(string, FONT_LARGE);
OLED_String_print("->", FONT_LARGE);
return next_position;
}
int menu_assign_parameters(menu_page* page, controller* C)
{
}
int menu_run(menu_page* page, controller* C)
{
menu_page* next_submenu_page;
menu_page* current_page = page;
while(next_submenu_page != -1)
{
current_page = next_submenu_page;
next_submenu_page = menu_page_select(current_page, C);
}
}
Файл OLED_menu.h:
#ifndef OLED_MENU_H
#define OLED_MENU_H
#include "symbols_enums.h"
#include "OLED.h"
#include "multiboard.h"
#include "CAN_message_IDs.h"
#include <assert.h>
#include <string.h>
#include <avr/delay.h>
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[12];
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;
int menu_page_init(char*, menu_page*, menu_page*);
int menu_page_print(menu_page* page);
menu_page* menu_page_select(menu_page* page,controller* C);
int menu_page_selection_mark(uint8_t, menu_page*);
void menu_page_print_data();
int menu_print_parameter_line(game_setting*, controller_direction , uint8_t);
//int TextBox_init(OLED_TextBox**, char*, TextBox_pos, uint8_t);
#endif // OLED_MENU_H
Я изменил его, чтобы вручную инициализировать один элемент структуры за раз, что, кажется, работает. Однако при выполнении программы происходит сбой до завершения menu_init () из-за следующих инициализаций:
menu_setting->submenu_pages[0] = controller_layout;
menu_setting->submenu_pages[1] = settings_difficulty;
menu_setting->submenu_pages[2] = settings_advanced;
main_menu->submenu_pages[0] = start_game;
main_menu->submenu_pages[1] = menu_setting;
controller_layout->submenu_pages[1] = servo_control;
controller_layout->submenu_pages[2] = solenoid_control