|
|
View previous topic :: View next topic |
Author |
Message |
Dimmu
Joined: 01 Jul 2007 Posts: 37
|
addressmod |
Posted: Fri Apr 04, 2008 3:53 pm |
|
|
Hi all,
I am currently using CCS 4.053 with a PIC18f97J60; with 256 kb of external RAM.
I have searched the forum but did not find the good answer to my addressmod problem : even if the declaration of external variables works fine, the compiler raises an error if I try to declare more than ~4 kb of external memory
Here is a sample of code. It compiles OK but 98% of the ram is used. If I increase the size of IDX4 to 512, then the compilation fails.
Code: |
#include <18F97J60.h>
#FUSES NOWDT, WDT128, H4_SW, NODEBUG, NOXINST, STVREN, NOPROTECT, FCMEN
#FUSES IESO, PRIMARY, ECCPE, ETHLED, NOWAIT, BW16, EMCU20, EASHFT, RESERVED
#device *=16
#use delay(clock=31.500 M )
/*External RAM definition*/
#define EXT_RAM_OFFSET 0x20000
#define EXT_RAM_SIZE 0x40000
void read_ext_ram ( int32 addr, int8 * data, int nb_bytes ) {
// some instruction in the function, not written here to keep the code small
}
void write_ext_ram ( int32 addr, int8 * data, int nb_bytes ) {
// some instruction in the function, not written here to keep the code small
}
addressmod ( EXT_RAM, read_ext_ram, write_ext_ram, EXT_RAM_OFFSET, EXT_RAM_OFFSET + EXT_RAM_SIZE - 1 );
void main(void) {
/*Defining some variables in EXT_RAM area*/
int EXT_RAM IDX0;
int EXT_RAM IDX1;
int EXT_RAM IDX2;
int32 EXT_RAM IDX3[512];
int32 EXT_RAM IDX4[450];
setup_external_memory ( EXTMEM_BYTE_WRITE | EXTMEM_WAIT_0 );
while(TRUE) {
delay_ms ( 250 );
}
}
|
If anybody knows what I forgot to do ?
Best regards,
Dimmu |
|
|
Dimmu
Joined: 01 Jul 2007 Posts: 37
|
|
Posted: Sat Apr 05, 2008 1:41 pm |
|
|
I found the problem.
It seems that the compiler cannot allocate more than 4kb of local variables, even if they are declared in an external memory area.
As soon as I declared them as global variables, it worked fine ( at least it compiled ). Now I'll ensure that everything works fine.
Best regards,
Dimmu |
|
|
Dimmu
Joined: 01 Jul 2007 Posts: 37
|
|
Posted: Sun Apr 06, 2008 2:28 pm |
|
|
...
After few tests, the function is too much bugged to be used right now.
Declaration of the external ram segment :
Code: | #define EXT_RAM_OFFSET 0x20000
#define EXT_RAM_SIZE 0x08000 ==> cannot assign more than 32k on one segment
void read_ext_ram ( int32 addr, int8 * data, int16 nb_bytes );
void write_ext_ram ( int32 addr, int8 * data, int16 nb_bytes );
addressmod ( EXT_RAM, read_ext_ram, write_ext_ram, EXT_RAM_OFFSET, EXT_RAM_OFFSET + EXT_RAM_SIZE - 1 ); |
I can manage to do a simple assignment :
Code: | external_var[i] = local_var[j]; |
but the other more complex tests fails :
Code: | external_var[i] = read_adc(); ==> writes incorrect value in external_var
foo(external_var); ==> the generated call to read_ext_ram makes the *data point to the addr variable
var_pointer = &external_var; ==> creates a 16 bits pointer to somewhere but I don't know where.
|
I think I'm gonna have to pay the support for one year to have all these bugs corrected |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Sun Apr 06, 2008 9:28 pm |
|
|
If you can identify the problem in the assembled code you should get a faster response if you have found a bug. I would be surprised if the compiler supports using external RAM in the same way you use the internal RAM. I would expect for there to be limitations that require workarounds. |
|
|
Ttelmah Guest
|
|
Posted: Mon Apr 07, 2008 2:28 am |
|
|
If you do a search here under the old name (typemod), you may find some of the threads about this function.
Generally, the functions do work, but are more restricted than the manual suggests. For the adc value, put it into a temporary variable first. Some of the internal functions (printf in particular, and read_adc), use the source and destination variables as scratch values during the operation. Unfortunately, this gives problems if they are not in the local RAM, or accessible as if they are.
Have you actually tried using the pointer to the memory?. It certainly did work a few versions ago. The value is odd, because they add an offset to the value to clear the local RAM space, which differs from the apparent offset needed.
For a large RAM, you need to use it as if it is 'paged', assigning multiple read and write functions as needed to address sections of the physical memory. The restriction at 32K for the memory space makes 'sense', if you think in terms that addresses are 16bit values.
They also seem to use a temporary buffer locally for some transfers, restricting the sizes that can be used for some elements.
Some of the problems with these functions were discussed in the V4 problems thread, and in general I'd say that you are much better off treating the external storage more like a disk, and using a local buffer, and moving the copy of this you want, to/from the storage...
Best Wishes |
|
|
Dimmu
Joined: 01 Jul 2007 Posts: 37
|
|
Posted: Mon Apr 07, 2008 5:13 am |
|
|
Thank you for the feedback.
I can confirm that using a temporary variable in the computation of read_adc works fine :
Code: | 1) external_var[0] = read_adc(); ==> works OK
2) temp = read_adc();
external_var[i] = temp; ==> works OK
3) external_var[i] = read_adc(); ==> does not work |
The 32k limit is not such a problem right now and I'll try to paginate the memory with multiple functions. However, in that case I think that it was useless to define an int32 variable as ADRS parameter in the read/write prototypes used with the addressmod.
My need for external memory is not to use it as usual RAM but mainly to hold big messages of ~1 kb each. I'm thus working on a workaround that should allow me to find the actual address [32 bits] of the message and then treat each byte sequentially with the TBLRD*+ and TBLWT*+ function.
The use of small variables declared in external memory shall be done with local copies in usual RAM.
main idea :
Code: | void set_external_addr ( external_variable[0] ); // the call to this function forces the reading
// of external_variable[0] and thus sets the TBLPTR
// data to the requested address
int8 read_byte_and_increment_TBLPTR ( void ); // using the TABLAT and TBLRD*+
void read_byte_and_increment_TBLPTR ( int8 DATA ); // using TABLAT and TBLWT*+ |
I'll try to test that this week and keep this thread updated with the results.
Best wishes,
Dimmu |
|
|
|
|
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
|