Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I make a function that accepts both ram and rom pointers in Microchip C18?

When I declare a function that accepts const char* and I pass a string literal, I get a

Warning: [2066] type qualifier mismatch in assignment

because string literals are rom const char*. It's the same the other way around.

Though the PIC is Harvard architecture, the memory is mapped into one contiguous address space, so theoretically it should be possible to support both ram and rom pointers the same way. Probably I have to use rom pointers because they are 24 bit while ram pointers are 16 bit.

However, just casting a const char* to a const rom char* does not work.

like image 553
AndreKR Avatar asked May 17 '11 01:05

AndreKR


2 Answers

Unfortunately, this is an inherent limitation of the Microchip C18 compiler. A pointer in C18 can point to either ROM or RAM, but not both.

This is why you will find duplicated functions for ROM and RAM operations in e.g. the Microchip Application Libraries:

BYTE* TCPPutString(TCP_SOCKET hTCP, BYTE* Data);
ROM BYTE* TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE* Data);

The Hi-Tech PICC-18 compiler has the appropriate address space determined at runtime, which allows for more flexible pointer usage. This is one of the reasons I ditched C18 in favour of PICC-18.

See the answers to this question and John Temples' Comparison of Hi-Tech PICC-18 and MPLAB C18 for more insight.

like image 175
makes Avatar answered Oct 12 '22 03:10

makes


Adding to the answer of mizo (I'm unable to comment, as I primarily answer on Arduino.SE and EE.SE)

The XC8 compiler also has the feature to determine the appropriate address space at runtime.

So yes, Hi-Tech PICC-18 does this, but is not the only compiler to do so.

Though I could understand if switching compiler might be impossible at the moment.


For that reason, you might want to use the following functions in string.h

/** @name memcpypgm2ram
 * The {\bf memcpypgm2ram} function performs a {\bf memcpy} where
 * {\bf s1} points to data memory and {\bf s2} points to program
 * memory.
 * @param s1 pointer to destination in data memory
 * @param s2 pointer to source in program memory
 * @param n number of characters to copy
 */
void *memcpypgm2ram (auto void *s1, auto const MEM_MODEL rom void *s2, auto sizeram_t n);

/** @name memcpyram2pgm
 * The {\bf memcpyram2pgm} function performs a {\bf memcpy} where {\bf s1} 
 * points to program memory and {\bf s2} point to data memory.
 * @param s1 pointer to destination in program memory
 * @param s2 pointer to source in data memory
 * @param n number of characters to copy
 */
MEM_MODEL rom void *memcpyram2pgm (auto MEM_MODEL rom void *s1, auto const void *s2, auto sizeram_t n);

And you could make your function like:

void YourStringFunction(ramstring);

void YourStringFunctionAccpetingRom(romstring){
YourStringFunction(memcpypgm2ram(romstring));
}

^This isn't actual code, more psuedo code. Also, I'm not sure if it's efficient.

like image 40
Paul Avatar answered Oct 12 '22 05:10

Paul