MC68HC11 SPI to Serial Flash ASM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC68HC11 SPI to Serial Flash ASM

6,182 Views
mot_monkey
Contributor I
Hello all,
 
I am looking for some ASM code example of MC68HC11 SPI to serial flash. I am thinking of using one of the newer serial flash chips, example: Spansion S25FL008A or maybe a 16MB version.
 
I have not done much work with SPI or serial flash at all so any help would be great. Thank you.
Labels (1)
0 Kudos
6 Replies

724 Views
Wings
Contributor I
OK, here's something that may get you started. It's from a widget that's glued to the back of an albatross and records GPS position as he tools around the Pacific, done many many moons ago. Couple of things I noticed: (1) PORTB,BIT3 is inverted by hardware before it hits the flash chip's CS input so you'll have to invert that logic if you have a direct connection (which you probably will), and (2) the macro BGTASK is simply a rename for an SWI instruction, and for your purposes, my BGTASK is simply a 5ms delay. Oh, also, ignore any references to FLAGS3,FLASH. The init code for the SPI is:

* Enable SPI for master mode, 500KHz clock. CPOL & CPHA
* clear for driving AT45DB041B Flash chip (SPI Mode 0).
LDAA #SPE+MSTR+SPR4 (mnemonics from data sheet)
STAA SPCR
JSR DOSPI KICK START SPI.


****************************************************************
*
* Flash Memory Routines, Atmel AT45DB041B chip.
*
* RDPAGE: Read a page into PG1RAM. Page# in AccD on entry.
* WRPAGE: Write a page from memory at X-reg. Flash page# in AccD on entry.
* FLOPEN: Sends page address in AccD to flash, preps for reading.
* DOSPI: Clocks out/in 1 byte and returns (after FLOPEN called). (byte in AccA)
* FLCLOSE: Disables flash chip.
* VFYFLASH: Entire Flash is tested for ability to write zeros, then erased.
* BF2READ: Reads Buffer#2 into PG1RAM.
* BF2WRIT: Writes Buffer#2 from PG1RAM.

FLOPEN EQU *
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
PSHA
LDA #$E8 OPCODE: CONTINUOUS ARRAY READ.
FLOPEN2 JSR DOSPI SEND OPCODE.
PULA
LSLD
JSR DOSPI SEND PAGE ADDR 1ST HALF.
TBA
JSR DOSPI SEND PAGE ADDR 2ND PART.
CLRA
JSR DOSPI SEND BYTE ADDR (ALWAYS 0).
* CLRA
* JSR DOSPI BYTE ADDR LSB.
JSR DOSPI AND 4 BYTES OF DONTCARES.
JSR DOSPI
JSR DOSPI
JSR DOSPI
RTS

FLCLOSE EQU *
BCLR PORTB,BIT3 CHIP SELECT INACTIVE.
RTS

RDPAGE EQU *
PSHX
BSR FLOPEN SEND PAGE ADDR.
LDX #PG1RAM PTR TO PAGE1RAM.
RDPAGE2 JSR DOSPI CLOCK OUT A BYTE.
STA 0,X AND SAVE IN PAGE1RAM.
INX BUMP PTR.
CPX #PG1RAM+256 READ 1 PAGE?
BLO RDPAGE2 IF NO, KEEP CLOCKING.
BSR FLCLOSE STOP THE READ.
PULX RESTORE X.
RTS DONE.


* Set a flag here while writing into flash. Causes BGTASK to not
* check magnet switch while we're fooling with the flash dude.

WRPAGE EQU * (executes in approx 25-30 msec)
BSET FLAGS3,FLASH SET THE FLASH FLAG FOR BGTASK.
PSHA
LDA #$82 OPCODE: WRITE PAGE THRU BUFFER 1.
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
JSR DOSPI SEND OPCODE.
PULA
LSLD
JSR DOSPI SEND PAGE ADDR 1ST HALF.
TBA
JSR DOSPI SEND PAGE ADDR 2ND PART.
CLRA
JSR DOSPI SEND BYTE ADDR (ALWAYS 0).
* CLRA
* JSR DOSPI BYTE ADDR LSB.
CLRB ZERO BYTE COUNTER.
WRPGLP LDA 0,X GET BYTE TO WRITE.
JSR DOSPI SEND TO FLASH.
INX BUMP PTR.
DECB CHECK COUNT.
BNE WRPGLP LOOP FOR 256.
BCLR PORTB,BIT3 CHIP SEL INACTIVE, WRITE STARTS.

WRPGWT BGTASK ;WAIT 5MS. (magnet switch ignored)
WRPGWT2 BSET PORTB,BIT3 FLASH CS ACTIVE.
LDA #$D7 OPCODE: READ STATUS REG.
JSR DOSPI
JSR DOSPI GET THE STATUS BYTE.
BCLR PORTB,BIT3 FLASH CS INACTIVE.
TSTA
BPL WRPGWT IS BUSY, WAIT 5MS LONGER.
BCLR FLAGS3,FLASH CLEAR THE FLAG SO BGTASK HANDLES MAG SWITCH.
RTS



DOSPI STAA SPDR SHIFT INTO FLASH.
: TST SPSR
BPL :-1 WAIT FOR SPIF SET.
LDAA SPDR RETURN WITH CLOCKED IN DATA.
SPIRTS RTS

