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 support@ccsinfo.com

Reading/Writing Pointers to EEPROM

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



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

Reading/Writing Pointers to EEPROM
PostPosted: Mon Jun 11, 2012 10:27 am     Reply with quote

I am attempting to replace a switch(case) system with function pointers.

My previous code relied on a variable stored in EEPROM so that each time the micro (16LF819) is powered up it would read the EEPROM and know which "setting" it was last used in.
Example:
Code:

mode = eeprom_read(0x00);
switch(mode)
  case1:
  whatev();
  break;

I had hoped that I would be able to do the same with the pointer but I'm unable to compile because of my #ROM 0x2100 {}; line of code.

I attempted to write a pointer to the function I want called when the micro powers up.
Code:
#ROM 0x2100 = {*test}

Gives me compile error: Expression must evaluate to a constant

test(); is the function I want it to run when it powers up.
How I do I write the location of this function (pointer) to eeprom?

I have a sneaking suspicion I'm about to find out about a built in
function that I was unaware of.

Thanks everyone
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 12:30 pm     Reply with quote

You can #org the function, and then since you know the address, you can
just put it into eeprom:
Code:

#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4M)

#rom getenv("EEPROM_ADDRESS") = {0x00, 0x05}

#org 0x500,0x51F
int8 my_func(void)
{
char c;

c = 0x55;

return(c);
}

//==========================================

void main()
{

while(1);
}
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 1:47 pm     Reply with quote

Both the 16F819 and 16F877 datasheets say that ON-Chip Program Memory starts at 0005h. In your #org example you used the starting location as 0x500.

-Are those both referencing the same location in memory?


Also, I can not make sense of what the manual is telling me about the getenv() function. What does this line do:
#rom getenv("EEPROM_ADDRESS") = {0x00, 0x05}

OH wait! It just clicked! It's finding the start address of the
EEPROM so you don't have to look that up for individual devices. Nice!

So whats the best way to determine what my memory end point should be?
Count lines in my .lst file?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 2:01 pm     Reply with quote

Actually, that is the Intel Lo-Hi storage format for the 16-bit value of
0x0500, which is the function's starting address.
http://people.cs.umass.edu/~verts/cs32/endian.html

Quote:

So whats the best way to determine what my memory end point should
be? Count lines in my .lst file?

I think so. I just round it up to the end of the next 16-byte boundary.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 2:12 pm     Reply with quote

Well I have some more reading to do.


And re: setting space for a function. The compiler was nice enough to tell me that I didn't give it enough space and how much more it needed!

Thanks for your help PCMprogrammer. I'm knee deep in that link you sent me.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 3:03 pm     Reply with quote

You know what, I've still got an issue.
Code:

void test(void){
  whatev;
}

void main(void){
  eeprom_write(0x00, &test);
}


I want to write the location of function test() to eeprom location 0x00.
Am I missing something?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 3:24 pm     Reply with quote

stinky wrote:
Am I missing something?
Yes.
CCS Manual wrote:
write_eeprom( )

Syntax: write_eeprom (address, value)

Parameters:
address is a (8 bit or 16 bit depending on the part) int, the range is device dependent
value is an 8 bit int
How many bits is a memory address and how many bits are you writing?
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 4:10 pm     Reply with quote

Up until you asked that I question I thought the answer to both of those questions was 8.


I do still believe that I'm writing 8 bits to EEPROM but perhaps my assumption on address length is incorrect.

So in the memory map I see addresses listed in 4 byte sections implying a maximum 16 bit value there. And table 1-1 lists the program flash as 2k x 14 so perhaps the correct answer is that I'm trying to write a 14 bit address into an 8 bit location.

Where I come from we refer to that as "too much junk in the trunk"
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 4:18 pm     Reply with quote

Here's an example. I couldn't get it to work with function return values,
so I gave up on that part, but at least it calls the function OK:
Code:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

#include "internal_eeprom.c"

void test(void)
{
putc('A');
}

// Typedef a function pointer.
typedef int8 (*_fptr)(void);


//==========================================

void main()
{
_fptr my_fptr, new_fptr;

my_fptr = test;   // Set function ptr to address of test()

printf("fptr = %lx\r", my_fptr);  // Display function ptr

write_int16_eeprom(0, my_fptr);   // Write it to eeprom

new_fptr = read_int16_eeprom(0);  // Read it back from eeprom

printf("new_fptr = %lx\r", new_fptr);  // Display value read

*new_fptr();  // Call it

while(1);
}
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 5:50 pm     Reply with quote

Aha!


And due to the functions inside internal_eeprom.c it will split my 16 bit integer into two 8 bit integers and write one into the eeprom address I specify, and then it will write one into the eeprom address one location greater than the first....yes?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 11, 2012 6:01 pm     Reply with quote

Yes.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Tue Jun 12, 2012 8:54 am     Reply with quote

OK I think I might be running into a syntax issue with CCS V 4.132.
The compiler doesn't like the following:

Code:

void test(void);
int16 *testPtr = &test;

if(testPtr == &test)
{
  ;
}

This produces an error of "Expecting a ( "
But it's ok if I do the following:
Code:

void test(void);
int16 *testPtr = &test;
int16 *retestPtr = &test;

if(testPtr == retestPtr)
{
  ;
}

Has anyone had any experience with this?
Ttelmah



Joined: 11 Mar 2010
Posts: 19329

View user's profile Send private message

PostPosted: Tue Jun 12, 2012 1:33 pm     Reply with quote

There are several syntax errors, and problems in what you post:

1)
void test(void);

This has now declared a function called 'test' that does nothing. No '{' to show the function code follows...

2)
int16 *testPtr=&test;

First problem here is that the compiler never likes initialising variables with anything except constants. This is listed as a limitation in the manual. You have to declare the variable, then initialise it separately.

3) Your pointer declaration, is wrong. The C syntax for a function pointer, to a function accepting and returning a void, is:

void (*testPtr)(void);

You are declaring a pointer to an int16.

4) Remember that in the PIC, the RAM, is not the same memory space as the ROM. '&' attempts to return the address of a RAM variable. The name of the function, _is_ it's address, with no '&' needed.

5) However you can't use a function name in a direct comparison, the compiler only supports the name as the source of an assignment.
So:
Code:

void test(void) {
   void (*testPtr)(void);
   void (*TP2)(void);
   testPtr=test;
   TP2=test;

   if(testPtr == TP2) {
      ;
   }
}


You have to be 'squeaky clean' when working with function pointers, particularly because of the twin memory spaces in the PIC.

As a 'comment', beware of storing the function address in the EEPROM. What happens to the code, if the write does not complete both bytes?.
Why not just declare an array of function pointers, initialise these at boot, and just store the array index?.

Best Wishes
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