Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Data table storage inside flash memory

Status
Not open for further replies.
Jay.slovak said:
How about passing a parameter from Interrupt (remember this will not act as RETFIE, as GIE is not being enabled automatically) or other Sub-routine?

EDIT: That interupt passing thingy is kind of useless :lol:

Oh yeah I think it will contribute under certain circumstances.This solution is also implemented in other microcontroller families.

eblc1388 said:
Nothing ?

Be careful when your table is larger than one page(256 bytes), not starting on a page boundary, larger than 512 bytes...etc..

It is getting messy with the correct PCL and PCLATH. Microchip AN556 is the document about what to watch out for with table read.

:roll: Don't worry,my friend.I can handle that.I will consider all related registers that have something to do with the boundaries.Actually there is a section describing such circumstances in detail in my text book.I may use it as a reference.


Nigel Goodwin said:
Yes, that's what I meant, the Harvard architecture of the PIC keeps data and program completely seperate - which makes tables rather difficult, the RETLW instruction can be used to provide a program structure that contains data.

But the RETLW structure is perfectly capable of doing what you require, if you have a look at **broken link removed** then they use RETLW to store large amounts of data to generate maps on a graphic LCD.

As already suggested, you have to take account of the 256 byte boundary problems, but the EPE code does just that (using almost all the program space for data).

Hm....I wouldn't agree with what you said about how difficult it is to manage data table in program memory for Harvard architectured processors.Actually when we talk about tables within a microcontroller,we ARE talking about data stored inside program memory.Besides MCS-51 and AVR microcontrollers are also Harvard architecture based microcontrollers.They both deal with tables well,through a certian instructions(MOVC A,@A+DPTR for 8051&LPM for AVR).As Jay said,PIC18 has similar and even more powerful instructions,too-"TLRD t,f" and "TLWT t,f".For some reason this instruction is not implemented on all PIC chips.But it doesn't mean it can't be done.Presumably it's what makes PIC special,that makes PIC the real RISC microcontrollers.

Anyway I'm happy with the DT directive.It will make generating RETLW tables a lot easier.With this directive I don't feel too sorry about instructions like TLRD when I use 16F and there isn't any. :)

BTW,I tried opening the FTP,but each time I hit enter the IE freezes.Is there an http link for the info?Thanks!

Regards,Alex.[/quote]
 
Pommie said:
I don't understand why people are trying to make this sound complicated. As you originally posted, store your data as DB, DW, DATA, whichever gets it in a way you need it and then just read it back via the flash read registers.

Mike.

Oh yes,now it does sound complicated. :roll: And we were just trying to figure out different ways of doing a same thing.

The two solutions are concluded as below:

A:

Code:
	ORG	0x00
	.
	.
	.
	MOVLW	HIGH(Table)
	MOVWF	PCLATH
	MOVLW	Index
	CALL	Table
	.
	.
	.
	ORG	0x820
Table
	ADDWF	PCL
	RETLW	'A'
	RETLW	'3'
	RETLW	0xF7
	RETLW	'G'
	RETLW	'x'
	RETLW	'8'
	.
	.
	.

B:
Code:
Table	DW 0x3FE,0xE2,0x2CA,0x55,........
	.
	.
	.
Get_data
	BSF	STATUS,RP1
	BCF	STATUS,RP0
	MOVF	ADDRL,W
	MOVWF	EEADR
	BSF	STATUS,RP0
	BSF	EECON1,EEPGD
	BSF	EECON1,RD
	NOP
	NOP
	BCF	STATUS,RP0
	MOVF	EEDATA,W
	MOVWF	DATAL
	MOVF	EEDATH
	MOVWF	DATAH

Of course I have to watch out for memory boundaries whenever neccessary.Is that right?

Regards,Alex.
 
Nigel Goodwin said:
Alex_rcpilot said:
BTW,I tried opening the FTP,but each time I hit enter the IE freezes.Is there an http link for the info?Thanks!

You can go to http://www.epemag.wimborne.co.uk, click on Download, from there select PICS, then look for WorldClock - I can't post the exact link because it doesn't update the URL.

oops!Guess it's the url that freezed my IE.I went to the exact location and clicked on World Clock,and then the window froze :shock:

Thank you all the same,Nigel.You've been very helpful.Now I need to donwload the application note which Jay has mentioned.I'm sure I can dig up something useful from there too. :)

Regards,Alex.
 
Alex_rcpilot said:
You can go to http://www.epemag.wimborne.co.uk, click on Download, from there select PICS, then look for WorldClock - I can't post the exact link because it doesn't update the URL.

