Jump to content

Recommended Posts

I'm curious why the EEPROM functions use a char for the eeprom address. Doesn't this limit the parameter to a maximum value of 127? Perhaps I don't understand how to use these fns in the first place. If I init some eeprom data using #pragma DATA _EEPROM followed by 250 bytes of data, how do I then access that data using eeprom_read(char addr) in my code? Would it be faster just to use the hardware eeprom registers with unsigned char address? I don't have a lot of experience using EEPROM except when declared in my code using rom storage specifier such as rom char* dummy = "Some string data";

 

Can anybody point me to some good examples?

 

Thanks,

Henry (lost in eeprom) :huh:

Link to post
Share on other sites

Hi Henry,

 

Looking at the eeprom.h file

 

	unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );

 

it shows the address as an unsigned char therefore giving a max address of 255.

 

Using the functions are shown in the manual and are straight forward.

 

For simple stuff like reading/writing eeprom I always do my own thing, that way I can read/write blocks and have it all interrupt driven.

 

Cheers

 

Reynard

Link to post
Share on other sites
Hi Henry,

 

Looking at the eeprom.h file

 

	unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );

 

it shows the address as an unsigned char therefore giving a max address of 255.

 

Using the functions are shown in the manual and are straight forward.

 

For simple stuff like reading/writing eeprom I always do my own thing, that way I can read/write blocks and have it all interrupt driven.

 

Cheers

 

Reynard

Actually the newest version of eeprom.h and presumably the lib is using an unsigned short for the address if using a PIC18. Partly my fault for not paying attention to an upgrade a few days before my post. It looks like you have an old version, too. The version I was using (I _thought_ it was 6.96) indicated char in both the manual and header for the address. That's what through me off. The new PIC18 version won't work either for the part I'm using (a PIC18 which has 256 bytes of EEPROM) but I think this is already on the bug list (I wish that list was published -hint, hint).

 

The manual now has an example (it didn't used to have one) which makes it more strightforward and to understand the addressing scheme. The hardware uses 12 and 21 bit addressing (I think?) for the rest of ROM, which only added to my confusion. In any case, the current PIC18 eeprom lib won't work but I have already written my own. The functions are quite simple - they're already written for you in the data sheet - except for the fact that it is different for each PIC18 part. :huh: That will just make the developer's job more fun! Just what they needed...

 

Regards,

H.

Link to post
Share on other sites

Here is an idea. Make use of BoostC overloading capabilities and add eeprom functions that deal with 16 bit addresses. Something like:

 

char eeprom_read(char address);

char eeprom_read(unsigned short address);

 

void eeprom_write(char address, char data);

void eeprom_write(unsigned short address, char data);

 

If that's what you want we'll add these functions to the next SourceBoost release.

 

Regards,

Pavel

Link to post
Share on other sites

Hi Henry,

 

You have to keep up with the fast changing face of BoostC.

 

I do have the latest version but the code snippet I used was from the PIC16 section as you did not specify the PIC number you are using.

 

Unless it is something complex like USB I always write my own libraries. That way they do what I want and I know exactly what makes them tick. If they don't work then I know who to blame.

 

Cheers

 

Reynard

Link to post
Share on other sites
Here is an idea. Make use of BoostC overloading capabilities and add eeprom functions that deal with 16 bit addresses. Something like:

 

char eeprom_read(char address);

char eeprom_read(unsigned short address);

 

void eeprom_write(char address, char data);

void eeprom_write(unsigned short address, char data);

 

If that's what you want we'll add these functions to the next SourceBoost release.

 

Regards,

Pavel

 

OK latest SourceBoost already supports 16 bit eeprom addresses for PIC18. Seems that nothing needs to get changed after all.

 

Regards,

Pavel

Link to post
Share on other sites

Pavel,

 

See my post "eeprom.pic18.lib broken in V6.96" in Bug Reports.

 

As you say, 16 bit eeprom addresses for PIC18 parts are supported in V6.96 with the eeprom library. The caveat here is that it will only work for those PIC18 parts that have more than 256 bytes of eeprom. This is because the hi byte of the eeprom address, eeadrh, does not exist in PIC18 parts that only have 256 bytes . If the current eeprom library is used for these then it will not link.

 

Regards

 

davidb

Link to post
Share on other sites
...As you say, 16 bit eeprom addresses for PIC18 parts are supported in V6.96 with the eeprom library. The caveat here is that it will only work for those PIC18 parts that have more than 256 bytes of eeprom. This is because the hi byte of the eeprom address, eeadrh, does not exist in PIC18 parts that only have 256 bytes . If the current eeprom library is used for these then it will not link...

 

OK I see now. Than eeprom functions should look more like:

 

#ifdef _PIC16
unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );
#elif _PIC18
unsigned char eeprom_read( unsigned char address );
unsigned char eeprom_read( unsigned short address );
void eeprom_write( unsigned char address, unsigned char data );
void eeprom_write( unsigned short address, unsigned char data );
#else
#error "unsupported target"
#endif

 

