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 CCS Technical Support

#ORG controls CONST data but not ROM data ?

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



Joined: 05 Aug 2006
Posts: 149
Location: Redditch, UK

View user's profile Send private message Visit poster's website

#ORG controls CONST data but not ROM data ?
PostPosted: Sun Mar 10, 2013 5:19 am     Reply with quote

I was looking to place read only data structs into some program memory at a a fixed address.

If I use const in combination with #org I can place my data where I like. However since const puts some extra code in front of the data you can't then use a pointer to the memory address to access it. As the manual says you should use expression an expressions like x = value[9] to access it and not a pointer.

The alternative provided by CCS for address pointer access to program memory data is the 'rom' keyword. This works fine and seems by default to place the data a the top of the PICs memory.

However putting a #org in front of the declaration has no effect on where the compiler places the data in memory.

So for this :
Code:
#define OUTPUTS      36

// Each element of route
typedef struct {
   int8   hour ;            // Start Time, hour
   int8   min ;            // Start Time, min
   int1   path[OUTPUTS] ;         // Path of points
} element ;


// Time table
typedef struct {
   int1   days[7] ;         // Valid days of week 0=Sun,1=Mon ...
   int8   beg ;            // First element
   int8   end ;            // Last element
} table ;

#org 0x9000,0x9FFF
// The Elements
rom element table_e[] = {
  // Hr,Mn  0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
   {12,0,   1,0,0,0,0,0,0,0},      // 0
   {12,30,   1,1,1,0,0,0,0,0},      // 1
   {12,45,   1,1,1,1,0,0,0,0},      // 2
   {13,0,   0,0,0,0,0,1,0,0},      // 3
   {13,30,   1,1,1,1,1,1,0,0}      // 4
} ;

// The timetable
rom table table_t[] = {
  // S,M,T,W,T,F,S      b, e
   {0,1,0,1,0,1,0,      1, 2},
   {1,0,1,0,1,0,1,      3, 4}
} ;
#org default


I get the data place here :

Code:
ROM data:
01FFCE: 2A 01 02 55 03 04

01FFD4: 0C 00 01 00 00 00 00 0C 1E 07 00 00 00 00 0C 2D
01FFE4: 0F 00 00 00 00 0D 00 20 00 00 00 00 0D 1E 3F 00
01FFF4: 00 00 00


So why does CCS not allow #org to work with rom keyword Question Is there another way to control address at which 'rom' place the data ?

I am using PCH V4.133
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun Mar 10, 2013 5:33 am     Reply with quote

Use #ROM......

const, puts the program to retrieve the data in front of the data.
rom, add further code, to allow pointers to be generated to the constant data. This requires it to have a separate table to hold the pointers. By default this second table is in the code where the rom is declared, and the actual data table is put at the top of the available address range.
You can locate both of these at locations in memory, by declaring a function to contain then, and using #ORG to specify where this is to be located. 'label_address' can then be used to find where the actual data table is located. In this case, the pointer table will be near the start of the ORG range, and the data table at the end.

The one that locates a value at a specified location without any control program, is #ROM

So:
Code:

#ROM   int16 0x0800 = { 0x0002,     
   0x0091,0x007E,             
   0x02A6,0x02BD,             
   0x0052,0x0052,             
   0x0333,0x0333,             
   0x2082,0x0000,             
   0x0000,0x0000,             
   0x232B                     
}

Generates a table of 28bytes located at 0x800 in the ROM, with no control programs attached.

Best Wishes
nurquhar



Joined: 05 Aug 2006
Posts: 149
Location: Redditch, UK

View user's profile Send private message Visit poster's website

PostPosted: Sun Mar 10, 2013 6:57 am     Reply with quote

Yes, I can se how these suggestions might work but all gets a bit messey.

Using a function wrapper around the data with a label means the scope of the label is only within the function. Thus label_address would have to be used only in that function. So to get the address you would have to pick it up at run-time by executing the function.

Having had a little try at the wrapper idea I am not sure it works.
Code:
#org 0x9000,0x9FFF
void GetElement(element *e, int8 n)
{
adr_table_e:
// The Elements
rom element table_e[] = {
  // Hr,Mn  0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
   {12,0,   1,0,0,0,0,0,0,0},      // 0
   {12,30,   1,1,1,0,0,0,0,0},      // 1
   {12,45,   1,1,1,1,0,0,0,0},      // 2
   {13,0,   0,0,0,0,0,1,0,0},      // 3
   {13,30,   1,1,1,1,1,1,0,0}      // 4
} ;
   int32 adr ;
   //adr = &table_e + (n * sizeof(element)) ;
   adr = label_address(adr_table_e) ;
   printf(termPutc, "Read %d @ %lx\r\n", n, adr) ;
   adr += (n * sizeof(element)) ;
   printf(termPutc, "Read %d @ %lx\r\n", n, adr) ;
   read_program_memory(adr, e, sizeof(element)) ;
}


Still puts data at top of memory :
Code:
ROM data:
01FFCE: 2A 01 02 55 03 04

01FFD4: 0C 00 01 00 00 00 00 0C 1E 07 00 00 00 00 0C 2D
01FFE4: 0F 00 00 00 00 0D 00 20 00 00 00 00 0D 1E 3F 00
01FFF4: 00 00 00


Using #ROM means sacrificying the readability of the structure assignment to a list of hex bytes.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun Mar 10, 2013 9:08 am     Reply with quote

