Hello there,
I am slowly transitioning to Freescale MCUs and right now I am working on my first prototype with a DEMO9S08QG8 board (MC9S08QG8 MCU). Up until now I had no major problems but now I am having a problem I can't seem to solve.
I am creating a little menu system for 2x16 LCD and for that I am trying to create some non volatile structures in FLASH memory (constants that will be flashed along the application code).
struct parameter;
struct menu;
struct menu_item;
typedef struct parameter
{
int* storage;
char* title;
byte type;
int min_range;
int max_range;
char* options[3];
}parameter;
typedef struct menu_item
{
byte type;
struct menu* menu;
parameter* param;
}menu_item;
typedef struct menu
{
char* title;
byte current_item;
byte num_elements;
menu_item* items[10];
}menu;
Initialization of constants:
extern int opc1 @0xFF00;
extern int opc2 @0xFF02;
extern int opc3 @0xFF04;
const parameter option1 ={
&opc1,
"Option 1",
PARAMETER_TYPE_YESNO
};
const parameter option2 =
{
&opc2,
"Option 2",
PARAMETER_TYPE_RANGE,
10,
50
};
const parameter option3 =
{
&opc3,
"Opcion 3",
PARAMETER_TYPE_OPTIONS,
0,
0,
{"Yes","No","Maybe"}
};
const menu_item submenu1_1 =
{
MENU_ITEM_PARAMETER,
0,
&opcion1
};
const menu_item submenu1_2 =
{
MENU_ITEM_PARAMETER,
0,
&opcion2
};
const menu_item submenu1_3 =
{
MENU_ITEM_PARAMETER,
0,
&opcion3
};
const menu_item* submenu1[3] =
{
&submenu1_1,
&submenu1_2,
&submenu1_3
};
const menu menu_ppal;
const menu_item submenu2_1 =
{
MENU_ITEM_SUBMENU,
&menu_ppal
};
const menu_item* submenu2[3] ={
&submenu1_2,
&submenu1_3,
&submenu2_1
};
const menu_item* menu_ppal_elements[2] = {
&submenu1,
&submenu2,
};
const menu menu_ppal ={
"Main menu",
0,
2,
menu_ppal_elements,
};
Note: My first version used unions to optimize memory size but I can't initialize const structs with unions.
Note2: This code resides in a menu.c, with the declarations for other modules in the menu.h header file
Note3: This is just an example to show how I declare and initialize the structs.
The thing is when I run/debug the application and inspect the constants they all have rubbish (and always the same rubbish). I suspected flash protection and when I try to unlock it with the FLASH Programmer in CW10.1 I get a timeout (as a matter of fact, I can erase and check erase, but I cannot program using that tool. But I can debug and run normally in debug mode). Am I forgetting something? Is there a better way of allocating constant data (strings and the sort) in C code?
Thanks in advance for your help!
Are you using the C startup code?
Some of the shown definitions are actually not const, especially pointers (or array of pointers) need the const after the *.
E.g.:
const menu_item*const submenu2[3] ={ &submenu1_2, &submenu1_3, &submenu2_1};
Otherwise submenu2 ends up in RAM and has to be initialized by the C startup code.
Not sure if this is your issue though.
Daniel
Thank you for your answer,but it seems my issue is different... I tried creating a constant string with both const char* v = "hello" and const char*const v = "hello" and I get rubbish on both (infinite ° chars actually). Is this how string constants are usually stored in Freescale MCUs? It should work,no?
Sorry if I point out the obvious; but just to be sure:
const char *v = "hello"; // will create a pointer in RAM to a const string and it will be initialised with the address of the string "hello" which is located in Flash
char * const v = "hello"; // will creat a constant pointer (in Flash) to a string and will contain the address if the string "hello" which also is located in Flash.
In both cases, if you look at the variable v, it will not contain the string "hello" but the address of the string in Flash.
Sten
Here is the section of the map file for the variables of menu.c
hello_s E092 2 2 1 .rodata option1 E094 F 15 1 .rodata option2 E0A3 F 15 1 .rodata option3 E0B2 F 15 1 .rodata submenu1_1 E0C1 5 5 1 .rodata submenu1_2 E0C6 5 5 2 .rodata submenu1_3 E0CB 5 5 2 .rodata submenu1 E0D0 6 6 1 .rodata submenu2_1 E0D6 5 5 1 .rodata submenu2 E0DB 6 6 1 .rodata menu_ppal_elements E0E1 4 4 1 .rodata menu_ppal E0E5 18 24 2 .rodata STRING.Hola.hola.1 E109 A 10 1 .rodata1 STRING.Opcion.1.2 E113 9 9 1 .rodata1 STRING.Opcion.3.3 E11C 9 9 1 .rodata1 STRING.Yes.4 E125 3 3 1 .rodata1 STRING.No.5 E128 3 3 1 .rodata1 STRING.Maybe.6 E12B 6 6 1 .rodata1 STRING.Menu.principal.7 E131 F 15 1 .rodata1 opc1 FF00 2 2 0 .abs_section_ff00 opc2 FF02 2 2 0 .abs_section_ff02 opc3 FF04 2 2 0 .abs_section_ff04
And the section allocation info:
.rodata 107 R 0xE092 0xE0FC ROM.rodata1 67 R 0xE0FD 0xE13F ROM.abs_section_ff00 2 N/I 0xFF00 0xFF01 .absSeg3.abs_section_ff02 2 N/I 0xFF02 0xFF03 .absSeg4.abs_section_ff04 2 N/I 0xFF04 0xFF05 .absSeg5
When I copied the code in my first post I translated it (but left some things untranslated accidentally) so in detail I have for example &opcion3 but it would really be &option3. Should you need the code as it is compiled I can copy it as is, but I don't think we will need it.
Observing the map file, I see everything goes to FLASH (I followed CompilerGuru suggestion and changed all pointers).
It's allright, it's been like 6 years since last time I developed C code (and it was C++ for PC when I was studying) and even though I understand the generics of it, there are some specifics that I just suppose are in some way. Up until now I was working in asm with another brand, so it is very possible I am just failing at something very basic and I just missed it.
Even so, when I check the variable v, what I really check is *v (in the debugger view I can see the contents of pointers, and if they are char* it interprets them as \0 ended strings, so the problem isn't there). Just to be sure, is this the typical way of creating constant data in non volatile memory?
Thanks all for the suggestions and help, let's see if we discover the origin of the issue
Hello,
Here is a simpler example than the one you give, and where I have a large number of different pre-determined messages to be sent, in this case, to the SCI1 module. I have a function that writes a string to the module, where the parameter is a pointer to the string address. It is possible you might have a similar function for writing to the LCD module.
void Tx1_sendstr( char *s);
I use a flash located message table, as follows:
const char * const msg_tab[] = ["String 1","String 2","String 3",..."String n"};
Of course, the first string has an index number of zero. To display a specific message, I then use the following function:
// Display message data to SCI1void disp_msg( byte msg_ndx){ Tx1_sendstr((byte *)msg_tab[msg_ndx]);}
For your more complex menu structures, maybe the string required for each menu item might be referenced simply by its index number, and the string data, or its address, kept out of the actual structures.
Regards,
Mac
As expected, this issue was that my code was wrong :smileysad:
char* constants do not work, but char[] do.
const char[] v = "Hello" ; //This works beatifully
The struct appeared as uninitialized because I had some of the pointers wrong, and when I tried the string constant and saw the same result I thought there was a problem with constants in general in my project.
Now it's working, thanks everyone for your help!
Can you check the .map linker output to see where the variables are actually allocated? RAM or ROM?