|
|
View previous topic :: View next topic |
Author |
Message |
webbone
Joined: 20 Sep 2004 Posts: 14 Location: Sacramento, CA
|
Question regarding #ROM directive, lookup tables |
Posted: Tue Mar 01, 2005 7:57 pm |
|
|
I have read through many of the posts here regarding lookup tables and string storage in program memory and have determined I will need to write my own routines in assembly using the TABLxxx registers (I'm use to doing things this way on 8x51 microcontrollers).
My question is: Is there a way to utilize labels for addresses and have the assembler/linker resolve them? Specifically, doing something like this (not truly PIC assembly):
Code: |
//tables
#ORG 2000
TableBase:
Msg1:
DB 0x40,'Hello World!',0x00
Msg2:
DB 0x40,'Goodbye All',0x00
Msg3:
DB 0x10,'Read ERR',0x00
//Code
MOVLW #ADDR_UPPER[Msg1]
MOVWF TBLPTRU
MOVLW #ADDR_HIGH[Msg1]
MOVWF TBLPTRH
MOVLW #ADDR_LOW[Msg1]
MOVWF TBLPTRL
READ_TABLE:
TBLRD*+
...etc...
|
I'm assuming there isn't a way to just use &Msg1 - on other assemblers I'm used to there are SEGMENT() and OFFSET() operators to extract the appropriate part of the address. If there is something of this sort available with the CCS compiler I can manage all of the rest in assembly no problem.
Suggestions are welcome.
My fallback is to write a table generator program that calculates the lengths and creates a bunch of #ROM statements with the appropriate addresses and also a set of #DEFINE statements so I can use the "labels" later in code but that is rather messy and requires multiple, non-automated steps in order to just make some text changes, etc. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 01, 2005 8:48 pm |
|
|
You should tell us what your overall purpose is.
Other board members may already have solved your problem.
But here is a possible answer to your immediate question.
By using the label_address() function, you can extract the
address of the string data.
Code: | #include <18F452.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
const char array[] = {"ABC"};
void main()
{
int16 ptr;
ptr = label_address(array);
while(1);
} |
Here is part of the .LST file, which shows the address of the string data:
Code: | 0006 4241 00007 DATA 41,42
0008 0043 00008 DATA 43,00 |
Here's the code that loads address 0x0006 and stores it in ptr.
Code: | 0000 00310 ... ptr = label_address(array);
0018 0E00 00311 MOVLW 00
001A 6E03 00312 MOVWF 03
001C 0E06 00313 MOVLW 06
001E 6E06 00314 MOVWF 06
0020 C003 F007 00315 MOVFF 03,07 |
Here's part of the symbol table. The RAM address of ptr is also 0x0006
but that's just a coinicidence. The string is in ROM and the ptr is in RAM.
|
|
|
webbone
Joined: 20 Sep 2004 Posts: 14 Location: Sacramento, CA
|
|
Posted: Tue Mar 01, 2005 8:57 pm |
|
|
THanks for the reply. I had failed to specify that I'm working on a 18F8720 processor in this application.
My overall purpose is to be able to have string tables in ROM that can be read using the TBLPTR hardware in the processor, the end destination of which will be external hardware (mostly) and possibly one of the serial ports.
It looks like the label_address() function will do what I'm asking for, especially since I'm in Microcontroller mode and don't have to worry about the TBLPTRU value. |
|
|
Ttelmah Guest
|
|
Posted: Wed Mar 02, 2005 4:48 am |
|
|
Remember though, that the compiler is perfectly capable of doing this for you.
If you declare a 'const' array, it stores it in ROM, and handles the address calculations, and the table read operations automatically. You seem to be 'making work' for yourself...
Best Wishes |
|
|
webbone
Joined: 20 Sep 2004 Posts: 14 Location: Sacramento, CA
|
|
Posted: Thu Mar 03, 2005 11:53 am |
|
|
Ok, I have tried the suggested method but it seems that I cannot construct items the way I showed in my first post. Specifically, this does not work:
Code: | const char Msg1[] = {0x17,"ABC",0x00}; |
I have tried changing datatypes to no avail as well - the error "expression must evaluate to a constant" comes up. I understand this isn't what C is expecting, but I don't want to have to write {0x17,0x41,0x42,0x43,0x00} - only the first and last "characters" need to be entered that way, all other data needs to be a string.
My "strings" have a first "character" which will either be an offset or an opcode (depending on the target they are used with), followed by the string data, followed by a terminator (0x00) or opcode (0x80-0xFF). The routine which "reads" this data understands this structure - I'm just trying to come up with a convenient way I can build messages as I showed above which I have previously been able to do just with DB.
Any suggestions will be greatly appreciated. As I mentioned earlier if I have to I will write an external program to generate include files but it would be nice not to have to do so. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 03, 2005 1:05 pm |
|
|
Quote: | const char Msg1[] = {0x17,"ABC",0x00}; |
That statement won't work in any C. Load up MSVC++ 6.0 and you'll get:
error C2078: too many initializers |
|
|
webbone
Joined: 20 Sep 2004 Posts: 14 Location: Sacramento, CA
|
|
Posted: Thu Mar 03, 2005 1:19 pm |
|
|
I now understand that C doesn't recognize what I am trying to do. I am guessing there is no convenient way to do this as I have shown so I will have to resort to writing a program to generate an include file (the progam will translate the strings so that the entire declaration is just 0x41,0x42, etc..) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 03, 2005 1:49 pm |
|
|
You're too eager to give up. What if you look at Ttelmah's recent
post here, http://www.ccsinfo.com/forum/viewtopic.php?t=21974
and modify it a little bit, to give the test program shown below.
It displays this result on the terminal window:
17 ABC
I didn't include the last 0x00 that you have in your example,
because strings are automatically terminated with a 0x00 by
the compiler. If you still want it, you can add it to the
structure declaration.
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
struct T_MSG
{
char MsgNum;
char Msg[4];
};
const struct T_MSG Messages[2] =
{
{0x17, "ABC"},
{0x18, "DEF"}
};
//const char Msg1[] = {0x17,"ABC",0x00};
//============================
main()
{
char c;
char i;
char array[20];
c = Messages[i].MsgNum;
strcpy(array, Messages[i].Msg);
printf("%x %s \n\r", c, array);
while(1);
} |
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Mar 03, 2005 2:01 pm |
|
|
Code: | const char Msg1[5] = {"\27ABC"}; |
Will do what you want. Note that you don't have to include the 0x00 since the string is already NULL terminated. Note that the numeric code is in octal so 0x17 is 27 octal. |
|
|
|
|
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
|