|
|
View previous topic :: View next topic |
Author |
Message |
arocholl
Joined: 14 Dec 2008 Posts: 21
|
DSRPAG / DSWPAG - EDS mode in RAM for PIC24 / DSPIC33 parts |
Posted: Mon May 20, 2013 8:24 am |
|
|
Some large RAM parts such as PIC24EP and dsPIC33EP can handle (and has internal RAM well above) 32KB RAM, but these parts use a paginated RAM which requires handling the DSRPAG and DSWPAG registers.
When compiling any of these parts into any recent CCS compiler version, you get access to the first 32KB only, and apparently compiler has no support for declaring variables or accessing them in the paginated mode, therefore any address beyond 32KB is unavailable for the compiler.
Besides using ASM to interact and define variables in a manual way, does anyone has a better suggestion or prior experience on any CCS trick to do the job in C ?
TIA |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon May 20, 2013 8:58 am |
|
|
Potentially Addresmod.
Generic function that allows you to interface any form of memory and use it as if it is a variable for the compiler. Has worked in several compiler versions, but also has the habit of going faulty as CCS fiddle with something else.
There is no need to look at assembler. Remember you can access registers directly with #byte and #word.
So you'd need something like (guess only....).
Code: |
#word DSRPAG=getenv("SFR:DSRPAG")
#word DSWPAG=getenv("SFR:DSWPAG")
void epage_Read(unsigned int32 addr, unsigned int8 * ram, unsigned int8 bytes)
{
unsigned int16 page_number;
unsigned int16 address_to_use;
page_number=addr/0x8000;
address_to_use=(addr & 0x7FFF) ! 0x8000; //low 15 bits with bit 15 set
DSRPAG=page_number;
memcpy(ram,address_to_use,bytes);
}
void epage_Write(unsigned int32 addr, unsigned int8 * ram, unsigned int bytes)
{
unsigned int16 page_number;
unsigned int16 address_to_use;
page_number=addr/0x8000;
address_to_use=(addr & 0x7FFF) ! 0x8000; //low 15 bits with bit 15 set
DSWPAG=page_number;
memcpy(address_to_use,ram,bytes);
}
addressmod (high_memory,epage_read,epage_write,0,0x7FFF);
//Then you can declare variables with:
int32 high_memory test_variable;
test_variable=23;
//etc..
|
Now not sure if memcpy, will work with the page registers selected, or if addressmod is working in the current compiler (haven't had cause to use it recently).
Might be worth an experiment!.....
Best Wishes |
|
|
arocholl
Joined: 14 Dec 2008 Posts: 21
|
|
Posted: Tue May 21, 2013 6:47 am |
|
|
Good input, I didn't think on Addresmod this way before your post, but more like a EEPROM or External RAM interface... Assuming it works as advertised, it could be a good workaround for some uses of upper RAM pages, albeit with some noticeable overhead for accessing it.
As I perceive it, the limitation of this approach is - except I am not interpreting the proposed functionality correctly - it will work fine to move data in and out of a given page to / from lower RAM, but hardly being any effective for storing data from RS232 or SPI directly.
I used your code template, made some corrections and gave addressmod a try with recent 4.140 compiler. Results are disappointing.
Code: |
void epage_Read(unsigned int32 nAddr, unsigned int8 * pBuffer, unsigned int8 nSyze)
{
unsigned int16 page_number;
unsigned int16 address_to_use;
page_number=nAddr/0x8000;
address_to_use=(nAddr & 0x7FFF) | 0x8000; //low 15 bits with bit 15 set
DSRPAG=page_number;
memcpy(pBuffer,address_to_use,nSyze);
}
void epage_Write(unsigned int32 addr, unsigned int8 * ram, unsigned int bytes)
{
unsigned int16 page_number;
unsigned int16 address_to_use;
page_number=addr/0x8000;
address_to_use=(addr & 0x7FFF) | 0x8000; //low 15 bits with bit 15 set
DSWPAG=page_number;
memcpy(address_to_use,ram,bytes);
}
addressmod (high_memory,epage_read,epage_write,0x8000,0xFFFF);
void main()
{
int nInd=0;
for (nInd=0; nInd<sizeof(arrData); nInd++)
{
arrData[nInd]=nInd;
}
//Then you can declare variables with:
int32 high_memory test_variable;
test_variable=23;
}
|
The major problem comes with the simple "test_variable=23", the compiler generates complete bogus code. It considers the int32 being a 8 byte buffer, not sure why, but more importantly it calls the "read" function, rather than the "write" function.
Code: |
56: test_variable=23;
00027E 200175 MOV #0x17, W5
000280 200006 MOV #0x0, W6
000282 B3C080 MOV #0x8, W0 <--- this is wrong
000284 B7F0D6 MOV.B WREG, nSyze
000286 280004 MOV #0x8000, W4
000288 888684 MOV W4, nAddr
00028A EF30D2 CLR 0x10D2
00028C 2000A4 MOV #0xA, W4
00028E 8886A4 MOV W4, pBuffer
000290 020200 CALL epage_Read <--- this is *very* wrong
|
Maybe with some tweaks this may end up working, somehow (e.g. reverse the function definition so writes call read on purpose, so end code is correct, etc) but this seems to be too unreliable for production code. |
|
|
arocholl
Joined: 14 Dec 2008 Posts: 21
|
|
Posted: Tue May 21, 2013 7:00 am |
|
|
As a side note, as you may expect #locate doesn't work either. It generates code for the assigned address with no care or extra code to handle pages, just tries to go to that location with raw code, which does nothing.
Code: |
int32 nVarInEDS;
#locate nVarInEDS=0x8100
...
nVarInEDS=32;
nVarInEDS=45;
|
will generate bogus code like this
Code: |
50: nVarInEDS=32;
00023E 200204 MOV #0x20, W4
000240 781F84 MOV W4, [W15++]
000242 F98100 POP nVarInEDS
000244 200004 MOV #0x0, W4
000246 781F84 MOV W4, [W15++]
000248 F98102 POP 0x8102
|
|
|
|
arocholl
Joined: 14 Dec 2008 Posts: 21
|
|
Posted: Tue May 21, 2013 7:51 am |
|
|
Just for reference of anyone interested, this is the code I will end up using, short of any other higher level suggestion.
Code: |
//Required: Set write page register to the right value,
//no need to change further for systems with less than 64KB RAM, as one page is enough
DSWPAG=1;
//Ideally, this should be enough for standard C assignment to work from this point on but
//CCS compiler uses push/pop for value assignment, whereas the CPU needs a MOV to work on
//EDS page areas, so you have no choice but assign with ASM entry like this (make sure bit 15 is 1)
//This code below sets 7 in the byte address at 0x8100.
#asm asis
MOV #7,W0
MOV #0x8100,W1 //Bit 15=1, therefore DSWPAG is used, EDS address is accesible. Note this is actually address 0x0100 in page 1.
MOV W0,[W1]
MOV #0x7F00,W1 //Bit 15=0, therefore DSWPAG is not used, EDS address is not accesible
MOV W0,[W1]
#endasm
|
Last edited by arocholl on Tue May 21, 2013 6:01 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue May 21, 2013 2:01 pm |
|
|
Unfortunately, addressmod, was working a few compiler versions ago, and went faulty when I last tried it. Hadn't tested with recent compilers....
Best Wishes |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1346
|
|
Posted: Tue May 21, 2013 7:44 pm |
|
|
When the compiler generates data lengths twice their normal size, that is normally for reading from program memory (32bits would take 64bits in program memory for these types of chips). You might pass along an example to the CCS support team (via email) and see if they can give you an idea about why it is doing that.
The example using #locate does generate correct assembly for the code written. The compiler isn't going to know enough to implement ESD automatically so it will simply implement moving a 32bit value to address 0x8100. Remember that "MOV W4, [W15++] " is the same calling PUSH with the contents of W4 for a PIC24/dsPIC33 chip.
So the steps are:
Load 0x20 into W4
PUSH W4 onto the stack
POP to nVarInEDS
Load 0x00 into W4
PUSH W4 onto the stack
POP to (nVarInEDS+2)
Which is what the assembly is doing
Which PIC are you using specifically? I was going to play around with it but couldn't figure out which PIC you were using. |
|
|
arocholl
Joined: 14 Dec 2008 Posts: 21
|
|
Posted: Wed May 22, 2013 3:26 am |
|
|
jeremiah wrote: | When the compiler generates data lengths twice their normal size, that is normally for reading from program memory (32bits would take 64bits in program memory for these types of chips). You might pass along an example to the CCS support team (via email) and see if they can give you an idea about why it is doing that. |
That may be it. I know how it works if you try to use PSV or normal FLASH memory access. My point was that if the compiler was smart enough to know you are accessing an EDS RAM area, it shouldn't access memory that way. So clearly addressmod assumes reading from FLASH only. That format will not work for EEPROM or external RAM either (where you do not need to double size in bytes) so addressmod doesn't seem to account for EEPROM access even though documentation seems to point to that in the example code.
jeremiah wrote: | The example using #locate does generate correct assembly for the code written. The compiler isn't going to know enough to implement ESD automatically so it will simply implement moving a 32bit value to address 0x8100. Remember that "MOV W4, [W15++] " is the same calling PUSH with the contents of W4 for a PIC24/dsPIC33 chip. |
Right. That is my point. The compiler doesn't know, but it could. The compiler should know, for these chips, that bit 15 of the EA is 1 in this address, and based on that understand it is beyond the normal memory region accessible without EDS and therefore handle DSxPAG. But it doesn't. If you play with #locate address 0x8100, the interesting thing is the compiler doesn't generate code for a 0x8100 address, because that will actually work for a <64KB part (only one extra EDS page). However, the ASM generated code clears the bit 15 and you get a 0x0100 address - and that is SFR TMR1 - nothing to do with the intended 0x8100 address.
I am not saying #locate would be the correct way to handle EDS, but in case someone was tempted to use #locate, it doesn't work.
One could argue a simplified EDS is not too different than near and far RAM memory region, which the compiler actually handles ok (generates compact instructions for near region, and larger instructions for far region).
jeremiah wrote: | So the steps are:
Load 0x20 into W4
PUSH W4 onto the stack
POP to nVarInEDS
Load 0x00 into W4
PUSH W4 onto the stack
POP to (nVarInEDS+2)
Which is what the assembly is doing |
It is, but again that is not compatible with any possible us of EDS. The EDS works with MOV only (not with push), and you need to force the bit 15 to 1 in order for the EDS to work. None of the generated CCS code is compatible with that.
jeremiah wrote: | Which PIC are you using specifically? I was going to play around with it but couldn't figure out which PIC you were using. |
You can use any of the PIC24EP512xxx or DSPIC33EP512xxx parts, such as DSPIC33EP512GP806. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1346
|
|
Posted: Wed May 22, 2013 6:19 am |
|
|
On the first issue: Did you send CCS support an example and tell them what isn't working? Hopefully they can fix it. Make sure you specify that both addressmod and EDS are not working correctly.
On the second issue: Yes, but the point was that CCS wasn't creating bogus assembly, it was generating correct assembly. Bogus code would indicate incorrect assembly. I agree though that they should add in support for EDS for ya. I am hoping your email from the first issue will get that ball rolling so you can get this resolved. |
|
|
arocholl
Joined: 14 Dec 2008 Posts: 21
|
|
Posted: Wed May 22, 2013 6:26 am |
|
|
I will send this to CCS, but they will probably put it in the same queue other of my (old) requests are waiting for any attention, so not very optimistic.
In the second topic, it is still bogus code IMHO. Here is the reason: you are coding for a 0x8100 address, which is not part of the standard addressable RAM, but the ASM code generated by CCS is done as if it was. If the compiler doesn't support EDS, that is fine, then it should generate an error because the underlying MCU targeted for that assembler code will not work as expected. I would consider a "Out of valid RAM range" or the like as the valid, minimally safe approach, reported by the compiler, not silent wrong generated ASM. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1346
|
|
Posted: Wed May 22, 2013 6:31 am |
|
|
If they don't respond in a day, give them a call. It's generally better if you call and use the customer service extenstion (I thnk it is 35) if you aren't getting responses. The CCS tech guys are generally pretty good when you talk with them. |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Sun Jul 14, 2013 3:16 am |
|
|
Addressmod is quite interesting feature, the issues with it I addressed few times in this forum already.
A friend of mine escalated the issue to CCS per email (the issue with not compiling the write function) in Feb2013, they got details with an example code (they got everything they asked for), a ticket has been risen, but nothing happened.
I saw 5.009 version and still the "write" function is not being compiled, instead it points to "read" function within the code. My understanding is it is maybe 5 minutes of work for them to fix that (as it worked somewhere around 4.13x).
Maybe a native speaker may call the guys and explain verbally, when the source code, disassembly, etc. (and other files they asked for) and detail description is not enough for them
BTW, they call it a "Feature Exclusive to CCS Compiler"
PS: this has been received from them when asked on status (Feb2013, July2013):
Quote: | Your e-mail has been assigned to someone in Tech Support.
As of yet, we have not had time to further review your e-mail. |
|
|
|
|
|
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
|