Regards,

Pavel

Link to post
Share on other sites

Pavel,

 

I see where you are going with function overloading but I think you still have a problem and need to determine when eeadrh is required otherwise how do you determine when to use a short or char? As it stands eeprom.c needs re-writing.

 

If PIC18F address is always a short then this will be converted to char when you write to eeadr.

 

It might simplify matters if you could define eeadr or probably a different variable name (to avoid conflicts) as a short (EEADR + EEADRH) wherever EEADRH exists. This would need to be done in each PIC18F header file.

 

I haven't checked all the PIC18F parts but I assume that where EEADRH is used it is contiguous and in the right order with EEADR!

 

Regards

 

davidb

Link to post
Share on other sites
Pavel,

 

I see where you are going with function overloading but I think you still have a problem and need to determine when eeadrh is required otherwise how do you determine when to use a short or char? As it stands eeprom.c needs re-writing.

 

If PIC18F address is always a short then this will be converted to char when you write to eeadr.

 

It might simplify matters if you could define eeadr or probably a different variable name (to avoid conflicts) as a short (EEADR + EEADRH) wherever EEADRH exists. This would need to be done in each PIC18F header file.

 

I haven't checked all the PIC18F parts but I assume that where EEADRH is used it is contiguous and in the right order with EEADR!

 

Regards

 

davidb

davidb, why won't the size of the address param that you use determine when eeadrh is required? For example, if you have a PIC18 with > 256 bytes of eeprom, you would always use a short for the address, and if your part has <= 256 you would always us a uchar. The compiler would then link the appropriate fn.

 

And wouldn't the proposed overloading idea also eliminate your concern about whether EEADRH and EEADR are contiguous and in the right order? As long as you stick to the convention of keeping EEADRH in the high order bits of the unsigned short parameter then it will always work.

 

The only problem I see is if you try to use a ushort for the address on a device with only 256 bytes of eeprom. This would be common if, for example, you needed that variable to be 16 bits for other purposes such as a math procedure or maybe it also needs to be a pointer to RAM but you don't know which until runtime. You would then always have to remember to do an explicit cast. Regardless of this it still seems like the best solution.

 

Let me know if you think I'm missing something. Regards,

-Henry

Link to post
Share on other sites
snip...

Unless it is something complex like USB I always write my own libraries. That way they do what I want and I know exactly what makes them tick. If they don't work then I know who to blame.

 

Cheers

 

Reynard

I'm often tempted by this as well, but it generally makes for buggier code. If you use the eeprom lib that ship with the compiler, it's likely that many other people are already using it and found the more esoteric bugs that may take years to pop up in your own code, even when it seems relatively simple.

 

Thanks for your help,

Henry

Link to post
Share on other sites

Henry,

 

All I was trying to say was that I don't think Pavels proposal can work without some re-write as currently eeadr is defined as a char in the PIC18F header files.

This will work With a PIC16F or a PIC18F with 256 bytes of eeprom but with a PIC18F with >256 bytes the short will be converted to a char i.e. eeadrh will not be updated.

 

To make it work both eeprom.c and eeprom.h and possibly the appropriate PIC18F header files need to be re-written.

 

Perhaps I am missing something simple.

 

Regards

 

davidb

Link to post
Share on other sites

Here is the improved header that takes into account existance of EEADRH register (for those who haven't followed this post from the beginning: don't rush and edit the eeprom header file. This is just a proposal for the current eeprom library that targets next SourceBoost release):

 

#ifdef _PIC16
unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );
#elif _PIC18
unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );
#ifdef EEADRH
	unsigned char eeprom_read( unsigned short address );
	void eeprom_write( unsigned short address, unsigned char data );
