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

Problem with data and ROM

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



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

Problem with data and ROM
PostPosted: Mon Aug 11, 2014 4:25 am     Reply with quote

Hello everyone !

I have got a problem with my code and I would like to know if you can help me to fix it.
I am programming a dsPIC33EP512MU810 with CCS + MPLAB8.92.

My problem is about ROM, CONST, "Attempt to create a pointer to a constant...


I have found this great topic (http://www.ccsinfo.com/forum/viewtopic.php?t=34302) that helps me to understand what is the problem and try new solutions.

However I still get some errors.

So, my first step is : i would like to store data type float in rom (I cannot store in RAM because tables are too big and I get the error : "Not enough RAM for all variables")
Then, I would like to get access to this data in order to do operation (a multiplication for example).


Here is my code.

Code:
#include <33EP512MU810.h>
#DEVICE ICD = true, ICD = 3

#FUSES NOPROTECT, NOWRT, NOGSSK, NOAPROTECT, NOAPLK, NOWDT, PUT16, RESET_PRIMARY, HS, CKSFSM, PLLWAIT, NOIOL1WAY,IESO, NOJTAG
#USE DELAY (CLOCK = 140MHz)



 float matrix1[2][2]={{10.28,4.34},{5.0,-0.0078}};
 float matrix2[2][2]={{1.0,0.0},{0.0,1.0}};
 float result[2][2]={{0.0,0.0},{0.0,0.0}};


void multiplication(float *mat1,float *mat2,float *res){
    int8 i=0;
   int8 j=0;
   int8 k=0;

       for(i=0;i<2;i++){
           for(j=0;j<2;j++){
            *(res+(2*i)+j)=0.0;
             for (k=0; k<2; k++){
                   *(res+(2*i)+j)=(*(mat1+(2*i)+k))*(*(mat2+(2*k)+j))+*(res+(2*i)+j);
             }
            }
      }

}

void main(){

multiplication(matrix1,matrix2,result);
while(1);   
}


Matrix1 and Matrix2 are in RAM.
So it works perfectly, I have got good results (monitoring the watch).

I have to precise some points :
- initially matrix1 and matrix2 are much bigger (matrix[6000][1]) So in this example, I simplifiy it (otherwise, I will get 'Not enough RAM for all variables')
- Pointers are something new for me (feel free to correct me if necessary)


Now, I have to store Matrix1 et matrix2 in ROM.

Quote:
Then it gets more complex, since the declaration 'CONST=READ_ONLY', makes all constants copy to RAM automatically (uses a lot of space...)

I cannot use CONST=READ_ONLY because I cannot afford to make all constant copy to RAM. It will be okay just a part but all, it will use a lot of space.

I cannot use CONST (for example, const float matrix1[2][2]={{10.28,4.34},{5.0,-0.0078}};) because i will get the errors : "Attempt to create a pointer to a constant"

So my last choice is ROM.

Code:
#include <33EP512MU810.h>
#DEVICE ICD = true, ICD = 3

#FUSES NOPROTECT, NOWRT, NOGSSK, NOAPROTECT, NOAPLK, NOWDT, PUT16, RESET_PRIMARY, HS, CKSFSM, PLLWAIT, NOIOL1WAY,IESO, NOJTAG
#USE DELAY (CLOCK = 140MHz)



 rom float matrix1[2][2]={{10.28,4.34},{5.0,-0.0078}};
 rom float matrix2[2][2]={{1.0,0.0},{0.0,1.0}};
 float result[2][2]={{0.0,0.0},{0.0,0.0}};

void multiplication(rom float *mat1,rom float *mat2,float *res){
    int8 i=0;
   int8 j=0;
   int8 k=0;

       for(i=0;i<2;i++){
           for(j=0;j<2;j++){
            *(res+(2*i)+j)=0.0;
             for (k=0; k<2; k++){
                   *(res+(2*i)+j)=(*(mat1+(2*i)+k))*(*(mat2+(2*k)+j))+*(res+(2*i)+j);
             }
            }
      }

}

void main(){

multiplication(matrix1,matrix2,result);
while(1);   
}


However, the WATCH displays "Restricted Memory" instead real values.
I don't get it.
So after a new research, i found that :
http://www.microchip.com/forums/m256044.aspx#256044

Quote:
The device reserves some memory so that you are able to debug using the ICD 2. During debugging, the 30F is running a 'debug executive' that is programmed into Test Memory on your device. This piece of code is constantly running between steps. It does require use of a portion of user RAM. For this device, it needs location 0x800 to 0x822.

Therefore, you cannot and should not use these locations.


In my case, I use ICD3 and an other PIC.
I don't know how to use other location.
Do you know ?

If someone has a solution (or even an other idea) how to solve this problem, it will be great.

Let me know if you need more information


Thanks
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Mon Aug 11, 2014 6:02 am     Reply with quote

I would like to add :
If you try to simulate with MPLAB SIM, it won't work and you get weird results (MPLAB SIM doesn't work with dsPIC33EP512MU810).

So, if you have some ideas, just tell me and I will try to fix with my materiel.

