CCS C pointer problemi,

Başlatan esensoy, 11 Mayıs 2013, 10:53:47

esensoy

Ekte ki resimde ki kod ansi c ile yazılmış, büyük ihtimalle CCS C nin uyumsuzluğundan problem oluyor,
problem şu;
TCHAR  8 bit integer dan türetilme,
create_name fonksiyonuna const TCHAR **path ile pic romunda tutulan, ismi 0085.TXT olan dosyanın ilk byte adresi olan 0xFEE2 geliyor,
fonksiyon içinde de const TCHAR *p diye bir pointer üretiyor,
for (p = *path; *p == '/' || *p == '\\'; p++) ;
satırında p ye 0xFEE2 adresini ataması lazım, *p ile de o adreste ki bilgiyi '/' ile karşılaştırması lazım,
fakat CCS boyle yapmıyor,
3 satır altta ki  w = p[si++]; kodu işletildiğinde w ye 0xFEE2 de ki dosya ilk karakteri olan 0x30 u atması gerekirken, data memory 0x213 adresinde ki 0x10 bilgisini atıyor,
dolayısıyla kod hata vererek çıkıyor,
nasıl düzelir bu durum?
En tehlikeli an "zafer" anıdır.

JKramer

Derleyicinin kurulum klasörünün kök dizininde Readme.txt dosyası var; biraz altlarda ram, rom ve pointer'larla ilgili bir bölüm olması lazım. Şimdi çıkmam gerekiyor, bulamazsanız birkaç saat sonra eklerim.

esensoy

   char id;                    id is stored in RAM
   char rom id;                id is stored in ROM
   rom char id;                id is stored in ROM
   rom char * id;              id is stored in RAM, is a pointer to ROM
   rom char rom * id;          id is stored in RAM, is a pointer to ROM
   char rom * id;              id is stored in RAM, is a pointer to ROM
   char * rom id;              id is stored in ROM, is a pointer to RAM
   rom char * rom id;          id is stored in ROM, is a pointer to ROM

Yanlışsam düzeltiniz,
const TCHAR *p; şeklinde tanımlanmış, yani yukarıdakilerden 4. ye uyuyor, ramde tutulan ama rom a işaret eden, fakat rom a işaret etmiyor 0x213 adresinde ki 0x10 a işaret ediyor,
bir diğer anlamadığım da
p = *path; ile p ye atanan 0x213 nereden geliyor?

ben fonksiyon içerisinde int8 a; diye bir değişken tanımlasaydım, path in gösterdiği, romun 0xFEE2 adresinde bulunan ve dosya isminin ilk harfi olan 0x30 u bu a değişkenine aşağıdakilerden hangisi ile atarım?
a= path;
a= *path;
a= **path;
a= &path;
En tehlikeli an "zafer" anıdır.

JKramer

Dün evde Proteus kurup biraz baktım, önce CCS'in forumundan alıntı yapayım:

http://www.ccsinfo.com/forum/viewtopic.php?p=146255

Alıntı YapRead the manual......

It is down to understanding that in the PIC, you have a separate memory space for program memory, and for the RAM. Different addresses. On many of the older chips, there was no hardware ability to actually read a specified location in program memory. So a 'pointer' could not be constructed. This is the CCS default.
Now on modern chips the ability does exist, but for reverse compatibility, and because doing this involves a significant amount of extra code, the _ROM_ data type is used for a constant for which a pointer can be constructed (you can change this with a setting). Alternatively, if you use 'ANSI' for the compiler setup, 'CONST' is no longer stored in ROM, but becomes a 'read only' definition for a RAM variable, for which a pointer can then be constructed, but at the cost of using a lot more RAM....

Best Wishes

https://ccsinfo.com/forum/viewtopic.php?t=50045&view=next
Alıntı YapLets 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

Yani ROM'a işaret etmek mümkün ama doğrudan ROM'un adresini atamak mümkün değil. Sizin durumunuzda fonksiyona ROM adresini geçiyorsunuz ama pointer'a atadığınızda onu data memory adresi olarak değerlendiriyor (0xFEE2, data memory'de mevcut değil).

Doğrudan ROM adresini yazamasak da şöyle bir kullanım mümkün:
(...)
rom int8 value=0xAA;
rom int8 *p;
int8 x;
(...)
p=(int8 *)&value;
x=*p;


ROM adresini kullanmak istersek read_program_memory fonksiyonu varmış:
(...)
#rom 0xFEE2 = {0x3030, 0x3538, 0x2E54}
char buffer[10];
(...)
read_program_memory(0xFEE2,buffer,6);

esensoy

Değerli vaktinizi ayırdığınız için teşekkür ederim,
Şöyle birşey yaptım,
int16 *k;
türünden bir değişken oluşturdum,
k=path; dedim,
sonra fonkisyon içinde ki tüm 'path' leri k ile değiştirdim, o kısmı çözdüm,

FRESULT create_name (
   DIR *dj,         /* Pointer to the directory object */
   const TCHAR **path   /* Pointer to pointer to the segment in the path string */
)
{
#if _USE_LFN   /* LFN configuration */
   BYTE b, cf;
   WCHAR w, *lfn;
   UINT i, ni, si, di;
   const TCHAR *p;
   int16 *k;

k=path;

   /* Create LFN in Unicode */
   for (p = *k; *p == '/' || *p == '\\'; p++) ;   /* Strip duplicated separator */
   lfn = dj->lfn;
   si = di = 0;
   for (;;) {
      w = p[si++];               /* Get a character */
En tehlikeli an "zafer" anıdır.