CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

How to declare a big string array in ROM?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
E_Blue



Joined: 13 Apr 2011
Posts: 417

View user's profile Send private message

How to declare a big string array in ROM?
PostPosted: Thu Aug 18, 2016 11:30 am     Reply with quote

I have a char type variable that can have values from 0x00 to 0xFF and I need to send a string through the serial port by using that variable to take a string from a string array from ROM.

Example:

Code:

char x;
string str[0xFF]={"zero","one","two"........};

x=getc();
printf(putc,"Result: %s",str[x]);



_________________
Electric Blue
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Thu Aug 18, 2016 12:02 pm     Reply with quote

Depends a little bit on the age of your compiler, and the PIC being used (PIC16's have limitations that the PIC18 doesn't have).

Code:

const char str[0xFF][8]={"zero","one","two"........};
//There is no such type in C as a 'string'....
//A 'string' in C, is an array of characters terminated with a NULL
//Then what you are showing is a two dimensional array, not a one
//dimensional one. You need to size the right hand bracket for whatever the
//largest single element is.

//Then you either use strcpy, to copy this into a temporary RAM buffer. So:
   char temp[10]; //needs to be large enough
   strcpy(temp,str[x]);
   //then print this:
   printf("Result: %s",temp);

//Or if you have a recent compiler, add the line:
#DEVICE PASS_STRINGS=IN_RAM

//after the processor include file, and then:
   printf("Result: %s",str[x]); 

//will work as is.


Printf routes to putc automatically.
E_Blue



Joined: 13 Apr 2011
Posts: 417

View user's profile Send private message

PostPosted: Thu Aug 18, 2016 12:16 pm     Reply with quote

Thanks for your fast answer.

I'm sorry, I forgot to mention that I'm using a PIC18F67J50 and CCS compiler v5.058.

I have two doubts about your example; first, when I add the line

#DEVICE PASS_STRINGS=IN_RAM

to the code, Actually all the strings will be loaded at start in RAM?

Second There's any limit on the array size besides physically ROM size.


Just to know, Can you give one example of one limitation that PIC16 have against PIC18 related to this?
_________________
Electric Blue
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 18, 2016 7:01 pm     Reply with quote

Quote:
when I add the line
#DEVICE PASS_STRINGS=IN_RAM
to the code, Actually all the strings will be loaded at start in RAM?

No. It doesn't copy all constant strings into RAM at the start of
the program, as you are suggesting.

When you call a function such as display_string() in the program below,
it copies "Hello World" from ROM into a RAM buffer. The address of the
RAM buffer is then given to display_string(). The RAM buffer is internally
allocated by the compiler. You don't have control over it. It uses a little
bit of your RAM to do this. The same RAM buffer is used each time.
Code:

#include <18F4620.h>
#device PASS_STRINGS=IN_RAM
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

void display_string(char *ptr)
{
printf("%s", ptr);
}

//======================================
void main(void)
{
display_string("Hello World");

display_string("ABCDE");

while(TRUE);
}



Quote:
There's any limit on the array size besides physically ROM size ?

For the PCM compiler, a const array is limited to the ROM page size.
Example: For a 16F877, this is 2K bytes.

For the PCH compiler, I don't think there's a limit. I tried a const array
of 3700 bytes of text for the 18F4620 and it compiled. Example:
Code:
#include <18F4620.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

int8 const array[3700] =
"The PCB, PCM, and PCH are separate compilers. PCB is for 12-bit opcodes, PCM is for
14-bit opcodes, and PCH is for 16-bit opcode PICr microcontrollers. Due to many
similarities, all three compilers are covered in this reference manual. Features and
limitations that apply to only specific microcontrollers are indicated within. These compilers
are specifically designed to meet the unique needs of the PICr microcontroller. This
allows developers to quickly design applications software in a more readable, high-level
language.
[ I cut the rest of the text for brevity ]
";

//======================================
void main(void)
{
int16 i;
int8 value;

value = array[i];

while(TRUE);
}

All tests were done with compiler vs. 5.061.
E_Blue



Joined: 13 Apr 2011
Posts: 417

View user's profile Send private message

PostPosted: Thu Aug 18, 2016 8:27 pm     Reply with quote

I have to create an array of 256 strings of 12 bytes including the null terminator.
Anyway, if I understand well what you are explaining to me, the compiler will warning me if the array is too big and refuse to compile.

Thanks for your info.
_________________
Electric Blue
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Fri Aug 19, 2016 12:43 am     Reply with quote

The amount of RAM used by 'PASS_STRINGS', is normally quite small. Much less than the size of the strings it handles. A couple of tests I did in the past had it using what appears to be a 'dynamic' buffer of between 16 and 64 bytes. There is a limit on the PIC18's as well on const sizes, but it is something like 64K!.

PASS_STRINGS, 'virtualises' the ROM. Remember on the PIC, the program memory is a completely separate address space. So there is 'address 0' in ROM, and another 'address 0' in RAM. This is why the PIC doesn't just allow a simple linear addressing of the ROM and RAM (like a PC). The advantage of this is that the PIC can be reading bytes from both address spaces at the same time, which gives good performance without involving the complexity of having to add things like cache. Downside is 'how to handle' the two address spaces?...
With 'PASS_STRINGS', the code gives an extended address to the ROM, and automatically buffers the access.

strcpy, is 'overloaded', and knows if it is given a ROM address, to use the code to access this, rather than the normal RAM code. This is the 'old' way of doing this, with you copying the required string to RAM yourself.
E_Blue



Joined: 13 Apr 2011
Posts: 417

View user's profile Send private message

PostPosted: Mon Aug 22, 2016 9:38 am     Reply with quote

Thanks! I have it clear now. Smile
_________________
Electric Blue
ronaldoklais



Joined: 18 Dec 2012
Posts: 13

View user's profile Send private message

PostPosted: Mon Aug 22, 2016 11:05 am     Reply with quote

You can write directly to rom using

#rom ADDRESS = { 0, 3, 11, 2, 3, 4 } // bytes

and then read using read_program_memory(address, dest, size)
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group