Feel free to ask question or ask more precisions if necessary.

I am going to search again as well for my side and I hope we will find a solution.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 3:44 am     Reply with quote

First key thing is to understand 'why' you have a problem. This is down to the architecture of the PIC. Unlike most modern common processors, the PIC uses separate memory address spaces and busses for the RAM, and ROM. This means there is 'address 5', in the RAM data space, and also 'address 5' in the ROM data space. This is why a simple pointer can't be constructed to ROM.
The reason for this, is it allows ROM and RAM fetches to be overlapped, giving relatively good performance without the cost of a high speed cache memory, but comes at the cost of having two address spaces....

Now CCS allows you to construct a pointer to ROM, but the value pointed to be such a pointer, can't directly be read when debugging. A program memory read, has to be carried out to fetch the value, it can't be simply used as an 'address'. The number it uses if you try to access RAM with it, can be pointing anywhere....

Now, is it that you want to have a lot of such constant arrays, and use the one routine to build the result?. If so, then have just a single pair of RAM arrays, copy the data to these. Only the array actually being used, then needs be in RAM, and debug can be used as normal on this. This is both faster, and safer.

Particularly on your chip.
Unfortunately, several of the 'tricks' available to allow pointers to constants, don't work on the really big PIC33's. This is the second 'core' problem...

There is a glaring problem in the maths. the 'result' matrix starts containing all zeros. Each line multiples the two source matrix entries by the result matrix. Result will therefore always be zero....

Then have you actually run a chip?. You specify HS, and your final 'target' frequency, but never tell the compiler what your crystal frequency is. Without this, it can't setup the PLL.
On these chips, as well as setting up the oscillator (HS), you also have to enable it as well (PR, or PR_PLL).

Now, that having all been said, consider:
Code:

#include <33EP512MU810.h>
#DEVICE ICD = true, ICD = 3

#FUSES NOPROTECT, NOWRT, NOGSSK, NOAPROTECT, NOAPLK, NOWDT, PUT16, RESET_PRIMARY, HS, CKSFSM, PLLWAIT, NOIOL1WAY,IESO, NOJTAG, PR_PLL
#USE DELAY (CLOCK = 140MHz, CRYSTAL=10MHz)

const float matrix1[2][2]={{10.28,4.34},{5.0,-0.0078}};
const float matrix2[2][2]={{1.0,0.0},{0.0,1.0}};

const float matrix3[2][2]={{10.56,2.34},{5.0,-0.0056}};
const float matrix4[2][2]={{1.0,0.0},{0.0,2.0}}; //Two more arrays to show the approach

#define locate(array,a,b) (array+((2*a)+b)) //memory location for array
#define index(array,a,b) *(locate(array,a,b)) //macro to carry out array indexing.

void multiplication(float *mat1,float*mat2,float *res){
   int8 i=0;
   int8 j=0;
   int8 k=0;
   float d1,d2,d3;

   for(i=0;i<2;i++)
   {
      for(j=0;j<2;j++)
      {
         index(res,i,j)=1.0; //changing to 1
         for (k=0; k<2; k++)
         {
            d1=index(mat1,i,k); //These make nice easy to access debug variables.
            d2=index(mat2,k,j);
            d3=index(res,i,j);
            index(res,i,j)=d1*d2*d3;
         }
      }
   }
}

void main()
{
   float result[2][2]={{0.0,0.0},{0.0,0.0}};
   float mat1[2][2];
   float mat2[2][2];
   //Now the following can be copied for as many constant matrices as required, using the
   //same RAM storage for each.
   memcpy(mat1,matrix1,sizeof(matrix1));
   memcpy(mat2,matrix2,sizeof(matrix2));
   multiplication(mat1,mat2,result);
   
   //so, for another pair of arrays.
   memcpy(mat1,matrix3,sizeof(matrix1));
   memcpy(mat2,matrix4,sizeof(matrix2));
   multiplication(mat1,mat2,result);   
   while(1);   
}


The key here is that 'memcpy', knows how to move values from ROM to RAM, and to handle the maths involved (remember that the ROM is 24bits wide, so trying to access variables is difficult - address has to be *4/3 as you move forward through the ROM....).
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 6:58 am     Reply with quote

Hello Ttelmah,

Thanks for your help, it is very nice.

Alright for the explanation about the architecture of the PIC, I understand better now.

Quote:

Now, is it that you want to have a lot of such constant arrays, and use the one routine to build the result?. If so, then have just a single pair of RAM arrays, copy the data to these.

Yes, it is a good idea. I didn't know ''memcpy', it is very convenient, thanks.

About maths problem, i will check that.

Quote:
Then have you actually run a chip?. You specify HS, and your final 'target' frequency, but never tell the compiler what your crystal frequency is. Without this, it can't setup the PLL.

Yes, I have run it and there are no errors when I build my project. However, I didn't pay attention about frequency.

About your code, I build it and I get one errors :

Quote:
*** Error 99 "main.c" Line 5(5,44): Option invalid No PLL option


