gavrasm Gerd's AVR assembler version 2.1 (C)2006 by DG4FAC ---------------------------------------------------------- Source file: spi_bit_bang_test.asm Hex file: spi_bit_bang_test.hex Eeprom file: spi_bit_bang_test.eep Compiled: 07.12.2007, 19:48:52 Pass: 2 1: ; 2: ; audiomega3-sampler 3: ; 4: ; Audio sampler 5: ; 6: 7: .include "m88def.inc" -> Warning 009: Include defs not necessary, using internal values! File: spi_bit_bang_test.asm, Line: 7 Source line: .include "m88def.inc" 8: ;.device ATmega88 9: 10: ; 11: ; dataflash definitions 12: ; 13: ; read 14: .equ CONTINUOUS_ARRAY_READ = 0xE8 15: .equ MAIN_MEMORY_PAGE_READ = 0xD2 16: .equ BUFFER_READ = 0xD4 17: .equ STATUS_REGISTER_READ = 0xD7 18: .equ FLASH_BUSY = 7 19: ; write 20: .equ BUFFER_WRITE = 0x84 21: .equ BUFFER_TO_MAIN_MEMORY_PAGE_PROGRAM_WITH_ERASE = 0x83 22: .equ BUFFER_TO_MAIN_MEMORY_PAGE = 0x88 23: .equ PAGE_ERASE = 0x81 24: .equ BLOCK_ERASE = 0x50 25: .equ MAIN_MEMORY_PAGE_PROGRAM_THROUGH_BUFFER = 0x82 26: ; additional 27: .equ MAIN_MEMORY_PAGE_TO_BUFFER_TRANSFER = 0x53 28: .equ MAIN_MEMORY_PAGE_TO_BUFFER_COMPARE = 0x60 29: .equ AUTO_PAGE_REWRITE_THROUGH_BUFFER = 0x58 30: ; properties 31: .equ PAGE_COUNT = 512 32: .equ BUFFER_COUNT = 264 33: 34: ; 35: ; definitions 36: ; 37: .equ tx = PD1; transmit pin 38: .equ tx_port = PORTD 39: .equ tx_ddr = DDRD 40: 41: .equ led1 = PC5 42: .equ led1_port = PORTC 43: .equ led1_ddr = DDRC 44: 45: .equ led2 = PD5 46: .equ led2_port = PORTD 47: .equ led2_ddr = DDRD 48: 49: .equ but1 = PD6 50: .equ but1_port = PORTD; 51: .equ but1_ddr = DDRD; 52: .equ but1_pin = PIND; 53: 54: .equ but2 = PD7 55: .equ but2_port = PORTD; 56: .equ but2_ddr = DDRD; 57: .equ but2_pin = PIND; 58: 59: .equ cs = PB2 60: .equ cs_port = PORTB 61: .equ cs_ddr = DDRB 62: 63: ; 64: ; registers 65: ; 66: .def bit_count = R16; bit counter 67: .def temp = R17; temporary storage 68: .def temp1 = R18; temporary storage 69: .def temp2 = R19; 70: .def txbyte = R20; data byte 71: .def spi_byte = R21; 72: .def remember_spi_byte = R26 73: 74: .def page_count_low = R22 75: .def page_count_high = R23 76: 77: .def buffer_count_low = R24 78: .def buffer_count_high = R25 79: ; 80: ; macros 81: ; 82: ; 16-bit math 83: .macro inc_16 84: ldi temp, 1 85: ldi temp1, 0 86: add @0, temp 87: adc @1, temp1 88: .endmacro 89: .macro add_16 90: ldi temp, low(@2) 91: ldi temp1, high(@2) 92: add @0, temp 93: adc @1, temp1 94: .endmacro 95: .macro cpi_16 96: cpi @0, low(@2) 97: ldi temp, high(@2) 98: cpc @1, temp 99: .endmacro 100: ; timing 101: .macro delay_i 102: ldi temp, @0 103: delay_loop: 104: dec temp 105: brne delay_loop 106: .endmacro 107: ; memory functions 108: .macro write_flash_page_address 109: ; bits: xxxxxx11 11111110 00000000 110: ; ^res ^^page pos^^buff pos^ 111: mov temp1, page_count_low 112: mov temp2, page_count_high 113: lsl temp1 114: rol temp2 ; rotate through carry to shift bits 1 to the left 115: mov spi_byte, temp2 ; N.B. high first, then low 116: ; careful... write_spi poisons "temp" 117: rcall write_spi 118: mov spi_byte, temp1 119: rcall write_spi 120: ldi spi_byte, 0 121: rcall write_spi 122: .endmacro 123: .macro write_dont_care_bytes 124: ldi spi_byte, 0 125: rcall write_spi 126: rcall write_spi 127: rcall write_spi 128: rcall write_spi 129: .endmacro 130: .macro write_opcode 131: ldi spi_byte, @0 132: rcall write_spi 133: .endmacro 134: .macro enable_flash 135: cbi cs_port, cs 136: .endmacro 137: .macro disable_flash 138: sbi cs_port, cs 139: .endmacro 140: .macro reset_page_count 141: ldi page_count_low, 0 142: ldi page_count_high, 0 143: .endmacro 144: .macro reset_buffer_count 145: ldi buffer_count_low, 0 146: ldi buffer_count_high, 0 147: .endmacro 148: ; feedback & debugging 149: .macro write_led_on 150: cbi led2_port, led2 151: .endmacro 152: .macro write_led_off 153: sbi led2_port, led2 154: .endmacro 155: .macro read_led_on 156: cbi led1_port, led1 157: .endmacro 158: .macro read_led_off 159: sbi led1_port, led1 160: .endmacro 161: .macro debug_spi 162: mov txbyte, page_count_low 163: rcall putchar 164: mov txbyte, page_count_high 165: rcall putchar 166: mov txbyte, buffer_count_low 167: rcall putchar 168: mov txbyte, buffer_count_high 169: rcall putchar 170: mov txbyte, spi_byte 171: rcall putchar 172: .endmacro 173: 174: ; 175: ; code segment 176: ; 177: .cseg 178: .org 0 179: 000000 C10C rjmp reset 180: ; 181: ; bit delay 182: ; serial bit delay 183: ; 184: ;.equ b = 13 ; 9600 baud (clock /8) 185: ;.equ b = 130 ; 9600 baud (clock /1) 186: .equ b = 8 ; 115200 baud (clock /1) 187: bit_delay: 188: 000001 E018 ldi temp, b 189: bitloop: 190: 000002 951A dec temp 191: 000003 F7F1 brne bitloop 192: 000004 9508 ret 193: ; 194: ; putchar 195: ; assumes no line driver (doesn't invert bits) 196: ; 197: .equ sb = 1; number of stop bits 198: putchar: 199: 000005 E00A ldi bit_count, 9+sb; 1+8+sb 200: 000006 9540 com txbyte; invert everything 201: 000007 9408 sec; set start bit 202: putchar0: 203: 000008 F410 brcc putchar1; if carry set 204: 000009 9A59 sbi tx_port, tx; send a '0' 205: 00000A C002 rjmp putchar2; else 206: putchar1: 207: 00000B 9859 cbi tx_port, tx ; send a '1' 208: 00000C 0000 nop ; even out timing 209: putchar2: 210: 00000D DFF3 rcall bit_delay; one bit delay 211: 00000E DFF2 rcall bit_delay 212: 00000F 9546 lsr txbyte; get next bit 213: 000010 950A dec bit_count; if not all bits sent 214: 000011 F7B1 brne putchar0; send next bit 215: 000012 9508 ret; 216: ; 217: ; char_delay 218: ; delay between characters 219: ; 220: char_delay: 221: 000013 EF1F ldi temp, 255 222: char_delay_loop: 223: 000014 E02A ldi temp1, 10 224: char_delay_loop1: 225: 000015 952A dec temp1 226: 000016 F7F1 brne char_delay_loop1 227: 000017 951A dec temp 228: 000018 F7D9 brne char_delay_loop 229: 000019 9508 ret 230: ; 231: ; Write data to SPI 232: ; 233: write_spi: 234: 00001A 2FA5 mov remember_spi_byte, spi_byte 235: 00001B D012 rcall rw_spi 236: 00001C 2F5A mov spi_byte, remember_spi_byte 237: 00001D 9508 ret 238: 239: read_spi: 240: 00001E D00F rcall rw_spi 241: 00001F 9508 ret 242: 243: ; 244: ; Software SPI 245: ; 246: .equ miso = PB4 247: .equ mosi = PB3 248: .equ sck = PB5 249: .equ nss = PB2 250: .equ spi_port = PORTB 251: .macro ss_active 252: cbi spi_port, nss 253: .endmacro 254: .macro ss_inactive 255: sbi spi_port, nss 256: .endmacro 257: .macro sck_hi 258: sbi spi_port, sck 259: .endmacro 260: .macro sck_lo 261: cbi spi_port, sck 262: .endmacro 263: .macro mosi_hi 264: sbi spi_port, mosi 265: .endmacro 266: .macro mosi_lo 267: cbi spi_port, mosi 268: .endmacro 269: .macro addi 270: subi @0, -@1 ;subtract the negative of an immediate value 271: .endm 272: .macro set_delay ;set up the time delay amount, from 1 to 7 273: subi @0, (@1 << 5) ;NOTE: THIS shift affects INC macro (below)! 274: .endm 275: .macro inc_delay ;bump the delay counter 276: subi @0, -(1 << 5) ;shift value here must be same as above! 277: .endm 278: 279: init_spi: 280: ss_inactive ;set latch bit hi (inactive) 281: 000021 9A22 sbi ddrb,nss ;make it an output 282: ; 283: sck_lo ;set clk line lo 284: 000023 9A25 sbi ddrb,sck ;make it an output 285: ; 286: mosi_lo ;set data-out lo 287: 000025 9A23 sbi ddrb,mosi ;make it an output 288: ; 289: 000026 9824 cbi ddrb,miso ;not really required, it powers up clr'd! 290: 000027 9508 ret 291: 292: ena_spi: 293: sck_lo ;(should already be there...) 294: mosi_lo 295: ss_active 296: 00002B 9508 ret 297: 298: disa_spi: 299: ss_inactive 300: 00002D 9508 ret 301: 302: rw_spi: 303: ;ldi temp,16 ;init loop counter to 16 bits 304: 00002E E018 ldi temp,8 ;use THIS line instead if 8-bit desired 305: ; 306: spi_loop: 307: 00002F 0F55 lsl spi_byte ;move 0 into D0, all other bits UP one slot, 308: ;rol spi_hi ; and C ends up being first bit to be sent. 309: ;If 8-bit desired, also comment out the preceding ROL SPI_HI statement 310: ; 311: 000030 F410 brcc lo_mosi 312: mosi_hi 313: 000032 C002 rjmp mosi_done ;this branch creates setup time on MOSI 314: lo_mosi: 315: mosi_lo 316: 000034 0000 nop ;also create setup time on MOSI 317: mosi_done: 318: ; 319: sck_hi 320: ; 321: ;must now time the hi pulse - not much else we can do here but waste time 322: ; 323: set_delay temp,4 ;(4 * 3) cycle delay; range is from 1 to 7! 324: time_hi: 325: inc_delay temp ;inc upper nibble until it rolls over; then, 326: 000038 F3F0 brcs time_hi ; C gets CLEARED, & temp has original value 327: ; 328: sck_lo ;drop clock line low 329: ; 330: ;must now delay before reading in SPI data on MISO 331: ; 332: set_delay temp,4 333: time_lo: 334: inc_delay temp 335: 00003C F3F0 brcs time_lo 336: ; 337: 00003D 991C sbic pinb,miso ;after delay, read in SPI bit & put into D0 338: 00003E 9553 inc spi_byte ;we FORCED D0=0, so use INC to set D0. 339: ; 340: 00003F 951A dec temp 341: 000040 F771 brne spi_loop 342: 000041 9508 ret 343: 344: wait_until_flash_ready: 345: enable_flash 346: write_opcode STATUS_REGISTER_READ 347: wait_until_flash_ready_loop: 348: 000045 DFD8 rcall read_spi 349: 000046 FF57 sbrs spi_byte, FLASH_BUSY 350: 000047 CFFD rjmp wait_until_flash_ready_loop 351: disable_flash 352: 000049 9508 ret 353: 354: 355: ; 356: ; Put flash pointer to 0 357: ; 358: write_test: 359: reset_page_count 360: write_pages_loop: 361: reset_buffer_count 362: 363: ;rcall wait_until_flash_ready 364: write_led_on 365: 366: enable_flash 367: write_opcode MAIN_MEMORY_PAGE_PROGRAM_THROUGH_BUFFER 368: write_flash_page_address 369: 370: ; 371: ; write 4 zeros, followed by the page address, 372: ; followed by the low byte of the page address 373: ; filling the rest of the page. 374: ; 375: 00005C E051 ldi spi_byte, 1 376: 00005D DFBC rcall write_spi ; 1 377: 00005E DFBB rcall write_spi ; 2 378: 00005F DFBA rcall write_spi ; 3 379: 000060 DFB9 rcall write_spi ; 4 380: 000061 2F56 mov spi_byte, page_count_low 381: 000062 DFB7 rcall write_spi ; 5 382: 000063 2F57 mov spi_byte, page_count_high 383: 000064 DFB5 rcall write_spi ; 6 384: 385: add_16 buffer_count_low, buffer_count_high, 6 386: 387: write_buffer_loop: ; fill rest of page 388: 000069 2F56 mov spi_byte, page_count_low 389: 00006A DFAF rcall write_spi 390: 391: debug_spi 392: 393: inc_16 buffer_count_low, buffer_count_high 394: cpi_16 buffer_count_low, buffer_count_high, BUFFER_COUNT 395: 00007C F360 brlo write_buffer_loop 396: 397: disable_flash 398: inc_16 page_count_low, page_count_high 399: cpi_16 page_count_low, page_count_high, PAGE_COUNT 400: 000085 F008 brlo write_next_page 401: 000086 F408 brsh return 402: write_next_page: 403: 000087 CFC4 rjmp write_pages_loop 404: return: 405: write_led_off 406: 000089 9508 ret 407: 408: main_memory_page_read_test: 409: read_led_on 410: reset_page_count 411: 412: main_memory_page_read_loop: 413: enable_flash 414: write_opcode MAIN_MEMORY_PAGE_READ 415: write_flash_page_address 416: write_dont_care_bytes 417: reset_buffer_count 418: mmpr_buffer_loop: 419: 0000A1 DF7C rcall read_spi 420: debug_spi ; print! 421: inc_16 buffer_count_low, buffer_count_high 422: cpi_16 buffer_count_low, buffer_count_high, BUFFER_COUNT 423: 0000B3 F368 brlo mmpr_buffer_loop 424: 425: disable_flash 426: ; reset page count if we are over PAGE_COUNT 427: inc_16 page_count_low, page_count_high 428: cpi_16 page_count_low, page_count_high, PAGE_COUNT 429: 0000BC F010 brlo mmpr_next_page 430: reset_page_count 431: mmpr_next_page: 432: 0000BF 9B4F sbis but2_pin, but2 433: 0000C0 CFCC rjmp main_memory_page_read_loop 434: 435: disable_flash 436: read_led_off 437: 0000C3 9508 ret 438: 439: continuous_read_test: 440: read_led_on 441: reset_page_count 442: reset_buffer_count 443: enable_flash 444: write_opcode CONTINUOUS_ARRAY_READ 445: write_flash_page_address 446: write_dont_care_bytes 447: 448: continuous_read_loop: 449: 0000DB DF42 rcall read_spi 450: debug_spi 451: 0000E6 9B4F sbis but2_pin, but2 452: 0000E7 CFF3 rjmp continuous_read_loop 453: 454: disable_flash 455: read_led_off 456: 0000EA 9508 ret 457: test_flash_page_address: 458: reset_page_count 459: ; bits: xxxxxx11 11111110 00000000 460: ; ^res ^^page pos^^buff pos^ 461: test_flash_page_address_loop: 462: ; Use buffer count as temp var (putchar poisons "temp") 463: 0000ED 2F86 mov buffer_count_low, page_count_low 464: 0000EE 2F97 mov buffer_count_high, page_count_high 465: 0000EF 0F88 lsl buffer_count_low ; shift left 466: 0000F0 1F99 rol buffer_count_high ; 467: 0000F1 2F49 mov txbyte, buffer_count_high ; N.B. high first 468: 0000F2 DF12 rcall putchar 469: 0000F3 2F48 mov txbyte, buffer_count_low ; then low 470: 0000F4 DF10 rcall putchar 471: inc_16 page_count_low, page_count_high 472: cpi_16 page_count_low, page_count_high, PAGE_COUNT 473: 0000FC F380 brlo test_flash_page_address_loop 474: 0000FD 9508 ret 475: 476: test_inc_16: 477: reset_page_count 478: test_inc_16_loop: 479: 000100 2F46 mov txbyte, page_count_low 480: 000101 DF03 rcall putchar 481: 000102 2F47 mov txbyte, page_count_high 482: 000103 DF01 rcall putchar 483: inc_16 page_count_low, page_count_high 484: cpi_16 page_count_low, page_count_high, PAGE_COUNT 485: 00010B F3A0 brlo test_inc_16_loop 486: 00010C 9508 ret 487: 488: ; 489: ; main program 490: ; 491: reset: 492: ; 493: ; set clock divider to /1 494: ; 495: 00010D E810 ldi temp, (1 << CLKPCE) 496: 00010E E020 ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) 497: 00010F 9310 sts CLKPR, temp 000110 0061 498: 000111 9320 sts CLKPR, temp1 000112 0061 499: ; 500: ; set stack pointer to top of RAM 501: ; 502: 000113 E014 ldi temp, high(RAMEND) 503: 000114 BF1E out SPH, temp 504: 000115 EF1F ldi temp, low(RAMEND) 505: 000116 BF1D out SPL, temp 506: ; 507: ; init pins 508: ; 509: 000117 9A51 sbi tx_ddr, tx 510: 000118 9A59 sbi tx_port, tx 511: 512: 000119 9A3D sbi led1_ddr, led1 513: 00011A 9A45 sbi led1_port, led1 514: 515: 00011B 9A55 sbi led2_ddr, led2 516: 00011C 9A5D sbi led2_port, led2 517: 518: 00011D 9856 cbi but1_ddr, but1 519: 00011E 9A5E sbi but1_port, but1 520: 521: 00011F 9857 cbi but2_ddr, but2 522: 000120 9A5F sbi but2_port, but2 523: 524: ; SPI 525: 000121 DEFE rcall init_spi 526: ; 527: ; main loop 528: ; 529: main_loop: 530: 000122 9B4E sbis but1_pin, but1 531: 000123 DF26 rcall write_test 532: 000124 9B4F sbis but2_pin, but2 533: 000125 DF9E rcall continuous_read_test 534: 000126 CFFB rjmp main_loop 535: -> Warning 001: 17 symbol(s) defined, but not used! Program : 295 words. Constants : 0 words. Total program memory: 295 words. Eeprom space : 0 bytes. Data segment : 0 bytes. Compilation completed, no errors. Compilation endet 07.12.2007, 19:48:53