Note how I'm telling the compiler to place an array of int16 values.
You need to add 'default' to the #org declaration.
Remember rom declarations are are in the rom, so inherently static. Their scope is universal. You just need to copy the label address return value into a global variable.

Best Wishes
nurquhar



Joined: 05 Aug 2006
Posts: 149
Location: Redditch, UK

View user's profile Send private message Visit poster's website

PostPosted: Sun Mar 10, 2013 9:42 am     Reply with quote

I don't see how putting the 'rom' data declartion inside a function realy helps any. As even if the function is #org'ed to a fixed memory address the compiler puts the function at the #org address ok but it still puts the data where it likes at the top of memory.

Using #ROM with a list of words will work as you suggest but makes the code much less readable as compared to the struct assignement syntax.

It just seems odd that 'const' can be controlled with #org and 'rom' can't. Seems like a usefull feature to me if CCS are listening.
nurquhar



Joined: 05 Aug 2006
Posts: 149
Location: Redditch, UK

View user's profile Send private message Visit poster's website

PostPosted: Sun Mar 10, 2013 10:34 am     Reply with quote

Well it could be I mis-understood something. I just went back to trying 'const' again and I don't see any code before the program data for the structure access.

That is :
Code:
#define OUTPUTS      36

// Each element of route
typedef struct {
   int8   hour ;            // Start Time, hour
   int8   min ;            // Start Time, min
   int1   path[OUTPUTS] ;         // Path of points
} element ;


// Time table
typedef struct {
   int1   days[7] ;         // Valid days of week 0=Sun,1=Mon ...
   int8   beg ;            // First element
   int8   end ;            // Last element
} table ;

#org 0x1000, 0x10FF default
// The Elements
const element table_e[] = {
  // Hr,Mn  0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
   {11,0,   1,0,0,0,0,0,0,0},      // 0
   {11,30,   1,1,1,0,0,0,0,0},      // 1
   {11,45,   1,1,1,1,0,0,0,0},      // 2
   {13,0,   0,0,0,0,0,1,0,0},      // 3
   {13,30,   1,1,1,1,1,1,0,0}      // 4
} ;

// The timetable
const table table_t[] = {
  // S,M,T,W,T,F,S      b, e
   {0,1,0,1,0,1,0,      0, 2},
   {1,0,1,0,1,0,1,      3, 4}
} ;
#org default


Now put this into memory :
Code:
 Line  Address  Opcode         Label                       Disassembly             

  2045  00FF8    D9D6 usb_init_cs            RCALL usb_detach                       
  2046  00FFA    EF19                        GOTO 0x1432                           
  2047  00FFC    F00A                        NOP                                   
  2048  00FFE    FFFF                        NOP                                   
  2049  01000    000B @const1117             TBLRD+*                               
  2050  01002    0001                                                               
  2051  01004    0000                        NOP                                   
  2052  01006    0B00                        ANDLW 0                               
  2053  01008    071E                        DECF 0x1e, F, BANKED                   
  2054  0100A    0000                        NOP                                   
  2055  0100C    0000                        NOP                                   
  2056  0100E    2D0B                        DECFSZ 0xb, W, BANKED                 
  2057  01010    000F                        TBLWT+*                               
  2058  01012    0000                        NOP                                   
  2059  01014    0D00                        MULLW 0                               
  2060  01016    2000                        ADDWFC 0, W, ACCESS                   
  2061  01018    0000                        NOP                                   
  2062  0101A    0000                        NOP                                   
  2063  0101C    1E0D                        COMF 0xd, F, ACCESS                   
  2064  0101E    003F                                                               
  2065  01020    0000                        NOP                                   
  2066  01022    0000                        NOP                                   
  2067  01024    002A @const1119                                                   
  2068  01026    5502                        SUBFWB 0x2, W, BANKED                 
  2069  01028    0403                        DECF 0x3, W, ACCESS                   
  2070  0102A    FFFF                        NOP                                   
  2071  0102C    FFFF                        NOP                                   
  2072  0102E    FFFF                        NOP                                   
  2073  01030    FFFF                        NOP                               
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Mon Mar 11, 2013 2:43 am     Reply with quote

Lets start with. Second line of your first post:

"However since const puts some extra code in front of the data you can't then use a pointer to the memory address to access it".

Key here is that what extra code you get, depends on the processor involved.

The processor is always generating extra code (rom, or const), but will put it in different locations, depending on processor, and what access you actually do.

Now rom is special. With rom, the compiler generates a 'pointer table', which is stored instead of the actual data in the code, and then the data itself is then stored at the top of the available data range. If you use 'default' with a ORG statement, this sets the available data range. The pointer table, can then be used to generate pointer accesses to the data. This then allows a rom data construct to be put at a known location.

However I have to ask if you really 'need' pointer access?. You can always use address access. Here if a table is at a known location, the read_program_memory function will allow you to access it. Not quite as simple as just using *, but with a couple of macros, this can be made almost as easy.

It is vital to understand, that you can't do 'traditional' pointer access to data in the ROM. This has been described dozens (hundreds) of times before, and is down to the fact that the ROM is not part of the same data space as the RAM on a PIC. So you can't take an address like 0x100, and say fred=*(0x100), and access the ROM. This will access address 100, but in the RAM instead. There is no single instruction fetching of ROM data, instead, you have to setup a table read, to access the ROM area. This is a fundamental difference about the PIC. Now CCS allows this to be hidden, using the rom data construct, automatically generating flags to mark the addresses as 'ROM', but even with this done, you can't then access the table using simple pointers, the compiler at all times has to 'know' that you are using pointers to ROM.

Best Wishes
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