#endif
#else
#error "unsupported target"
#endif

 

Regards,

Pavel

Link to post
Share on other sites

Pavel,

why wouldn't you do it like this which would prevent somebody from accidentally linking in both overrides and then writing code that would crash? A real possibility if they were porting some code from a 256 byte rom device to a part with > 256.

#ifdef _PIC16
unsigned char eeprom_read( unsigned char address );
void eeprom_write( unsigned char address, unsigned char data );
#elif _PIC18
#ifdef EEADRH
	unsigned char eeprom_read( unsigned short address );
	void eeprom_write( unsigned short address, unsigned char data );
#else
	unsigned char eeprom_read( unsigned char address );
	void eeprom_write( unsigned char address, unsigned char data );
#endif
#else
#error "unsupported target"
#endif

Actually now that I think about it, your version would be more portable to newer devices with more rom because you could put the same directive in the function defs with the uchar addresses like this:

// eeprom.c
unsigned char eeprom_read( unsigned char address )
{
// if they only passed a unsigned char, but this part has > 256 bytes rom, 
// assume hi order bits are 0
#ifdef EEADRH
eeadrh = 0;
#endif
eeadr = address;
...
}

Of course I haven't tested this...

 

Best,

Henry

Link to post
Share on other sites
All I was trying to say was that I don't think Pavels proposal can work without some re-write as currently eeadr is defined as a char in the PIC18F header files.

Do you mean the argument called "address" or the register eeadr? The latter will always be a char. That won't change in the re-write. The assignment isn't made until inside the body of the fn.

This will work With a PIC16F or a PIC18F with 256 bytes of eeprom but with a PIC18F with >256 bytes the short will be converted to a char i.e. eeadrh will not be updated.

The short won't ever be converted to anything else. The hi order bits will be assigned to eeadrh and the low order bits assigned to eeadr or eeadrl.

 

I hope this clarifies :huh:

Henry

Link to post
Share on other sites

Henry,

 

The facts:

 

1. eeadr (eeadrl) is always defined as a char in all the PIC header files that have eeprom of any size.

2. eeadrh is only defined as a char in PIC header files that have more than 256 bytes of eeprom.

3. The current build of the eeprom lib will not work with PIC18Fs with only 256 byte eeprom because eeadrh is NOT defined for these parts.

4. The curent eeprom.c and eeprom.h need to be modified in some way - The clunky way would be to put a conditional in eeprom.c to only use eeadrh for every PIC18F that has only >256 byte eeprom (or the inverse of this). This would be long winded and would probably need regular updating as Microchip launch even more parts.

 

The short won't ever be converted to anything else. The hi order bits will be assigned to eeadrh and the low order bits assigned to eeadr or eeadrl.

 

Correct me if I am wrong, but what you seem to be implying is that if eeadr & eeadrh are in consecutive hardware registers in lo/hi byte order (as they probably are) then writing a short to just eeadr will also write the high byte of the short to eeadrh. Surely, this cannot be correct as shorts should always be converted (truncated). Writing a short to any char will only write the lo byte to the char and the top byte will be lost.

 

However, if you defined eeadr (or a mirror of it to avoid confusion) as a short then writing a short to just eeadr should update both eeadr and eeadrh correctly.

 

If you are correct in your assumptions then I am going back to asm!

 

Regards

 

davidb

Link to post
Share on other sites
1. eeadr (eeadrl) is always defined as a char in all the PIC header files that have eeprom of any size.

Correct

2. eeadrh is only defined as a char in PIC header files that have more than 256 bytes of eeprom.

Correct

3. The current build of the eeprom lib will not work with PIC18Fs with only 256 byte eeprom because eeadrh is NOT defined for these parts.

Wrong. EEprom library was built for a general PIC18 device that has eeadrh register. It will try to write into this register regardless if the concrete PIC18 you use does or doesn't have this register. This will have no side-effect if this location isn't used in hardware.

4. The curent eeprom.c and eeprom.h need to be modified in some way - The clunky way would be to put a conditional in eeprom.c to only use eeadrh for every PIC18F that has only >256 byte eeprom (or the inverse of this). This would be long winded and would probably need regular updating as Microchip launch even more parts.