oops!Guess it's the url that freezed my IE.I went to the exact location and clicked on World Clock,and then the window froze :shock:
[/quote]

PM me your email address, and I'll send you the file!.
 
Alex_rcpilot said:
Of course I have to watch out for memory boundaries whenever neccessary.Is that right?

Regards,Alex.

You don't have to watch out for page boundaries. They get taken care of in the way you increment a 16 byte pointer.

The code you posted above doesn't write the high byte of the address. It should read.
Code:
        BSF    STATUS, RP1   ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   ADDRL, W      ;Write the
        MOVWF  EEADR         ;address bytes
        MOVF   ADDRH,W       ;for the desired  <---------
        MOVWF  EEADRH        ;address to read  <---------
        BSF    STATUS, RP0   ;Bank 3
        BSF    EECON1, EEPGD ;Point to Program memory
        BSF    EECON1, RD    ;Start read operation
        NOP                  ;Required two NOPs
        NOP                  ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   EEDATA, W     ;DATAL = EEDATA
        MOVWF  DATAL         ;
        MOVF   EEDATH,W      ;DATAH = EEDATH
        MOVWF  DATAH         ;


Of course, once the first byte is read then subsequent bytes can just increment the address pointer.

A more elegant approach, would be to initialise the address first and then have a routine which post increments the address after reading each byte.

Code:
INIT    BSF    STATUS, RP1   ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   Low(Table)    ;Write the
        MOVWF  EEADR         ;address bytes
        MOVF   High(Table)   ;for the desired
        MOVWF  EEADRH        ;address to read
        BCF    STATUS, RP0   ;Bank 2
        BCF    STATUS, RP1   ;Bank 0
        RETURN


FETCH   BSF    STATUS, RP1   ;
        BSF    STATUS, RP0   ;Bank 3
        BSF    EECON1, EEPGD ;Point to Program memory
        BSF    EECON1, RD    ;Start read operation
        NOP                  ;Required two NOPs
        NOP                  ;
        BCF    STATUS, RP0   ;Bank 2
        INCFSZ EEADR,F       ;inc address
        DEC    EEADRH,F      ;dec high if not crossed page boundary.
        INC    EEADRH,F      ;inc high byte
        BCF    STATUS, RP1   ;Bank 0
        RETURN               ;

Table   data   1234,"a"

HTH

Mike.
 
The next thing I would like to know is how people usually get data from these data tables.What I'm trying to do is simple : store multiple tables in the flash memory,and write a subroutine to read any of these tables.And I just need to tell the subroutine the starting address of target table & the index to get the right data byte.

I reviewed some of the PIC16F877 code I had done a long time ago and here's how I had done it. The address of the table is loaded to two consecutive locations PROG_ADD and PROG_ADD+1. The data read is stored in two loactions TEMP1 and TEMP2.

Code:
PROG_READ:
         BANKISEL PROG_ADD
         MOVLW    PROG_ADD
         MOVWF    FSR
;
         MOVF     INDF,W          ; PROG_ADD
         BSF      STATUS,RP1      ; BANK 0 -> BANK 2
         MOVWF    EEADR
;
         INCF     FSR,F
         MOVF     INDF,W          ; PROG_ADD+1
         MOVWF    EEADRH
;
         BSF      STATUS,RP0      ; BANK 2 -> BANK 3
         BSF      EECON1,EEPGD    ; Point to program memory
         BSF      EECON1,RD       ; GO Read!
         NOP                      ; 2 NOPs needed
         NOP                      ; by PROG_READ
         BCF      STATUS,RP0      ; BANK 3 -> BANK 2
         MOVF     EEDATA,W
         BCF      STATUS,RP1      ; BANK 2 -> BANK 0
         MOVWF    TEMP1
;
         MOVLW    LOW EEDATH
         BANKISEL EEDATH
         MOVWF    FSR
         MOVF     INDF,W
         ANDLW    3Fh
         MOVWF    TEMP2
;
         RETURN

Using the full 14-bits can be quite handy if you are storing a lot of data. It will be worth the extra programming. Using the FSR and INDF registers should be familiar to 8051 assembly programmers.

BTW, I also checked some of my code and DW works just as well as the DATA directive.
 
Pommie said:
Alex_rcpilot said:
Of course I have to watch out for memory boundaries whenever neccessary.Is that right?

Regards,Alex.

You don't have to watch out for page boundaries. They get taken care of in the way you increment a 16 byte pointer.

