Home

Programming Microcontrollers using Assembly Language

image

Contents

1. df ertnl rjmp df ertn relative branch out of reach df_6 sbrs r17 4 check for read or write rjmp df 10 Jump if write cpi 22042 is it an input stream brne df ertn if not error clr r21 not really necessary rcall df send read a byte from DataFlash rjmp df okrtn and leave df 10 cpi 720 1 is it an output stream brne df_ertn if not error push r2l save their arg rcall df send shoot it to DataFlash pop r21 restore their arg rjmp df okrtn and go En era there is no open stream aE 2s sbre r17 7 command require an open stream rjmp df ertn yes error sbrs 71753 command require idle device rjmp df 3 Jump if no push r21 save scratch reg rcall df status read device status sbrs r21 7 bit 7 1 means ready rjmp df busy pop r21 restore scratch reg We will now put the 11 bit page address and 9 bit buffer address into R19 ZH and ZL R19 0000pppp ZH pppppppb ZL bbbbbbbb Even if our command doesn t use a page and or buffer address we still have to put out some don t care bits in their positions Since we don t care we can just use whatever was left over from the previous call df 3 lds ZL df _baddr low order buf byte addr lds ZH df baddr 1 high order buf byte addr ror ZH shift bit 0 to carry lds ZH df paddr low order page addr rol ZH carry to bit 0 bit 7 to carry lds r19 df paddr 1 high order page address andi r19 0x07 keep 3 bits
2. ldi r23 lt mov 1 223 rcall sendchar reall str_out ldi 723 12 mov 21 223 rcall sendchar ret ld EZ Y ldi r17 10 mul r2 217 add r0 r16 st y xr0 ret ldd r2 y 1 ldi r17 10 mul 72 217 mov 73 20 ld EDV mul r2 r17 add r0 r16 brec fw inc rl add Yl 13 st y Yr0 crud cpi yl low df_paddr brne bufa ldi r19 0x07 and r1 r19 rjmp fx tst ri breq fx ldi r19 0x01 and rl rt9 ldi r19 0x07 and r0 r19 st y xr0 std y tl rl ret Y r r repeat count helper routine put out r21 in hex convert to hex number hee ring pul on send s Gh ct helper routine add digit to byte current value multiply by 10 add in new digit keep low order byte helper routine add digit to word high byte multiply by 10 keep low order of product low byte multiply by 10 add in new digit carry add low 10 to high put low away range restrictions here all 11 bit values are legal for page addr mask high only 100000111 and lower is legal for buf keep 1 high bit and 3 low bits put high away 26 str out send string to USART 7 Z point to string to send preserved str_out push zh push zL push rl stl ld r1 Z tst rl breq stdne rcall sendchar rjmp stl stdne pop rl pop zl pop zh ret df command execute DataFlash command R16 command indicator df_cont_read through df close variables as needed df buf buffer
3. a specified starting address in the main memory Once the address is set up any number of bytes may be read without further addressing If we reach the end of memory page 2047 byte 263 the address wraps back to the beginning page 0 byte 0 B Main Memory Page Read a sequential stream of data is read from a specified starting address within a specified page of main memory Once the address is set up any number of bytes may be read without further addressing At the end of the page byte 263 the address wraps back to the beginning of the same page byte 0 C Buffer Read a sequential stream of data is read from a specified starting address within one of the SRAM buffers Once the address is set up any number of bytes may be read without further addressing At the end of the buffer the address wraps back to the beginning of the buffer D Status Register Read the device status register contents are returned The status register contains a device busy bit a comparison results bit and bits which specify the memory size of the device an arbitrary constant for a particular device type E Buffer Write a sequential stream of data is written to the specified buffer starting at a specified address Once the address is set up any number of bytes may be written without further addressing At the end of the buffer the address wraps back to the beginning of the buffer F Buffer to Main Memory Page with Erase the conte
4. are two internal SRAM buffers of 264 bytes which allows for overlapping operations One buffer may be written to or read from the DataFlash memory while the other buffer is being filled or emptied by the user Pages of memory are grouped into 256 blocks of 8 pages each and blocks are grouped into 6 sectors of 1 to 64 blocks each Most of our operations will happen at the page level although there is a command to erase memory at the block level Sectors are important in one special case of refreshing memory which we will discuss shortly A diagram of the device s architecture is shown in Figure 15 1 and summarized in Figure 15 2 DataFlash Memory Array Architecture Blocks Sectors Figure 15 1 DataFlash Memory Array Architecture am S x Sector Block s Pages Bytes 0 0 0 7 2 112 1 1 31 8 255 65 472 2 32 63 256 511 67 584 3 64 127 512 1023 135 168 4 128 191 1024 1535 135 168 5 192 255 1536 2047 135 168 Each page is 264 bytes long Each block is 8 pages long 2 112 bytes Figure 15 2 Allocation of the DataFlash Memory DataFlash Commands There are 21 different operations we can perform with the DataFlash For now we will gloss over the details and look at the big picture using the command names from the Atmel datasheet The pound sign designates a buffer number 1 or 2 A Continuous Array Read a sequential stream of data is read from
5. channel However we are relieved of needing temporary SRAM storage in this case although we may use it if we wish Types of Commands The Atmel documentation groups the DataFlash s commands into those that access the main memory and those that do not There are three commands in the second group Buffer Read C Status Read D and Buffer Write E These three commands may be performed in parallel with the commands in the first group although commands in either group may not be performed simultaneously with other commands in their group This means it is possible to be filling or emptying one DataFlash buffer while the other is being written or read to the main memory The efficiency that may be achieved from this overlapping of operations is why there are two internal buffers Most of the commands that access the main memory cause the device to be busy for some varying amount of time up to about 20 milliseconds for the worst case That may seem fast 0 02 seconds but it is enough time for the Butterfly to execute about 160 000 instructions Obviously we do not want to be storing frequently accessed data in the DataFlash if we can avoid it Figure 15 4 shows the relative timing of the commands For commands that access the main memory the DataFlash must be idle not busy before the command can be issued We will use the Status Read command to determine if the device is busy a command that we fortunately can send to a busy devic
6. loop shown and hang around like teenagers on a street corner The DataFlash Command Performance The only thing left is the routine that processes the commands df command execute DataFlash command R16 command indicator df cont_read through df close variables as needed df buf buffer selection in bit 0 df paddr page address df baddr buffer byte address returns R16 0 if command is successful unchanged if device is busy or error occurs Ne Ne Ne Ne Ne Ne Ne Ne Ne Ne Ne Se e if the call writes or returns data R21 is used for both df command push push push push push push NNB BKK Svo 2 H L in r17 spcr see if device is initialized sbrs r17 spe check th nable bit breg df_ertnl if cleared it s not initialized The caller will load the equate value corresponding to the desired command into R16 and may or may not need to put values into the df buf df_paddr and df_baddr variables depending on the command These variables are not modified by df command Upon return R16 will be zero for success or unchanged if the device were busy or in the case of some other error This allows calls to be easily repeated until R16 is returned as zero The first test the last three lines above is to check to see if the device were properly initialized If not we exit with R16 returned unchanged Next below we use the R16 value to fetch the command s three bytes out of the df def table As us
7. o termination swap r17 bit 4 to bit 0 position andi r17 0x01 keep R W bit inc r17 add 1 so W 1 R 2 sts df strm r17 and make it the stream flag This is the normal return which sets R16 to zero 18 df okrtn CLr 16 This is the error return which leaves R16 intact df ertn pop ZL pop ZH pop r20 pop r19 pop r18 pop r17 ret That is the end of the df command routine We called df doit to send the actual command to the DataFlash It sends out the opcode byte then the three address bytes we previously constructed then optionally 1 or 4 extra bytes needed for internal timing in the DataFlash df doit df 21 df 20 df doit send the DataFlash a full command 4 8 bytes initiate command by CS transition from hi to low then send out R8 R19 ZH and ZL and optionally some don t care bytes number is in R17 bits 0 2 leave CS in low state push r21 sbi portb portb0 bring CS high should already be cbi portb portb0 and drop it to start command mov r21 r18 opcode recall df send mov r21 r19 lst address byte rcall df send mov r21 ZH 2nd address byte rcall df send mov r21 ZL 3rd address byte rcall df send andi r17 0x07 extra byte count breg df 20 jump if none clr r21 not necessary rcall df send send extra byte dec BLT decrement byte counter brne df 21 jump if there are more pop w2 ret And that is all there is to it Now for some testi
8. page addresses The caller will store values in these variables as appropriate for the desired command load a command indicator into a register and then call the common entry point The value in the register will be used to select which command is desired and with portions of the above table encoded as flash memory constants the appropriate command can be sent to the DataFlash The Routines We can finally get down to the business of writing some code Start a new project I called mine Jack Flash in honor of Mick Jagger pushing 70 Here is the start of the program A File name Jack Flash asm Program to manipulate the DataFlash nolist include ml69def inc definitions for the Atmega 169 list Use thes quates in calls to df command to specify the desired command These values are offsets into f the df def bytes plus 1 equ df cont_read 1 A continuous read equ df page read 4 B page read equ df buf read C buffer read equ df stat_read 10 D status read equ df buf write 13 E buffer write equ df prog erase 16 F prog w erase equ df prog 19 G prog w o erase equ df page erase 22 H page erase equ df blk erase 25 I block erase equ df prog buf 28 J prog thru buffer equ df xfer 31 K page to buf xfer equ df compare 34 L page to buf comp equ df auto 37 M auto rewrite equ df read 40 N read stream equ df write 43 0 write stream equ df_
9. rol r19 carry to bit 0 28 df 9 df busy df 4 sbrc rjmp cpi brne rcall rjmp rcall sbi rjmp pop rjmp rcall swap andi inc sts df_okrtn df ertn df doit df 21 eier pop pop pop pop pop pop ret r17 6 df 4 r16 df stat_read df_9 does the command open a stream jump if yes special case jump if not status read df status read the status byte df okrtn normal return df doit execute command portb portb0 bring CS high to terminate command df okrtn device is busy we need idle r21 restore scratch register df ertn and hightail it error rtn df doit execute command w o termination r17 bit 4 to bit 0 position r17 0x01 keep R W kit r17 add 1 so W 1 R 2 df strm ri7 and make it the stream flag r16 ZL ZH r20 r19 r18 r17 df_doit send the DataFlash a full command 4 8 bytes initiate command by CS transition from hi to low send out R8 don t care bytes leave push push sbi cbi mov rcall mov rcall mov rcall mov rcall andi breq Gls reall dec then R19 ZH number is in R17 CS in low state and ZL and optionally some bits 0 2 r17 r21 portb portb0 portb portb0 B bring CS high should already be and drop it to start command 7215778 opcode df send r21 r19 lst address byte df send 21 ZH 2nd address byte df send r21 ZL 3rd address byte df send r17 0x07 extra byte count df
10. transition that the DataFlash recognizes as the start of a command We then load R21 with the Read Status opcode and send it using df send Then to read the status byte we must send an additional don t care byte via df send The byte does not need to be a zero it can be anything but we will zero it anyway due to our OCD Obsessive Compulsive Disorder When we are done we output a 1 to CS to terminate the command df send exchange byte with DataFlash Ne Se Ne se R21 byte going out and coming in df send out spdr r21 going out df wt in r21 spsr watch spif flag sbrs r2l spif 0 means busy rjmp df wt in r21 spdr grab the incoming byte ret The df send routine depends on the caller to take care of the CS line and any other details It simply sends what is in R21 to the DataFlash and returns the response in R21 The out instruction copies R21 to the SPI Data Register which causes the hardware to 14 start clocking the 8 bits to the DataFlash We then watch the SPIF bit of the SPSR SPI Status Register to see when the process has completed Once it has we read the result from SPDR the same data register we wrote to into R21 and we are done We could have used interrupts here It is possible to generate an interrupt when the SPDR register is able to accept the next character another way of looking at it is when the SPDR has received a character For our routines we will just do polling the check and jump
11. without reloading registers if the device is busy Initialization Now for some initialization of the SPI hardware in the ATmega 169 As usual we will put this code into a subroutine and call it which makes our program easier to read for humans and makes the code liftable portable for other projects df init initialize DataFlash communication this sets up the SPI stuff and resets the DataFlash note this is hard coded for the AVR Butterfly Ne Ne Ne Ne Se df init push ZH push ZL push r16 sbi ddre porte7 PE7 is an output cbi porte porte write 0 to reset DataFlash sbi ddrb portb0 sbi ddrb portbl sbi ddrb portb2 chi ddrb portb3 sbi portb portb0 BO is an output CS Bl is an output SCK B2 is an output MOST B3 is an input MISO write a 1 to CS Ne Ne Ne Ne Se ldi r16 30 df_b dec r16 reset for at least 10 microseconds brne dfb sbi porte porte7 drop reset pulse 12 ldi r16 1 lt lt spi2x SPI double speed out spsr rl6 enable SPI master mode 3 ldi r16 1 lt lt spe 1 lt lt mstr 1 lt lt cpha 1 lt lt cpol out sper rlo cLr ZL sts df strm ZL stream is closed ldi ZH 0xb3 kill gt 20 ms df lp sbiw ZHsZL 1 45 824 loops brne df lp pop r16 pop ZL pop ZH ret As the comments note this routine is specific to the Butterfly and its wiring Pin 7 of Port E is wired to the DataFlash reset line so we start by initiating a reset pulse We then set up t
12. zero jump if not O defaults to 1 value to write to stream restore command offset do command got a busy error return repeat count unknown character send character to host followed by CRLF and back into the loop set buffer 1 put buffer choice away good response is 24 buf2 paddr baddr wrtval rptval Zero show nxlp r20 set buffer 2 r20 bufla r21 page address active 722 page address is a word yh high df paddr yl low df_paddr ok r21 buffer address active r21 buffer address is a word yh high df baddr yl low df_baddr ok r21 write val active yh high wrval yl low wrval ok r21 repeat count active yh high rptcnt yl low rptcnt ok r16 zero active value y r16 first byte r16 r21 skip if not word y 1 r16 2nd byte ok yl show all values yh RODE i ys separator for values yh buffer selection yl df_buf uword 2 decimal str out r1 222 sendchar yh df paddr l page address yl df_paddr uword 2 decimal str_out 71 222 sendchar yh df baddr 1 buffer address yl df_baddr uword 2 decimal str out r1 x222 sendchar yh write value yl wrval uword 2 decimal str out 25 fixword fw do som bufa EX mov r1 r22 rcall sendchar clr yh lds yl rptent rcall uword 2 decimal reall str_out pop yn pop yl rjmp ok mov FO pr21 rcall byte 2 hex
13. 0x87 0x08 0x83 0x86 E and E db 0x08 0x88 0x89 0x08 0x81 0x81 G and H db 0x08 0x50 0x50 0x48 0x82 0x85 I and J db 0x08 0x53 0x55 0x08 0x60 0x61 K and L db 0x08 0x58 0x59 0x90 0x00 0x00 Mand N db 0x80 Ox01 0x01 OxA0 0x02 0x02 O and P main ldi r16 high RAMEND set up stack pointer out SPH r16 ldi r16 low RAMEND out SPL r16 This should look pretty familiar by now We have some equates equ directives which we will use to identify the DataFlash commands We will load one of them into R16 prior to calling the df command routine There are then three variables df paddr df baddr and df buf which are used to communicate addressing information to df command For those commands that require it see Figure 15 4 the user will load some or all of these variables with values specific to the command For example Block Erase requires the address of a page within the block to be erased there are 8 pages per block so df paddr would be loaded with an appropriate value Likewise Program with Erase needs to have a buffer number and a page address so df buf and df paddr would need to be defined For the word variables the low order byte is stored in the lower address for example df paddr and the high order byte is stored in the higher address df_paddr 1 The last variable df strm is used internally by df command and should not be explicitly changed by the user It indicate
14. 20 jump if none r21 not necessary df send send extra byte r17 decrement byte counter 29 brne df 21 df 20 pop r21 f jump if there are more pop r17 ret df status read the DataFlash status A returns R21 byte received df status sbi portb portb0 cbi portb portb0 ldi r21 0x57 rcall df send clr r21 rcall df send sbi portb portb0 r r Y r r r r bring CS high should already be and drop it to start command command read status send it out not necessary read the status bring CS high to end command ret i df send exchange byte with DataFlash R21 byte going out and coming in out spdr r21 df wt in r21 spsr sbrs r21 spif rjmp df wt r r going out watch spif flag 0 means busy in r21 spdr grab the incoming byte Pret df init initialize DataFlash communication this sets up the SPI stuff and resets the DataFlash note this is hard coded for the AVR Butterfly df init push ZH push ZL push r16 sbi ddre porte7 PE7 is an output cbi porte porte7 write 0 to reset DataFlash sbi ddrb portb0 BO is an output CS sbi ddrb portbl Bl is an output SCK sbi ddrb portb2 B2 is an output MOST cbi ddrb portb3 B3 is an input MISO sbi portb portb0 write a 1 to CS ldi r16 30 df b dec r16 reset for at least 10 microseconds brne df b sbi porte porte7 ldi r16 1 lt lt spi2x r drop reset pulse SPI double speed
15. 30 df lp out ldi out clr Sts ldi sbiw brne pop pop pop ret spsr rl6 enable SPI master mode 3 r16 1 lt lt spe 1 lt lt mstr 1 lt lt cpha 1 lt lt cpol spcr r16 ZL df_strm ZL stream is closed ZH 0xb3 kill gt 20 ms ZH ZL 1 45 824 loops df lp r16 ZL ZH 31
16. Additional Chapter for Programming Microcontrollers using Assembly Language by Chuck Baird This chapter tells how to use the AVR Butterfly s DataFlash serial memory chip and develops a general purpose support routine Copyright 2006 by Chuck Baird All rights reserved http www cbaird net 11 Chapter 15 Jumpin Jack DataFlash The AVR Butterfly has an integrated circuit IC chip that is not used by the distributed application although that software does contain some rudimentary support routines for it It is the Atmel AT45DB041B DataFlash memory chip a 4 megabit half a million bytes nonvolatile serial memory interfaced via the SPI interface The device datasheet which includes all the details that follow and much more can be downloaded from the Atmel website The DataFlash can be used to store a wide variety of data from digital voice to collected experimental data to program code ready to be written into the main flash memory The DataFlash cannot be directly read or written by AVR Studio although it is accessible to any SPI compatible device since the SPI pins on the Butterfly are brought out to the J400 connector see Chapter 11 Of course the Butterfly s ATmega 169 can read and write the DataFlash and even make it available through the RS 232 port as we shall see Device Architecture The DataFlash memory array is arranged as 2 048 pages of 264 bytes each for a total of 4 325 376 bits In addition there
17. am Properties Actual DataFlash Commands Pseudo A B C D E F G H I J K L M N O P Selects a buffer X XI XIX X X X X Uses buffer address Xi XIX X X Uses page address X X X X X X X X X xX Extra bytes for setup 4144 1 Causes busy X X X X X X XIX Busy time factor E ee ea alla Requires idle device XIX XIX XI XIX X XIX Opens stream X XIX X X Closes stream X Requires stream X XIX Stream type R R R W W X Figure 15 4 Command properties This table contains more information than we need but it is summarized here for completeness The first row Selects a buffer indicates whether the command acts on one of the two internal buffers We will look at the next three rows in a moment when we see how the addressing for the DataFlash works The next two rows are included for your information only and will not be used in our subroutine Causes busy indicates whether or not the command will busy the device and Busy time factor gives the worst case timing for how long the busy will last The units are 250 microseconds each or about 2 000 MCU instructions Requires idle device tells whether the command has to wait until the DataFlash is available and the last four rows indicate how the command uses streams In the Stream type row an R means we will be reading the stream and a W means we will be writing the stream X means it does not matter Com
18. am a open continuous read n lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt get stream byte s p close stream f write buffer to page a open continuous read n lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt lt 7B gt get stream byte s p close stream This starts off by showing the current values of the buffer page address buffer address write value and repeat count We then erase page 0 set the repeat count to 10 and show the values again We then open the continuous read stream read 10 bytes the repeat count and close the stream We then set the write value to 123 and write it to buffer 1 We again read 10 bytes which have not changed We then write buffer 1 to page 0 with erase and read 10 bytes This time they have changed to decimal 123 or 0x7B So it is as mentioned clumsy but it is also sufficient for testing We will borrow several of the support routines from other chapters usart_init sendchar byte_2_hex sendCRLF match_jumpl and uword_2 decimal The entire program follows minus the borrowed code which is available from the other projects The testing program of course is incidental to the DataFlash routines File name Jack Flash asm 3 Program to manipulate the DataFlash nolist include m169def inc definitions for the Atmega 169 list Use thes quates in calls to df command to specify A the
19. andle all commands The general flow of the command processing routine is as follows Entry Is the device initialized no error return yes is there an open stream no does the command require an open stream yes error return no does the command require an idle device yes is the device idle no busy return yes next step no does command open a stream yes send command leave stream open normal return no carry out command normal return yes does command require an open stream no error return yes carry out command read write or close stream normal return This will handle all commands although we will code Read Status a separate routine This is not only because it needs to be called from within this flow qe line but also because it has a different structure it does not need addressing bytes than all other commands It can be called either separately or through the common entry point To implement the above flow we will summarize what we know about the various commands plus three pseudo commands we will add The commands are A Continuous Read I Block Erase B Page Read J Program through Buffer C Buffer Read K Page to Buffer Transfer D Status Read L Page to Buffer Compare E Buffer Write M Auto Rewrite F Program with Erase N Get Byte from Stream G Program without Erase O Put Byte to Stream H Page Erase P Close Stre
20. at our leisure without worrying much about the DataFlash itself However with only 1K of SRAM to work with in the Butterfly we may not want to give up a minimum of over a fourth of it for one or more buffers for use with the DataFlash What this means in practical terms is that we may want to play some tricks with those commands that allow us to read or write DataFlash data whether to its pages or its internal buffers Rather than handling all the data at once which would require us to have space for it we may choose instead to break the process into three steps Open a channel read or write the data and close the channel We can then take our time with the second step perhaps generating the data by sampling the A D converters or sending the data out via the RS 232 line or playing it on the speaker In this manner our program has the option of handling the data a byte at a time and does not need a large local storage capacity Doing something like this requires more work on our part as programmers because we have to keep track of where we are in the process If all our data were collected in SRAM our Write to DataFlash routine could simply be called with the starting address of the data and the number of bytes and that would be it Using this alternative method we will need to call a routine to open the write channel make some number of calls to a routine which writes one byte per call and finally call a third routine which closes the
21. close 46 P close stream dseg r Y r These three variables will be loaded with appropriate values depending upon the command prior to calling the df command routine Notice that we are calling the buffers 0 and 1 rather than 1 and 2 df paddr byte 2 page address 0 2047 low then high df baddr byte 2 buffer address 0 263 low then high df buf byte 1 buffer even buffer 1 odd buffer 2 10 this variable is internal to df command do not alter df strm byte 1 stream O closed l output 2 input cseg what follows is flash code org 0x0000 jmp main reset comes her a This is th ncoded table which describes the DataFlash commands E Each entry is three bytes long and they are in the order of the quates above The first byte has bit flags describing the characteristics of the command The second byte is the opcode for i buffer 1 access and the third byte is the opcode for buffer 2 access For commands which do not use the internal buffers both opcodes will be the same byte 0 bit 0 2 number of extra bytes to append to address bit 3 if 1 requires idle devic R bit 4 if 1 read stream otherwise write or no stream bit 5 if 1 command closes stream A bit 6 if 1 command opens stream bit 7 if 1 command uses stream df def db 0x5C 0x68 0x68 Ox5C 0x52 0x52 A and B db 0x51 0x54 0x56 0x00 0x57 0X57 C and D db 0x40 0x84
22. desired command These values are offsets into the df def bytes plus 1 21 r r r df buf r df _ strm rptcnt wrval bx equ df cont_read 1 A continuous read equ df page read 4 B page read equ df buf_read 7 C buffer read equ df stat_read 10 D status read equ df buf write 13 E buffer write equ df prog erase 16 F prog w erase equ df prog 19 G prog w o erase equ df page erase 22 H page erase equ df blk erase 25 I block erase equ df prog buf 28 J prog thru buffer equ df xfer 31 K page to buf xfer equ df compare 34 L page to buf comp equ df auto 37 M auto rewrite equ df read 40 N read stream equ df write 43 0 write stream equ df_close 46 P close stream dseg These three variables will be loaded with appropriate values depending upon the command the df command routine buffers 0 and 1 rather than 1 and 2 df paddr df baddr r r r prior to calling Notice that we are calling the page address 0 2047 low then high buffer address 0 263 low then high buffer even buffer 1 odd buffer 2 this variable is internal to df_command do not alter byte 2 byte 2 byte byte 1 these byte byte 1 byte 10 cseg org 0x0000 jmp main r r r Y r Y stream O closed l output 2 input variables are used by the front end repeat cou
23. e We can also classify the commands into two other groups One group is made up of the commands that just cause something to happen like erasing a page or copying the contents of one of the buffers to the main memory Once we issue the command we do not need to have further interaction with the DataFlash although the device may become busy and temporarily unavailable The other group consists of those commands mentioned earlier that read or write some number of bytes to buffers or memory Those are the ones we are going to break into three step processes We will call these the streaming commands and the channel we establish a stream Support Routine Summary We can now state how we would like our set of DataFlash routines to behave at least in general terms e We will need an SPI initialization routine e The command processing routine will have a busy and or error return so we can wait until the device is available or recognize problems e For streaming commands we will need three types of operations Open stream read or write stream and close stream The actual command such as Read Page will open the stream Then we will make additional calls to read each byte and finally a separate call to close the stream e If the SPI is not initialized or if we call a non streaming routine while we are streaming or if we try to use a closed stream we will return an error e We can use a common entry point i e one subroutine to h
24. e rcall rjmp rcall rjmp 0x80 0x01 r16 high RA SPH r16 0x01 END r16 1low RAMEND SPL r16 usart init df init r10 df buf rl0 df paddr rl10 df paddr 1 r10 df baddr r10 df baddr 1 r10 rptcnt r10 wrval r10 r Y yh high wrval yl low wrval r21 zh high bx z1 low bx getchar loop sendchar 16 r1 To tat ota 22938 r16 digi digi ct ct r0O rl match jumpl huh x bufl X buf2 y paddr z baddr w wrtval r rptval zero show 0 0 r16 0 r21 wwd fixbyte ok fixword ok OxA0 0x02 0x02 O and P set up stack pointer do rs 232 initialialization and DataFlash initialization buffer 1 page address 0 Il o buffer address repeat count 0 which is 1 write value 0 R21 0 if byte 1 if word write value is active write value is a byte variable Z will point to string buffer for building output strings see if there s a character coming in if zero set no character otherwise echo it back to them get it for compare immediates check for command jump if lt a jump if p jump if lt p check for digit jump if lt 0 jump if 9 jump if lt 9 do a table lookup no match set buffer 1 set buffer 2 page address is active buffer address is active write val is active repeat count is active zero active value show all values end of list convert to dec
25. ead Status command The first tells us whether the MCU s SPI hardware is ready to accept another byte to clock out to the SPI slave and the second tells us whether the DataFlash is involved with internal reading or writing of its main memory 13 If the command we send does cause the DataFlash to go busy this happens following the CS line being brought back high For our stream commands we will send the command as outlined above but we leave the CS line low This leaves the DataFlash expecting more data Then at our leisure we can send receive additional data with no manipulation of CS Finally to close the stream we bring CS high once again thus terminating the command sequence The DataFlash may or may not become busy at that point depending on the command We have a separate routine df status to read the status byte of the DataFlash It is the simplest of the commands because it has no addressing bytes We just send the command opcode 0x57 then read the response Here is the entire routine df status read the DataFlash status returns R21 byte received df status sbi portb portb0 bring CS high should already be cbi portb portb0 and drop it to start command ldi r21 0x57 command read status rcall df send send it out GLI r21 not necessary rcall df send read the status sbi portb portb0 bring CS high to end command ret To be safe we bring CS high then take it low to get the high to low
26. he datasheet specifically notes that changing a bit from a 1 to a 0 without first erasing is not recommended Always erase a page prior to programming it The Status Byte Bit 7 of the status byte is the device busy bit where a 1 means the device is ready and 0 means the device is busy Bit 6 is used to test the results of compare operations where 0 means the contents matched and 1 means the contents differed Following a compare we need to wait until the device is no longer busy before looking at the compare results The device memory size density is encoded into bits 5 through 2 of the status byte This is an arbitrary constant for each device type and the binary value does not reflect the size For the Butterfly s DataFlash chip the four bits are 0111 Sector Refreshes Sectors are groups of 1 to 64 blocks where blocks are 8 pages long see Figure 15 2 Each page in a sector must be reprogrammed erased and rewritten within every 10 000 cumulative page erase program operations in that sector The Auto Rewrite command is designed to simplify this task If we are sequentially programming pages within a sector then this problem never arises However if we are randomly updating reprogramming pages then it is necessary to ensure that we refresh each page in each sector at least once every 10 000 updates of pages within that sector In the worst case a total page by page refresh of one of the larger 512 page sectors using the Au
27. he other SPI pins and write a 1 to the CS Chip Select line This is the line we will use to tell the DataFlash we are talking to it A high 1 means we are not and a low 0 means we are so the line is said to be active low The tilde or NOT is used to designate CS as an active low line We then waste some time to make sure our reset pulse is long enough and release the reset line We set the operational parameters of the SPI in two I O registers We set it to double speed SPI master mode 3 which determines how it interprets data and enabled We will use the enable bit later on to verify that this initialization routine was previously called We mark the data stream as closed df_strm 0 and then kill some more time quite a lot actually to let the DataFlash fully wake up from its reset stupor Details like these timing considerations are in the DataFlash datasheet The SPI register details are in the ATmega User s Manual in the SPI section Sending Commands to the DataFlash The way we talk to the DataFlash is to bring the CS line Port B bit 0 from a high to a low 1 to 0 Then we output bytes to the SPI VO register SPDR SPI Data Register watching its busy bit to see when it can accept the next byte When we are done we bring the CS line back high to signal the end of the communication The busy bit just mentioned in conjunction with the SPDR register is not the same as the busy bit returned from the DataFlash R
28. imal whether it s a byte or word jump if word 23 cmd ertn readstr 132 mov subi mov isl add inc cpi breq cpi breq reall EST brne cpi brne reall rjmp ldi rjmp mov lds tst brne inc mov rcall Est brne rcall dec brne rjmp writestr 131 huh nxlp bufl bufla ok mov lds EST brne inc lds mov rcall EST brne dec brne rjmp ldi mov reall reall rjmp clr Sts ldi 18 r16 Oy a 15 r16 16 16 r15 16 KARA RA A r18 n readstr r18 o writestr df command nxlp r18 r16 r22 rptcnt r22 rj2 r22 r16 r18 df command r16 ertn out21 122 rj2 ok r18 r16 r22 rptcnt r22 rjl r22 r21 wrval r16 r18 df command r16 erin E22 rjl ok ELO Tp r1 r16 sendchar sendcrlf loop r20 df buf r20 r16 keep orig convert to 0 15 save a copy multiply by 2 add original for 3 turn a gt 1 p gt 46 need special handling jump if read stream jump if write stream otherwise go do it got a busy error return need special handling jump if not status read put out r21 in hex error return read stream which may be repeated save command offset get repeat count check for zero jump if not O defaults to 1 restore command offset do command got a busy error return put out r21 in hex repeat count write stream which may be repeated save command offset get repeat count check for
29. ividual clock pulse and take care of several overhead details Just like we can design software RS 232 interfaces we can do likewise for SPI but it is much easier and more reliable to use the USART and SPI hardware that is incorporated in the MCU For more information there is a short discussion of SPI in the ATmega 169 User s Manual page 143 and the datasheet for the AT45DB041B DataFlash memory is available on the Atmel website Designing the DataFlash Access Routines To come up with a design for support routines for the DataFlash we need to give some thought to the kinds of things we will likely want to do Obviously we will need an SPI initialization routine or nothing will work We will also want to look at the interrupt capabilities of the SPI if any and decide whether we want to make use of them Finally there is the question of whether to implement all of the commands the DataFlash knows or pick a reasonable subset of them suitable for general use We may also want to have additional routines which provide services that do not translate directly to DataFlash commands If we were programming a computer with a large amount of standard memory SRAM designing some of the routines to access the DataFlash would be fairly straight forward We could easily allocate one or more buffers at 264 bytes each in memory then write routines to copy them to and from the DataFlash buffers and or pages We could fill or empty the local buffers
30. municating with the DataFlash To send a command to the DataFlash we write the command a hex operation code or opcode a fancy way of saying a number to an I O register in the MCU The MCU s SPI hardware then automatically clocks the bits to the DataFlash For all but the Read Status command we then send between 3 and 7 additional bytes For all of these bytes we will ignore the return values remember the SPI receives data as it sends data In the order of transmission the 3 address bytes consist of 4 don t care bits 11 bits of page address a value of 0 to 2047 and 9 bits of byte address a value of 0 to 263 A few commands want either one or four additional bytes of don t care bits for internal timing considerations but most do not That makes each command other than Read Status either 4 5 or 8 bytes long Now the three mystery rows in the table above make sense Uses buffer address shows whether we have to have an actual buffer offset in the 9 bits or whether those are 9 don t care bits Likewise Uses page address indicates whether we need an actual 11 bit page address or can use don t care bits Finally Extra bytes for setup gives the number of additional bytes we need to add following the address bytes if any The method we will use to pass arguments to our routines will be to define three variables a single byte for the buffer selector and two word variables for the 9 bit buffer and 11 bit
31. ng to see if it all works 19 Test routines The program to test these routines will likely be more complicated and longer than the routines being tested We will make a general purpose front end that uses single character commands issued by host software via the RS 232 line Here are the commands it will recognize they are case sensitive Command Use a p execute DataFlash command select buffer 1 select buffer 2 enter page address enter buffer byte address enter write byte value enter repeat count 0 9 accumulate active numeric value zero active numeric value display addresses and variables ml IN lt pd gt II We have some variables that can be set by the user the page address buffer byte address write value and repeat count We select which one is active with its command y z w or r Then as the digits 0 to 9 are received the current value is multiplied by 10 and the new digit is added The value is kept within its legal range page addresses from 0 to 2047 buffer addresses from 0 to 263 write value from 0 to 255 and repeat count from 0 to 255 A minus sign zeroes the active value An equals sign causes all the values to be sent to the host displayed The commands a to p execute the corresponding DataFlash commands a Continuous Read i Block Erase b Page Read j Program through Buffer c Buffer Read k Page to Buffer Transfer d Stat
32. nt value to write to stream string buffer what follows is flash code reset comes her This is th ncoded tabl Each entry is three bytes long which describes the DataFlash commands and they are in the order of the quates abov characteristics of the command buffer 1 access access Th and the third byt For commands which do not use the internal buffers first byte has bit flags describing the The second byte is the opcod is the opcode for buffer 2 both for opcodes will be the same number of extra bytes to append to address byte 0 bit 0 2 bit 3 D bit 4 if bit 5 1f bit 6 1f bit 7 if db 0x5C 0x68 db Ox51 0x54 db 0x40 0x84 db 0x08 0x88 db 0x08 0x50 db 0x08 0x53 db 0x08 0x58 1 requires idle devic 1 read stream otherwise write or no stream 1 command closes stream 1 command opens stream 1 command uses stream 0x68 0x5C 0x52 0x52 A and B 0x56 0x00 0x57 0x57 C and D 0x87 0x08 0x83 0x86 E and F 0x89 0x08 0x81 0x81 G and H 0x50 0x48 0x82 0x85 I and J 0x55 0x08 0x60 0x61 K and L 0x59 0x90 0x00 0x00 M and N 22 main loop nota notd digit wwd db ldi out ldi out reall reall clr sts sts sts sts sts sts Sts Y points to active variable ldi ldi GER 1di ldi rcall breq reall mov 5 O o 5 O 0 0 0 00 000 00 subi Est brn
33. nts of the specified buffer is written to a page in memory following the erasure of that page The status register will indicate the device is busy during this operation G Buffer to Main Memory Page without Erase the contents of the specified buffer is written to a page in memory The page must have been previously erased The status register will indicate the device is busy during this operation H Page Erase the specified page of main memory is erased The status register will indicate the device is busy during this operation I Block Erase the specified block of 8 pages is erased The status register will indicate the device is busy during this operation When large amounts of data are written a block erase can be more efficient than a page by page erase J Main Memory Page Program through Buffer this command is a combination of the Buffer Write and the Buffer to Main Memory Page with Erase commands Data is written to the specified buffer and when the command terminates the target page is erased and the buffer is written to the specified page The status register will indicate the device is busy during the erase and write operations K Main Memory Page to Buffer Transfer this reads a page of main memory into one of the buffers The status register will indicate the device is busy during this operation L Main Memory Page to Buffer Compare this compares the contents of one of the buffers with the content
34. oes the command require an idle device 7 yes 1s the device idle 8 no busy return 9 yes next step 10 no does command open a stream 11 yes send command leave stream open 12 normal return 13 no carry out command 14 normal return 15 yes does command require an open stream 16 no error return 17 yes carry out command read write or close stream 18 normal return We are starting at line 3 where we check to see if there is an open stream The variable df _strm is 0 if not or nonzero 1 output 2 input if so lds r20 df strm check the stream flag tst r20 set the flags lds does not breg df 2 Jump if no open stream 16 This is line 15 We check to see if this command requires an open stream Only the stream read write and close pseudo commands do sbrs r17 7 command require an open stream rjmp df ertn no error This is line 17 where we perform the stream commands For a close we will bring CS high and zero df_strm FE noo we have a stream cmd read write or close sbrs ELTS is the command close stream rjmp df 6 jump if not sbi portb portb0 yes bring CS high to stop xfer clr r17 sts df strm r17 stream is now closed rjmp df okrtn df ertnl rjmp df ertn relative branch out of reach df_6 sbrs r17 4 check for read or write rjmp df 10 Jump if write For a Read Stream command we make sure it is an inp
35. s of the specified page The status register will indicate the device is busy during this operation At the end of the operation the compare bit of the status register will indicate the results of the compare M Auto Page Rewrite through Buffer this is a combination of the Main Memory Page to Buffer Transfer and the Buffer to Main Memory Page with Erase commands A page of main memory is copied into a buffer that page is erased and then the buffer is rewritten to the original page The status register will indicate the device is busy during this operation The purpose of this command is for sector refreshes discussed later A diagram of the commands and their associated actions may help clarify them The command names have also been simplified slightly to make them easier to reference later The letter designations A B etc are the same as in the above list Only one SRAM buffer is shown although there are two separate and equal buffers either of which may be specified for any command which uses a buffer Main Memory SRAM Buffers Continuous Read Page Read Buffer Read gt A B C D E Buffer Write F A B C D Status Read E F Program with Erase G Program without Erase H Page Erase 1 Block Erase J Program through Buffer K Page to Buffer Transfer L Page to Buffer Compare M Auto Rewrite Figure 15 3 DataFlash commands An erased bit will read as a 1 However t
36. s whether there is an open stream and if so whether it is an input read or output write stream 11 Next we find 48 bytes in flash at address df def three per command which define the commands The first byte has bit flags for the way the command uses streams whether it requires an idle device and how many extra bytes need to follow the addressing bytes The second byte is the command opcode if we are using buffer 1 and the third byte is the opcode if we are using buffer 2 Notice that 1 and 2 are Atmel s names for the buffers but we will select buffer 1 if bit 0 of df_buf is 0 and buffer 2 if bit 0 of df bufis 1 We could call the buffers Barney and Wilma if we wished since all references to them will be through bit 0 of df buf and it really does not matter which is which As long as we are consistent If a command does not use a buffer then the same opcode is repeated in both the second and third bytes This allows us to act as if all commands use buffers and select the opcode based on bit 0 of df buf in all cases Where the buffer does not matter we get the same opcode in either case It simplifies the code a little Notice that the equates are merely offsets into the df def values that locate the first byte of each command s set plus one We add one to make these offsets nonzero because our command processor will return the original offset in case of a busy or error or zero in case of success That allows us to call again
37. selection in bit 0 df paddr page address df baddr buffer byte address returns R16 0 if command is successful unchanged if device is busy or error occurs if the call writes or returns data R21 is used for both df command push r17 push r18 push r19 push r20 push ZH push ZL in r17 spcr see if device is initialized sbrs r1l7 spe check th nable bit breg df_ertnl if cleared it s not initialized ldi ZL low df def lt lt 1 put address of table word addr ldi ZH high df def lt lt 1 into Z register add ZL r16 R16 has byte offset 1 4 etc brcc df 1 Check for overflow inc ZH carry into high order dr 1 sbiw ZH ZL 1 R16 was one byte too much lpm r17 Z load bit flags for command lpm r18 2 and buffer 1 opcode lpm 1952 and buffer 2 opcode lds ZL df buf bit 0 says which opcode to use sbrc ZL O if bit 0 0 r18 is good mov r18 r19 otherwise use buffer 2 r19 A At this point R17 has the bit flags for the command and A R18 has the opcode we will use for the DataFlash 21 lds r20 df strm check the stream flag Est r20 set the flags lds does not breg df 2 Jump if no open stream sbrs r17 7 command require an open stream rjmp df ertn no error ARS we have a stream cmd read write or close sbrs LAO is the command close stream rjmp df 6 Jump if not sbi portb portb0 yes bring CS high to stop xfer clr r17 sts df strm r17 stream is now closed rjmp df okrtn
38. to Rewrite command can take over 10 seconds so this is an issue that might justify some design creativity to resolve The SPI Interface The Serial Peripheral Interface or SPI is a protocol supported by the ATmega 169 hardware and used by the DataFlash chip In the Butterfly the MCU s SPI lines are connected to the DataFlash and brought out to solder pads Unfortunately in the ATmega 169 the SPI pins are also Port B pins 0 3 This means that if we use the DataFlash in one of our programs we must for that program sacrifice the lower four bits of Port B Normally this would not be a problem but in the Butterfly so few I O pins are externally available because of the wealth of other features it may hamper some designs SPI works by exchanging data between two devices one of which is designated the master and the other is designated the s ave In the Butterfly the DataFlash chip will always be the slave The ATmega 169 is capable of assuming either role and even switching on the fly The master sends commands to the slave and provides the clock for the data exchange The slave does not initiate communication Essentially SPI sets up a pair of registers one in the master and one in the slave and shifts data bits between them Bits that leave the master end up in the slave s register and bits that leave the slave end up in the master s register When the master hardware sends 8 clock pulses the two devices exchange a byte So
39. ual we have to convert the flash word address to a byte address then we add the offset Because of the way we are returning either the offset or a zero to indicate failure or success we added one to the offsets to make them nonzero The sbiw instruction subtracts one to correct the value back to a true offset 15 We then load the three bytes for the command from flash memory R17 gets the flag bits and R18 and R19 get the two opcodes We look at bit 0 of df buf to decide which opcode to use and the winner ends up in R18 ldi ZL low df def lt lt 1 put address of table word addr ldi ZH high df def lt lt 1 into Z register add ZL r16 R16 has byte offset 1 4 etc brcc af 1 Check for overflow inc ZH carry into high order df 1 sbiw ZH ZL 1 R16 was one byte too much lpm r17 2 load bit flags for command lpm r18 2 and buffer 1 opcode lpm r19 2 and buffer 2 opcode lds ZL df_ buf bit 0 says which opcode to use sbrc ZL 0O if bit 0 0 r18 is good mov r18 r19 otherwise use buffer 2 r19 A At this point R17 has the bit flags for the command and R18 has the opcode we will use for the DataFlash Now we walk through the flowchart mentioned earlier which is repeated here with line numbers for reference 1 Entry Is the device initialized 2 no error return 3 yes 1s there an open stream 4 no does the command require an open stream 5 yes error return 6 no d
40. us Read l Page to Buffer Compare e Buffer Write m Auto Rewrite f Program with Erase n Get Byte from Stream g Program without Erase o Put Byte to Stream h Page Erase p Close Stream The write value is used for command o and the repeat count allows automatic multiple reads and writes for commands n and o A repeat count of 0 is interpreted as 1 Each single character sent by HyperTerminal or other host software will be echoed There may or may not be additional data sent commands n and d and then an exclamation mark success or asterisk failure and a carriage return line feed follows 20 With this set of commands we can fully test the DataFlash routines albeit in a slightly clumsy manner We will need to remember to close the stream when we open it commands a b c e and j The d and n commands will echo what was received in hexadecimal in decimal Here is a sample dialog 0 0 0 0 0 show variables h erase page 0 r set repeat count active 1 repeat count 1 0 repeat count 10 0 0 0 0 10 show variables a open continuous read n lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt lt FF gt get stream byte s p close stream w set write value activ 1 write value 1 2l write value 12 3 write value 123 0 0 0 123 10 show variables e open buffer write stream o write byte s to stream p close stre
41. ut out some don t care bits in their positions Since we don t care we can just use whatever was left over from the previous call df 3 lds ZL df_baddr low order buf byte addr lds ZH df baddr 1 high order buf byte addr ror ZH shift bit 0 to carry lds ZH df paddr low order page addr rol ZH carry to bit 0 bit 7 to carry lds r19 df paddr 1 high order page address andi r19 0x07 keep 3 bits rol r19 carry to bit 0 This is the real line 10 where we check to see ifthe command opens a stream sbrc r17 6 does the command open a stream rjmp df_4 jump if yes This is line 13 where we execute a command that does not open a stream First we will see if the command is Read Status and if so just call df status to do the work Otherwise we call df_doit and then bring CS high to terminate the command cpi r16 df stat_read special case brne df_9 jump if not status read rcall df status read the status byte rjmp df okrtn normal return df_9 reall df doit execute command sbi portb portb0 bring CS high to terminate command rjmp df okrtn df busy device is busy we need idle pop r21 restore scratch register rjmp df ertn and hightail it error rtn This is line 11 where we execute the command but leave the stream open We call df doit for the command but then leave CS low We also set df_strm to 1 for an output stream or 2 for an input stream df 4 reall df doit execute command w
42. ut stream then read a byte cpi r20 2 is it an input stream brne df ertn if not error clr r21 not really necessary rcall df send read a byte from DataFlash rjmp df okrtn and leave For a Write Stream command we make sure it is an output stream then write a byte df 10 cpi 22057 is it an output stream brne df ertn if not error push r21 save their arg rcall df send shoot it to DataFlash pop r21 restore their arg rjmp df okrtn and go This is line 4 We check to see if the command requires a stream and that the DataFlash not be busy Kenn there is no open stream GE 2 sbrc r17 7 command require an open stream rjmp df ertn yes error sbrs iS command require idle device rjmp df 3 Jump if no This is line 7 where we read the DataFlash status byte and check the busy bit push r21 save scratch reg rcall df status read device status 17 sbrs r21 7 bit 7 1 means ready rjmp df busy pop r21 restore scratch reg These next lines perform a little preparation for line 10 which is not in the flowchart Since at this point we know we will be needing to send the addressing bytes we construct the 3 bytes that will be sent following the command opcode We will now put the 11 bit page address and 9 bit buffer address into R19 ZH and ZL R19 0000pppp ZH pppppppb ZL bbbbbbbb Even if our command doesn t use a page and or buffer address we still have to p
43. we will access the DataFlash by loading an ATmega 169 SPI output register with a command byte which will then be automatically clocked shifted to the slave We will usually follow this byte with some addressing bytes For each byte sent we will also receive a byte in return but we will ignore these Then if we expect a response to our command for example when we read the DataFlash we will send one or more don t care bytes which clock the DataFlash additional times and allows us to receive the response The phrase don t care means the contents is irrelevant it is the number of bits that counts The idea of having to send something to receive something is a little foreign for normal peripheral interactions like reading a joystick switch Before we can use the SPI we must initialize its hardware by writing to some internal MCU registers After initialization we use the MCU s SPI registers to send the DataFlash its expected commands and receive its responses The commands themselves are interpreted by the DataFlash Therefore part of our conversation is with the ATmega 169 SPI hardware and part of it is with the DataFlash We could in a similar manner set up two or more Butterflies or other SPI capable MCUs to communicate with each other For completeness let me point out that it is possible to talk to the DataFlash by emulating the SPI interface using the Port B I O pins In that case we would have to generate each ind

Download Pdf Manuals

image

Related Search

Related Contents

  3000 Tradewind™  AGPS User's Manual (PC)  Service Manual - Genie Industries  JVC Range toledo User's Manual  Standaard manual  Le paiement électronique sur Internet  PENTATrainer User Manual - University College London  Bitdefender Antivirus for Mac  CONTENTS - Telefonguru  

Copyright © All rights reserved.
Failed to retrieve file