Correct. The changes I just made include an updated header (just like in my post above) and sources that don't use eeadrh in functions that use char address and do use eeadrh in functions that use short address.

 

Regards,

Pavel

Link to post
Share on other sites

Pavel,

 

Wrong. EEprom library was built for a general PIC18 device that has eeadrh register. It will try to write into this register regardless if the concrete PIC18 you use does or doesn't have this register. This will have no side-effect if this location isn't used in hardware.

 

You say there is no side effect to using a PIC18F with only 256 byte eeprom but it no longer links for a PIC18F4520 with SB V6.96 whereas it used to on the RC version.

 

The following simple example shows the problem:

 

#include <system.h>
#include <eeprom.h>

// Target PIC18F4520

void main()
{
unsigned char temp = 0x0f;
unsigned char addr = 0xff;

while(1)
{
	eeprom_write(addr, temp);

	temp = eeprom_read(addr);
}
}

 

This compiles OK but produces the following when trying to link:

 

Building...

BoostLink Optimizing Linker Version 6.96

http://www.sourceboost.com

Copyright© 2004-2009 Pavel Baranov

Copyright© 2004-2009 David Hobday

 

failure

"C:\Program Files\SourceBoost\boostlink_pic.exe" /ld "C:\Program Files\SourceBoost\lib" libc.pic18.lib test.obj "..\..\Program Files\SourceBoost\Lib\eeprom.pic18.lib" /t PIC18F4520 /d C:\SW_IN_PROGRESS\TEST /p test

Exit code was -2.

Removing target: test.hex

Error: Failed to resolve external:eeadrh

Error: Failed to resolve external:eeadrh

Failed to locate output file 'C:\SW_IN_PROGRESS\TEST\test.hex'

Done

 

Failed

 

Notice that it failed because eeadrh could not be resolved because it is not defined in PIC18F4520.h

 

I resolved the problem in my project by not using the library but could you let us know what you have changed in eeprom.c to resolve this matter with eeadrh.

 

Regards

 

davidb

Link to post
Share on other sites

Pavel,

 

I missed your last post with the improved header to take account of EEADRH so ignore my last post on request for information.

 

For my own sanity I have modified local copies of eeprom.h & eeprom.c and at least proved that it will compile for targets with different eeprom sizes.

 

Regards

 

davidb

Link to post
Share on other sites
...I missed your last post with the improved header to take account of EEADRH so ignore my last post on request for information...

 

Your comments are valid. My current thinking is to provide 2 eeprom lib files for PIC18: one that will include functions that use char address and another that included both char and short addressing and uses eeaddrh register. They both will use the same header (the one that I poster earlier in this thread).

 

Regards,

Pavel

Link to post
Share on other sites
Henry,

 

The facts:

 

1. eeadr (eeadrl) is always defined as a char in all the PIC header files that have eeprom of any size.

2. eeadrh is only defined as a char in PIC header files that have more than 256 bytes of eeprom.

Yes because the register is 8 bits for both of them. When eeadrh is defined, it is always defined as a char because these are 8-bit devices. No?

 

The short won't ever be converted to anything else. The hi order bits will be assigned to eeadrh and the low order bits assigned to eeadr or eeadrl.

 

Correct me if I am wrong, but what you seem to be implying is that if eeadr & eeadrh are in consecutive hardware registers in lo/hi byte order (as they probably are) then writing a short to just eeadr will also write the high byte of the short to eeadrh. Surely, this cannot be correct as shorts should always be converted (truncated). Writing a short to any char will only write the lo byte to the char and the top byte will be lost.

 

However, if you defined eeadr (or a mirror of it to avoid confusion) as a short then writing a short to just eeadr should update both eeadr and eeadrh correctly.

No. It's irrelevent whether eeadr & eeadrh are contiguous in the hardware. I think you are confusing the function parameter with the actual assignment within the function. First you pass a short to the function. Then the function takes the hi order bits of the short and assigns them to eeadrh. Then it takes the low order bits and assigns them to eeadr. Then it returns (OK it might do a couple other tasks). We never cared whether eeadr and eeadrh were in consecutive hdwr registers; we never tried to "write a short to just eeadr"; never had to cast a short to a char (implicitly or explicitly); we never lost any significant bits. Correct me if I'm wrong, but AFAIK these devices only do things 8 bits at a time (mostly!).

 

