View previous topic :: View next topic |
Author |
Message |
esko
Joined: 17 Nov 2016 Posts: 12
|
Reading program memory using inline assembler |
Posted: Sun Nov 27, 2016 5:00 pm |
|
|
The MCU is PIC18F25K22
I have some tables in my code and those tables are in program memory.
For example the default settings for the application and the LCD initialization instructions and GUI state engine states - to name a few.
I would like to have a function like this: Code: |
#define PGM_P __ADDRESS__
typedef unsigned int8 uint8_t;
uint8_t ReadProgMem (PGM_P aAdr) {
#asm
<the assembler code goes here>
#endasm
} |
I know how to read the flash using TBLRD and associated SFRs.
What I do not know is:
- Assigning the address to the TBLPTRL, TBLPTRH and TBLPTRU SFRs
- Returning the value from the TABLAT register
In this case the __ADDRESS__ is declared as an 32 bit unsigned integer so the values go directly into the TBLPTR* registers.
I also would like to know whether the rest of the code will get tainted if I manipulate those SFRs. I WILL block interrupts during that operation and I will NOT use the function inside an interrupt.
Are there any other considerations with this - the code protection for example is set up in a way that this is possible. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Nov 27, 2016 5:14 pm |
|
|
obvious question
WHY not use the CCS C functions they provide??
Jay |
|
|
esko
Joined: 17 Nov 2016 Posts: 12
|
|
Posted: Sun Nov 27, 2016 6:00 pm |
|
|
Yes - it IS a VERY obvious question. And it does nothing to help me
I have already tried out the ONLY fucntion I could find for this purpose:
Code: |
_bif void goto_address(__ADDRESS__ address);
_bif __ADDRESS__ label_address(__ADDRESS__ label);
// Program Memory Prototypes:
_bif void read_program_memory(__ADDRESS__ address, unsigned int8* dataptr, unsigned int16 count);
|
Alhough THAT might do what I want to do there is a lot of overhead in it.
Code: |
#define PGM_P __ADDRESS__
typedef unsigned int8 uint8_t;
uint8_t ReadProgMem (PGM_P aAdr) {
uint8_t pbyte;
read_program_memory( aAdr, &pbyte, 1 );
return pbyte;
}
|
I do not want THAT.
Sure someone has made a C function that takes a 32 bit argument and returns a byte. This is all the information I need - how does the compiler pass arguments to funcrtions and how it returns them. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Nov 27, 2016 6:08 pm |
|
|
from the ccs manual..
read_program_eeprom( )
Syntax:
value = read_program_eeprom (address)
Parameters:
address is 16 bits on PCM parts and 32 bits on PCH parts
Returns:
16 bits
Function:
Reads data from the program memory.
Availability:
Only devices that allow reads from program memory.
Requires:
Nothing
Examples:
checksum = 0;
for(i=0;i<8196;i++)
checksum^=read_program_eeprom(i);
printf("Checksum is %2X\r\n",checksum);
Example Files:
None
Also See:
write_program_eeprom(), write_eeprom(), read_eeprom(), Program Eeprom Overview
....
so am I missing 'something' here. This function does return what's in the PICs internal EEPROM...
If you really want assembler, then simply cut a small program using the function and dump the listing! CCS does not 'hide' anything,never has for the past 2 decades that I'm aware of.
Jay |
|
|
esko
Joined: 17 Nov 2016 Posts: 12
|
|
Posted: Sun Nov 27, 2016 6:23 pm |
|
|
Actually ..... You are missing nothing I quess I have to go back to elementary school and learn how to read
There is one glitch though. This one returns a word (not a byte) and probably also wants the address to be aligned on word boundary.
Actually.... I will implement this one and then see what it does |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Nov 27, 2016 7:42 pm |
|
|
If you press F11 while your project is open, The CCS manual 'magically' appears.....
There are 4 different 'read-eeprom' functions, which one you use depends on the PIC you have as well as compiler. Some will return a byte, others a word, etc.
I just randomly PICked one to show you that sometimes reading the manual is kinda useful !!
It's always open when I work,can't remember syntax, or names and no nerves in left ring finger....so lots of typos...
Jay |
|
|
esko
Joined: 17 Nov 2016 Posts: 12
|
|
Posted: Sun Nov 27, 2016 11:04 pm |
|
|
If I press ALT-CTL-F4 I get a new terminal.... out of 7 predefined.
This is a real Old School developing environment - no GUI - just the terminal
Sorry about that.
As I said - I have to do more reading and less editing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Mon Nov 28, 2016 2:17 am |
|
|
Note that the code example in the data sheet also reads a word as well though. The address used to talk to the program memory, is a 'word address', so it is not easy to read on a byte basis.
You actually have to read a word, and then select the upper or lower byte.
To show how to do the assembler, if you did want to go that way:
Code: |
//table read needs to access TBLPTR, TABLAT. Define these
#byte TBLPTRL=getenv("SFR:TBLPTRL")
#byte TBLPTRH=getenv("SFR:TBLPTRH")
#byte TBLPTRU=getenv("SFR:TBLPTRU")
#byte TABLAT=getenv("SFR:TABLAT")
//Up to this point answers your question about how to add register
//definitions for the assembler. These will now work
|
Now the function to read a single _word_ from the program memory, is 'read_program_eeprom'. The 'read_program_memory' function is designed to read a block.
If you look at the code generated for 'read_program_eeprom':
Code: |
.................... value=read_program_eeprom(0x1000);
0016: MOVFF INTCON,@@0B
001A: BCF INTCON.GIEH
001C: CLRF TBLPTRU
001E: MOVLW 10
0020: MOVWF TBLPTRH
0022: CLRF TBLPTRL
0024: TBLRD*+
0026: MOVF TABLAT,W
0028: TBLRD*
002A: MOVFF TABLAT,03
002E: CLRF TBLPTRU
0030: BTFSC @@0B.7
0032: BSF INTCON.GIEH
0034: MOVWF value
0036: MOVFF 03,value+1
|
This is exactly the same as the code in the data sheet to read the program memory. Now much point in going DIY!.... |
|
|
|