The code you posted above doesn't write the high byte of the address. It should read.
Code:
        BSF    STATUS, RP1   ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   ADDRL, W      ;Write the
        MOVWF  EEADR         ;address bytes
        MOVF   ADDRH,W       ;for the desired  <---------
        MOVWF  EEADRH        ;address to read  <---------
        BSF    STATUS, RP0   ;Bank 3
        BSF    EECON1, EEPGD ;Point to Program memory
        BSF    EECON1, RD    ;Start read operation
        NOP                  ;Required two NOPs
        NOP                  ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   EEDATA, W     ;DATAL = EEDATA
        MOVWF  DATAL         ;
        MOVF   EEDATH,W      ;DATAH = EEDATH
        MOVWF  DATAH         ;


Of course, once the first byte is read then subsequent bytes can just increment the address pointer.

A more elegant approach, would be to initialise the address first and then have a routine which post increments the address after reading each byte.

Code:
INIT    BSF    STATUS, RP1   ;
        BCF    STATUS, RP0   ;Bank 2
        MOVF   Low(Table)    ;Write the
        MOVWF  EEADR         ;address bytes
        MOVF   High(Table)   ;for the desired
        MOVWF  EEADRH        ;address to read
        BCF    STATUS, RP0   ;Bank 2
        BCF    STATUS, RP1   ;Bank 0
        RETURN


FETCH   BSF    STATUS, RP1   ;
        BSF    STATUS, RP0   ;Bank 3
        BSF    EECON1, EEPGD ;Point to Program memory
        BSF    EECON1, RD    ;Start read operation
        NOP                  ;Required two NOPs
        NOP                  ;
        BCF    STATUS, RP0   ;Bank 2
        INCFSZ EEADR,F       ;inc address
        DEC    EEADRH,F      ;dec high if not crossed page boundary.
        INC    EEADRH,F      ;inc high byte
        BCF    STATUS, RP1   ;Bank 0
        RETURN               ;

Table   data   1234,"a"

HTH

Mike.

:) Ha!You're right.The higher addr byte must be taken care of to avoid boundary problems.And it's the addr word that should be incremented.Thank you for the code example!

motion said:
The next thing I would like to know is how people usually get data from these data tables.What I'm trying to do is simple : store multiple tables in the flash memory,and write a subroutine to read any of these tables.And I just need to tell the subroutine the starting address of target table & the index to get the right data byte.

I reviewed some of the PIC16F877 code I had done a long time ago and here's how I had done it. The address of the table is loaded to two consecutive locations PROG_ADD and PROG_ADD+1. The data read is stored in two loactions TEMP1 and TEMP2.

Code:
PROG_READ:
         BANKISEL PROG_ADD
         MOVLW    PROG_ADD
         MOVWF    FSR
;
         MOVF     INDF,W          ; PROG_ADD
         BSF      STATUS,RP1      ; BANK 0 -> BANK 2
         MOVWF    EEADR
;
         INCF     FSR,F
         MOVF     INDF,W          ; PROG_ADD+1
         MOVWF    EEADRH
;
         BSF      STATUS,RP0      ; BANK 2 -> BANK 3
         BSF      EECON1,EEPGD    ; Point to program memory
         BSF      EECON1,RD       ; GO Read!
         NOP                      ; 2 NOPs needed
         NOP                      ; by PROG_READ
         BCF      STATUS,RP0      ; BANK 3 -> BANK 2
         MOVF     EEDATA,W
         BCF      STATUS,RP1      ; BANK 2 -> BANK 0
         MOVWF    TEMP1
;
         MOVLW    LOW EEDATH
         BANKISEL EEDATH
         MOVWF    FSR
         MOVF     INDF,W
         ANDLW    3Fh
         MOVWF    TEMP2
;
         RETURN

Using the full 14-bits can be quite handy if you are storing a lot of data. It will be worth the extra programming. Using the FSR and INDF registers should be familiar to 8051 assembly programmers.

BTW, I also checked some of my code and DW works just as well as the DATA directive.

Thank you motion.The BANKISEL directive is interesting.I just viewed its introduction in MPLAB help file.I better practise a little to get used to it. :) Indirect addressing IS handy.I love it!

Thank you guys.Now I have all the answers required.You've been of great help!

Regards,Alex.
 
I have often used FLASH to store jump tables. There is one big advantage - on the 16F877 you can have a jump table that can point to ANYWHERE in program memory - since the program memory is 14 bits wide.
Admittedy, the code overhead, reading the FLASH and moving the info to the PCLATH and the PCL, might be too much for some applications, but if you are reading the FLASH for some other purpose, such as text strings, then I think it's a good idea. I have also used a similar system to "embed" the address of some executable code in a menu item structure.
Using RETLW for data storage in FLASH is very inefficient in some case - 7 bit ASCII for example can be stored in pairs in a 14 bit word.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top