What I learned that's new, if I understand Pavel correctly, you can assign something to a bogus address or register and it will have no side effect. Are you sure? I would have thought that would crash on the spot.

 

Regards,

Henry

Link to post
Share on other sites

Henry,

 

I think we are getting bogged down by confusion in the detail, probably because I didn't explain myself very well.

 

The overall discussion was about how to overcome the fact that the latest version of the eeprom lib does not work for PIC18F parts with only 256 byte eeprom. This is because not all PIC18F

parts have the hardware register EEADRH aka eeadrh. eeadrh is used in the function for ALL PIC18F variants so any program using the library for a target with only 256 byte eeprom fails to link.

 

The discussion now is how to recognise the two types of PIC18F parts and generate a common library file. Apart from putting conditionals in for each part the only thing we have to recognise

the difference is the definition EEADRH. I might be wrong but I don't think this can be used when generating the eeprom lib file.

 

Regarding the discussion on char and shorts it wasn't about how the current function was meant to work in C, that is understood, but more about how to modify it. I was thinking at register

level to take account of both 8 and 16 bit addresses.

 

Regardless of whether it was a good idea or not I suggested that you could define eeadr or a shadow of it as a short in the header files for all parts that have 16 bit addressing for the

eeprom. e.g. in PIC18F8723 you could define a version of eeadr as follows (eeadr itself can be left defined as a char):

 

volatile short eeadr_16bit	@EEADR;

This therefore defines eeadr_16bit as eeadr & eeadr+1. For consecutive register addressing eeadr+1 happens to be the same as EEADRH aka eeadrh. Therefore if you use eeadr_16bit in place of

eeadr in the function then eeadr and eeadrh will both be updated if a short is written to it.

 

So in place of:

	// Load address
eeadr = address;

#ifdef EEADRH
eeadrh = address >> 8;
#endif

we could simply use:

	// Load address
eeadr_16bit = address;

With devices that only have 256 byte eeprom i.e. no EEADRH writing a char to eeadr_16bit will still update it correctly as will a short which will simply lose the top byte.

This only works if the address eeadr+1 is unused which may or may not be the case.

 

The upshot of this is that eeadrh would no longer be needed in the function so if it was defined or not it wouldn't matter.

The main problem is that a shed full of header files would have to be modified and it is also non standard.

 

I haven't tried this but I do not see why it wouldn't work anyway please ignore my ramblings!

 

Pavel is making proposals on how to overcome the problem for the next version. I agree with his latest thinking of having separate eeprom lib files for the two eeprom variants of PIC18F.

I tried modifying the eeprom source files in the way he suggested previously and when compiled with a project they appeared to work for all variants but generating a common library

from these is a different matter.

 

Regards

 

davidb

Link to post
Share on other sites
Henry,

 

I think we are getting bogged down by confusion in the detail, probably because I didn't explain myself very well.

 

The overall discussion was about how to overcome the fact that the latest version of the eeprom lib does not work for PIC18F parts with only 256 byte eeprom. This is because not all PIC18F

parts have the hardware register EEADRH aka eeadrh. eeadrh is used in the function for ALL PIC18F variants so any program using the library for a target with only 256 byte eeprom fails to link.

 

The discussion now is how to recognise the two types of PIC18F parts and generate a common library file. Apart from putting conditionals in for each part the only thing we have to recognise

the difference is the definition EEADRH. I might be wrong but I don't think this can be used when generating the eeprom lib file.

Why not if it's used in the header file as Pavel is proposing? You can't use it in the .c file as I mistakenly suggested in post 14 because the libs are just that - libs and obviously not re-compiled on our end. The directive that checks for EEADRH ensures that we link in the correct overload of the fn without, like you said, directives for each part.

 

Regarding the discussion on char and shorts it wasn't about how the current function was meant to work in C, that is understood, but more about how to modify it. I was thinking at register

level to take account of both 8 and 16 bit addresses.

 

Regardless of whether it was a good idea or not I suggested that you could define eeadr or a shadow of it as a short in the header files for all parts that have 16 bit addressing for the

eeprom. e.g. in PIC18F8723 you could define a version of eeadr as follows (eeadr itself can be left defined as a char):

 

volatile short eeadr_16bit	@EEADR;