*
* Verify Flash memory by writing zeros into every page and
* reading back the results. If no error Flash is then erased
* and returns C=0. If error C=1 on return and X contains
* page number having error (and Flash not erased).
*
VFYFLASH EQU * TEST EVERY PAGE OF FLASH.
LDX #0
VFLOOP LDA #$82 OPCODE: WRITE PAGE THRU BUFFER 1.
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
JSR DOSPI SEND OPCODE.
PSHX
PULD
LSLD
JSR DOSPI SEND PAGE ADDR 1ST HALF.
TBA
JSR DOSPI SEND PAGE ADDR 2ND PART.
CLRA
JSR DOSPI SEND BYTE ADDR (ALWAYS 0).
CLRA
JSR DOSPI BYTE ADDR LSB.
CLRB ZERO BYTE COUNTER.
VFLP2 CLRA BYTE TO WRITE = 0 FOR TEST.
JSR DOSPI SEND TO FLASH.
DECB CHECK COUNT.
BNE VFLP2 LOOP FOR 256.
BCLR PORTB,BIT3 CHIP SEL INACTIVE, WRITE STARTS.
BSR WRPGWT WAIT FOR WRITE TO FINISH.

PSHX
PULD
JSR FLOPEN SEND PAGE ADDR.
CLRB BYTE COUNTER.
VFLP3 JSR DOSPI CLOCK OUT A BYTE.
TSTA COMPARE.
BEQ VFLP4 ERROR IF NOT ZERO.
VFERR JSR FLCLOSE STOP THE READ.
SEC C=1 ON ERROR.
RTS X HAS ERROR PAGE.
VFLP4 DECB CHECK COUNT.
BNE VFLP3 LOOP FOR 256 BYTES.
JSR FLCLOSE
INX INC TO NEXT PAGE.
CPX #2048 DONE ALL PAGES?
BLO VFLOOP LOOP IF NOT.

* NOW ERASE ENTIRE FLASH.
ERASFLSH LDX #0 BLOCK # TO ERASE.
ERASLP LDA #$50 OPCODE: BLOCK ERASE.
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
JSR DOSPI SEND OPCODE.
PSHX
PULD
LSLD
LSLD
LSLD
LSLD
JSR DOSPI SEND BLOCK ADDR 1ST HALF.
TBA
JSR DOSPI SEND BLOCK ADDR 2ND PART.
CLRA
JSR DOSPI SEND DONTCARE BITS.
BCLR PORTB,BIT3 CHIP SEL INACTIVE, ERASING STARTS.
JSR WRPGWT WAIT FOR ERASE TO FINISH.
INX INC TO NEXT BLOCK.
CPX #256 DONE ALL BLOCKS?
BLO ERASLP LOOP IF NOT.
CLC C=0 ON NO ERROR.
RTS ALL DONE.


BF2READ EQU *
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
LDA #$D6 OPCODE: BUFFER #2 READ.
JSR DOSPI SEND OPCODE.
CLRA
JSR DOSPI PAGE ADDR 1ST HALF (DONTCARES).
JSR DOSPI PAGE ADDR 2ND PART (DONTCARES).
JSR DOSPI SEND BYTE ADDR (ALWAYS 0).
JSR DOSPI AND 1 BYTE OF DONTCARES.
LDX #PG1RAM PTR TO PAGE1RAM.
RDBUF2 JSR DOSPI CLOCK OUT A BYTE.
STA 0,X AND SAVE IN PAGE1RAM.
INX BUMP PTR.
CPX #PG1RAM+256 READ 1 PAGE?
BLO RDBUF2 IF NO, KEEP CLOCKING.
BCLR PORTB,BIT3 CHIP SELECT INACTIVE.
RTS DONE.



BF2WRIT EQU * (executes in approx 25-30 msec)
BSET PORTB,BIT3 CHIP SELECT ACTIVE.
LDA #$87 OPCODE: BUFFER #2 WRITE.
JSR DOSPI SEND OPCODE.
CLRA
JSR DOSPI SEND PAGE ADDR 1ST HALF (DONTCARES).
JSR DOSPI SEND PAGE ADDR 2ND PART (DONTCARES).
JSR DOSPI SEND BYTE ADDR (ALWAYS 0).
LDX #PG1RAM WRITE FROM PG1RAM.
WRBF2LP LDA 0,X GET BYTE TO WRITE.
JSR DOSPI SEND TO FLASH.
INX BUMP PTR.
CPX #PG1RAM+256 CHECK END.
BLO WRBF2LP LOOP FOR 256.
BCLR PORTB,BIT3 CHIP SEL INACTIVE.
RTS DONE.


*
* Flash Memory Routines, Atmel AT45DB041B chip.
*
*** END *************************************************************
0 Kudos

724 Views
Wings
Contributor I
Wow, that looks awful. Looked OK when I pasted it but in the forum it's lost all the tabs. mmmmm.... any suggestions?
0 Kudos

724 Views
mot_monkey
Contributor I
Wings/all thanks for the info. Will have to do some playing this end :smileyvery-happy:
0 Kudos

724 Views
Alban
Senior Contributor II

Hi Wings,
You can include an attachement.
So you could just attach a .asm to your post.
Cheers,
Alban.

0 Kudos

724 Views
peg
Senior Contributor IV

Hi,

Can I ask why new flash, old CPU?

I'm not helping but this will push your question back to the top!!!

BR Peg

 

0 Kudos

724 Views
mot_monkey
Contributor I

Peg,

Been using the 68hc11 for a long time now, this is true. At this point in time don't have the time to switch, unless there is a quick solution. Do you think my plan is a bad idea? Is there a newer chip that would accept existing code without huge translation effort? I use all of the various features offered by the 68hc11 to date except the SPI and it has worked out real good all these years, due to a new project requirement I need a large capacity flash memory seems like SPI to serial flash would be good given the new serial flash coming out now. 

Thanks.

0 Kudos