When I remove 'CRYSTAL=10MHz', I can build all.
However, when I use THE WATCH to check result values, it displays : 'Reserved memory'.

I think it is because ICD3 reserved memory. Do you know how to fix that ?
According to that link http://www.microchip.com/forums/m256044.aspx#256044 , I have to change location but I don't know how to do that.

Thank you and have a nice day !
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 7:48 am     Reply with quote

The code as posted, compiled for me, and is setting the fuses correctly to run.
Compiler version?.
Check the include file for your processor, and the fuse names.
The crystal value needs to match what you have.

With ICD selected, the compiler should already be reserving the needed RAM addresses. Again what is your compiler version?.

You can #RESERVE any RAM area you want, and then the compiler won't use it. So:
Code:

#include <33EP512MU810.h>
#RESERVE   0x800:0x8022 //must be here before anything else
#DEVICE ICD = true, ICD = 3


For me though, this gives the error that this address range is already reserved for the debugger.....
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 8:27 am     Reply with quote

Compiler version : PCD Compiler V4.128
Here the file I included for my project (33EP512MU810.h) : http://www.filedropper.com/33ep512mu810


Quote:
The crystal value needs to match what you have.

According to the PIC datasheet, the Oscillator Crystal Frequency has 10 MHz as minimum value and 40 MHz as maximum value.

Quote:

For me though, this gives the error that this address range is already reserved for the debugger.....

I am going to check that right now.

Thanks
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 8:41 am     Reply with quote

I have just tested and gets errors unfortunately.

Quote:

Executing: "C:\Program Files (x86)\PICC\Ccsc.exe" +FD "main.c" #__DEBUG=1 +ICD +DF +LN +T +A +M +Z +Y=9 +EA I+="C:\Program Files (x86)\PICC\Drivers\" #__dsPIC33EP512MU810__=TRUE
>>> Warning 225 "C:\Program Files (x86)\PICC\devices\33EP512MU810.h" Line 553(18,53): Duplicate #define
*** Error 99 "main.c" Line 6(5,44): Option invalid No PLL option
*** Error 103 "main.c" Line 8(1,40): Constant out of the valid range 8022 is out of the RAM range
2 Errors, 1 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Tue Aug 12 16:37:38 2014


Error 99 is due to 'CRYSTAL=10MHz' and Error 103 is due to #Reserve
I really don't get it why it doesn't work with me. I am going to search more about 'Option invalid No PLL option'.

If you need more information, feel free to ask.

Thanks again
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 9:22 am     Reply with quote

Double keytap. Look at the address, versus what the debugger needs.

Seriously though _what compiler version_. It accepts PR_PLL, and the crystal, with every compiler I've tried.
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 9:39 am     Reply with quote

Quote:
Double keytap. Look at the address, versus what the debugger needs.

According to MPLAB IDE Help, File registers used are :

Quote:
0x1000-0x101B
0x101C-0x101D
0x101E-0x101F
0x1020-0x1021
0x1022-0x1023
0x1024-0x1027
0x1028-0x104F


Sorry, I don't get it. What do you mean by 'Double keytap' ?

It is strange that It doesn't work with me.
Maybe, I do something wrong ?
--> I create a project with Project Wizard (choose the right PIC reference)
--> add main.c in source Files
--> add 33EP512MU810.h in Header Files
And build all.

Maybe ICD3 Firmware ? What firmware do you use ?

Otherwise, if I remove 'Crystal', why does it display 'reserved memory' for 'result' ?
Have you an idea about that ?

Thanks
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 12:45 pm     Reply with quote

I think I have found a solution ! Very Happy
I have to do more tests to make sure that is right.
So, I will come back tomorrow to keep you informed.

Have a nice evening !
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 1:34 pm     Reply with quote

Quote from your own post:
Quote:

The device reserves some memory so that you are able to debug using the ICD 2. During debugging, the 30F is running a 'debug executive' that is programmed into Test Memory on your device. This piece of code is constantly running between steps. It does require use of a portion of user RAM. For this device, it needs location 0x800 to 0x822.


Difference between 8022, and 822....

As I said, I can't actually use the reserve, since all my compilers state that the addresses are already reserved for the debugger if I select ICD.

Why can't you tell us your compiler version?.
Stuart



Joined: 11 Aug 2014
Posts: 8

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 2:30 pm     Reply with quote

Quote:
Why can't you tell us your compiler version?


Compiler version : PCD Compiler V4.128

Quote:
Difference between 8022, and 822....

Yes, sorry. My compiler states as well that the addresses are already reserved for the debugger if I select ICD3.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Aug 12, 2014 3:27 pm     Reply with quote

I went back to V4, but didn't go this far.

However as you have found the addresses are already reserved.

Are you looking when the code is inside the actual routine?. Otherwise the addresses will be invalid.

On the clock, the key is to test what speed your chip actually is running. The old 'flash an LED' test. If it flashes at the right speed, smile and don't worry. However if not, you'll need to work out a way of setting up the PLL correctly. Some code for programming the PLL was posted here at that sort of time, but you'll probably have to set the fuse with a ROM statement as well.
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