This therefore defines eeadr_16bit as eeadr & eeadr+1. For consecutive register addressing eeadr+1 happens to be the same as EEADRH aka eeadrh. Therefore if you use eeadr_16bit in place of

eeadr in the function then eeadr and eeadrh will both be updated if a short is written to it.

 

So in place of:

	// Load address
eeadr = address;

#ifdef EEADRH
eeadrh = address >> 8;
#endif

we could simply use:

	// Load address
eeadr_16bit = address;

With devices that only have 256 byte eeprom i.e. no EEADRH writing a char to eeadr_16bit will still update it correctly as will a short which will simply lose the top byte.

This only works if the address eeadr+1 is unused which may or may not be the case.

 

There are several problems with this. First, I don't think you can update two registers at once like you are proposing due to hardware limitations. Correct me if I'm wrong - I hope I am because it would be a nice feature if we could do it! In other words,

	// Load address
eeadr_16bit = address;

cannot work on any PIC18 device because you can (generally) only write to one register at a time. Reading the datasheet would appear to confirm this. Again, let me know if I'm wrong. Also, the c code to be replaced has no directives as you show above. There would be 2 separate functions that both use the same name but different parameters. OK, they would each have different names in the lib due to name mangling but that would be invisible to you as the user. The linker would automatically link in the correct fn.

 

Another problem is it would require the assumption that EEADRH and EEADR would have to be contiguous as you pointed out. I don't think Microchip has ever implied that this would be guaranteed even if it's usually true.

 

Also most of us struggle at one time or another with a shortage of RAM and/or program ROM. With Pavel's proposal your existing code (on a < 256 byte ROM part) would compile and link with less overhead than if we were always forced to link in a version that was loading a short on the stack instead of a char (for the fn call) as well as making a 16 bit assignment in the lib instead of only char.

 

And as you mentioned, it assumes eeadr+1 is unused. Pavel seems unconcerned about writing to unused addresses but I'm still shy about it, and his lack of concern may be due to eeadrh not being defined as eeadr+1.

 

The upshot of this is that eeadrh would no longer be needed in the function so if it was defined or not it wouldn't matter.

The main problem is that a shed full of header files would have to be modified and it is also non standard.

 

I haven't tried this but I do not see why it wouldn't work anyway please ignore my ramblings!

 

Pavel is making proposals on how to overcome the problem for the next version. I agree with his latest thinking of having separate eeprom lib files for the two eeprom variants of PIC18F.

I tried modifying the eeprom source files in the way he suggested previously and when compiled with a project they appeared to work for all variants but generating a common library

from these is a different matter.

 

Regards

 

davidb

I'm not sure why function overloading would require two lib files but I don't write compilers... It seems to me that name mangling would take care of the problem and only the correct function would end up being linked into our file from the lib that contained the two overloads of each function. No?

 

Regards,

Henry

Link to post
Share on other sites
And as you mentioned, it assumes eeadr+1 is unused. Pavel seems unconcerned about writing to unused addresses but I'm still shy about it, and his lack of concern may be due to eeadrh not being defined as eeadr+1.

 

PIC hardware lets you write to and read from unimplemented registers. Write does nothing and read produces a zero result. So as I see it code that operates on unimplemented registers won't be useful but at the same time won't do any harm either.

 

I'm not sure why function overloading would require two lib files but I don't write compilers... It seems to me that name mangling would take care of the problem and only the correct function would end up being linked into our file from the lib that contained the two overloads of each function. No?

This doen't do anything with overloading. If we want to produce minimal code for functions that read or write eeprom we should use eeadrh for PICs that do have big eeprom and shouldn't use eeadrh for PICs that have short eeprom. From other hand if we have only one library it will contain code that uses eeardh. Now the question is how to disable use of such code for PICs that have short eeprom. The only way we can do it is not let linker use functions that operate on eeadrh register. And we do it by disabling these function prototypes in eeprom header via #ifdef EEARDH preprocessor statement. So it looks that at the end one eeprom library will be enough. And it will indeed for PICs with short eeprom. But for long eprom there is a problem. Users can accidentially call functions that don't use eeardh when working with PICs that have long eeprom and because these functions don't operate on eeadrh they might access wrong eeprom locations. For example:

 

eeprom_read( 10 ); //will call eeprom_read( unsigned char ) and if eeadrh is not zero the code will access other than  addr 10 eeprom location
eeprom_read( (unsigned short)10 ); //will call eeprom_read( unsigned short ) this one will access addr 10

 

