What I have to do to put const chars into flash memory?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

What I have to do to put const chars into flash memory?

Jump to solution
2,908 Views
piotrdzierzak
Contributor II

Hello!

 

What I have to do to put const chars into flash memory?

 

I use KDS like below with j-link from Segger (Picture1).

Picture1:

 160379_160379.bmpKDS_ver.bmp

 

For example

static const unsigned char en_menu_1_0[15]="Put into flash";

Picture2:

160380_160380.bmpconst_char.bmp 

 

map file (Picture3):

 

 160381_160381.bmpmapfile.bmp

 

 

When I read from this array in run

i= en_menu_1_0[2];

Picture4:

160385_160385.bmpread_const.bmp 

On the Picture4 the value i=0x74 (ASCII == ‘t’) so this is correct. In this situation debbuger show correct value.

 

But why:

1. The debugger shows strange value like in picture2 above, where is initialization of const unsigned char array?             const unsigned char en_menu_1_0[15]="Put into flash"?

2. Why address of static const unsigned char en_menu_1_0 is …. 0x00000000 (picture2)?

 

...................................................................................................................................................

Maybe I describe what I want to do....

I want to prepare menu strings that I want to put to the flash memory.

Then make array of pointers to the array of chars….

Something like this below for atmel.

But how can I do this in Kinetis (KL46Z256)?

 

In 8051 there is “code”

In atmel ther is “PROGMEM”

What I have to do in Kinetis KL46?

 

example from atmel:

const char MenuItem1[] PROGMEM = "Mirek";

const char MenuItem2[] PROGMEM = "Tomek";

const char MenuItem3[] PROGMEM = "Atnel";

 

const char * const MenuItemPointers[] PROGMEM = {

  MenuItem1,

  MenuItem2,

  MenuItem3

};

 

int main( void ) {

 

lcd_init();

uint8_t i;

      while(1) {

         for(i=0; i<3; i++)

           lcd_str_P( (char*)pgm_read_word( &MenuItemPointers[i] ) );

      }

}

...............................................................................................................................................

I will be very gratefull for any help and sugestion.

 

Best Regards

Piotr

 

Labels (1)
1 Solution
2,110 Views
bobpaddock
Senior Contributor III

This is the code I use with GCC.  Some macros make it compatible with AVR-GCC so same code can be used on both ARM and AVR.

#define PGM_P char const *

#define strncpy_P strncpy

#define PROGMEM

#ifndef PGM_READ_WORD
#define PGM_READ_WORD(adr) (adr)
#endif

#define UNUSED( PARAMETER ) (void)(PARAMETER) /** Used to silence 'unused parameter' */

/* Example function: */

static uint16_t bootload_jump_func( uint8_t const *string_u8 );
static uint16_t bootload_jump_func( uint8_t const *string_u8 )
{
UNUSED( string_u8 );
bootload_jump_func(); /* Never returns */
return( 0U ); /* Keep compiler happy, we never get here */
}

/* ******************** Decode incoming ASCII commands ******************** */

/*
* To get the static strings to really be in the flash you have to do
* it this way with structures. The 'obvious' way only gets the array
* of pointers in flash, not the strings themselves. Also the
* #)$*#$(#$*)_# IAR compiler doesn't generate the code you expect
* sucking away your RAM! #$__*)#$* IAR will not let you put an array
* of pointers into flash, but it will allow you to put an array of
* structures into flash.
*/
typedef uint16_t (*cmdfunc_t)( uint8_t const *string_u8 );
typedef struct /* define the struct 'cmd_entry' */
{
PGM_P string; /* Pointer to string in flash */
cmdfunc_t function;
}str_func_entry;


static const char cmd_str_firmware_update[] PROGMEM = "Firmware_Update";

static const str_func_entry cmd_func_table[] PROGMEM= /* Declare a constant object of type 'cmd_entry' */
{/* Keep in Alphabetical order for the Help command: */
{cmd_str_firmware_update, bootload_jump_func}
};
#define COMMANDS_AVAILABLE (sizeof( cmd_func_table ) / sizeof( str_func_entry ))

static uint16_t cmd_help_func( uint8_t const *string_u8 )
{
UNUSED( string_u8 );

strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );
strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );

for( uint_fast16_t number_of_patterns_u16 = 0U; number_of_patterns_u16 < COMMANDS_AVAILABLE; number_of_patterns_u16++ )
{
strout_P( (PGM_P) PGM_READ_WORD( cmd_func_table[number_of_patterns_u16].string ) );
strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );
}

strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );

return( 0U );
}

View solution in original post

2 Replies
2,111 Views
bobpaddock
Senior Contributor III

This is the code I use with GCC.  Some macros make it compatible with AVR-GCC so same code can be used on both ARM and AVR.

#define PGM_P char const *

#define strncpy_P strncpy

#define PROGMEM

#ifndef PGM_READ_WORD
#define PGM_READ_WORD(adr) (adr)
#endif

#define UNUSED( PARAMETER ) (void)(PARAMETER) /** Used to silence 'unused parameter' */

/* Example function: */

static uint16_t bootload_jump_func( uint8_t const *string_u8 );
static uint16_t bootload_jump_func( uint8_t const *string_u8 )
{
UNUSED( string_u8 );
bootload_jump_func(); /* Never returns */
return( 0U ); /* Keep compiler happy, we never get here */
}

/* ******************** Decode incoming ASCII commands ******************** */

/*
* To get the static strings to really be in the flash you have to do
* it this way with structures. The 'obvious' way only gets the array
* of pointers in flash, not the strings themselves. Also the
* #)$*#$(#$*)_# IAR compiler doesn't generate the code you expect
* sucking away your RAM! #$__*)#$* IAR will not let you put an array
* of pointers into flash, but it will allow you to put an array of
* structures into flash.
*/
typedef uint16_t (*cmdfunc_t)( uint8_t const *string_u8 );
typedef struct /* define the struct 'cmd_entry' */
{
PGM_P string; /* Pointer to string in flash */
cmdfunc_t function;
}str_func_entry;


static const char cmd_str_firmware_update[] PROGMEM = "Firmware_Update";

static const str_func_entry cmd_func_table[] PROGMEM= /* Declare a constant object of type 'cmd_entry' */
{/* Keep in Alphabetical order for the Help command: */
{cmd_str_firmware_update, bootload_jump_func}
};
#define COMMANDS_AVAILABLE (sizeof( cmd_func_table ) / sizeof( str_func_entry ))

static uint16_t cmd_help_func( uint8_t const *string_u8 )
{
UNUSED( string_u8 );

strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );
strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );

for( uint_fast16_t number_of_patterns_u16 = 0U; number_of_patterns_u16 < COMMANDS_AVAILABLE; number_of_patterns_u16++ )
{
strout_P( (PGM_P) PGM_READ_WORD( cmd_func_table[number_of_patterns_u16].string ) );
strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );
}

strout_P( text_string_ptr_get( CMDS_TXT_CRLF ) );

return( 0U );
}

2,110 Views
piotrdzierzak
Contributor II

Thank you very much for answer and help!
Very useful sugestions - everything works fine - I checked:)

Best Regards

Piotr