This will lead to tricky to find errors. The solution is to produce 2 libraries. One for short eeprom and another for long eeprom. This way all nasty surprises will be eliminated and one won't need to think what eeprom function to pick. Compiler will do this job for you and pick the most appropriate function according to the type of the address used in a call.

 

Regards,

Pavel

Link to post
Share on other sites

Hi Henry,

 

There are several problems with this. First, I don't think you can update two registers at once like you are proposing due to hardware limitations. Correct me if I'm wrong - I hope I am because it would be a nice feature if we could do it! In other words,

	// Load address
eeadr_16bit = address;

cannot work on any PIC18 device because you can (generally) only write to one register at a time. Reading the datasheet would appear to confirm this. Again, let me know if I'm wrong. Also, the c code to be replaced has no directives as you show above.

 

NO, of course it doesn't update two registers at once since the PIC18F is only an 8-bit device. This is the main reason we use high level language; it mostly hides the low level operations required by the processor to carry out what we require, regardless of the processors native data size. If you write a short to a short as above, regardless of whether it is an FSR that has been re-defined as a short or a normal memory location the compiler converts this into writing both lo and hi bytes. Try looking at the code generated by the compiler e.g. the above would be:

		  MOVF main_1_address, W
	  MOVWF main_1_eeadr_16bit
	  MOVF main_1_address+D'1', W
	  MOVWF main_1_eeadr_16bit+D'1'

 

The fact that the two registers are not actually written to simultaneously can sometimes be a problem, particularly with timers A-D etc but that's another story.

 

Regarding your other comments Pavel has mostly covered these.

 

Regards

 

davidb

Link to post
Share on other sites
This doen't do anything with overloading. If we want to produce minimal code for functions that read or write eeprom we should use eeadrh for PICs that do have big eeprom and shouldn't use eeadrh for PICs that have short eeprom. From other hand if we have only one library it will contain code that uses eeardh. Now the question is how to disable use of such code for PICs that have short eeprom. The only way we can do it is not let linker use functions that operate on eeadrh register. And we do it by disabling these function prototypes in eeprom header via #ifdef EEARDH preprocessor statement. So it looks that at the end one eeprom library will be enough. And it will indeed for PICs with short eeprom. But for long eprom there is a problem. Users can accidentially call functions that don't use eeardh when working with PICs that have long eeprom and because these functions don't operate on eeadrh they might access wrong eeprom locations. For example:

That is the problem I was referring to in post 14 when I said: "Pavel, why wouldn't you do it like this which would prevent somebody from accidentally linking in both overrides and then writing code that would crash? A real possibility if they were porting some code from a 256 byte rom device to a part with > 256."

 

The solution in my post would solve that problem and also David's concerns but wouldn't allow for a reduced overhead version on the long EE parts. Hence the reason for two libs. I'm glad it's worth your time :)

 

Thanks,

Henry

Link to post
Share on other sites

Hi davidb,

 

I'm aware of the 4 asm instructions that get generated when you assign a 16-bit value in RAM. It doesn't work with all the SFRs, perhaps because they're not always contiguous or special buffering etc but I think you're right it would probably work with these. Where I'm still confused is why you don't want to write a byte to each register (or only one if EEADRH is not defined) instead of always writing 16 bits to two consecutive addresses and the associated problems with that. Or why you thought the directive testing for EEADRH in the header with a new lib would result in a short being truncated using Pavel's proposal? Your post suggests that I must have misunderstood you somewhere along the way, or vice-versa. You seem plenty knowledgable so I apologize if missed something. We're satisfied with Pavel's proposal so perhaps we should move on to more important things...

 

Regards,

Henry

Link to post
Share on other sites

Hi Henry,

 

I'm aware of the 4 asm instructions that get generated when you assign a 16-bit value in RAM. It doesn't work with all the SFRs, perhaps because they're not always contiguous or special buffering etc but I think you're right it would probably work with these.

Correct, It doesn't normally work for SFR's as they are normally defined as char that is why I suggested a re-defined shadow of eeaddr as a short.

 

We're satisfied with Pavel's proposal so perhaps we should move on to more important things...

I agree, we have probably wasted enough time on this particular subject.

 

Regards

 

davidb

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...