⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spiflash.asm

📁 ADI 公司的DSP ADSP21262 EZ-KIT LITE开发板的全部源代码
💻 ASM
字号:
///////////////////////////////////////////////////////////////////////////////////////
//NAME:     SPIflash.asm (ATMEL SPI Flash)
//DATE:     4/23/04
//PURPOSE:  Program the SPI Flash for the ADSP-21262 Ezkit
//
//USAGE:    This file contains the subroutines used to program and verify the SPI Flash
//
////////////////////////////////////////////////////////////////////////////////////////
#include "SPIflash.h"

.global write_enable;
.global write_disable;
.global read_status_register;
.global write_status_register;
.global read_data_bytes;
.global page_program;
.global flash_program;
.global sector_erase;
.global chip_erase;
.global read_device_id;
.global setup_spi;
.global setup_spi_dma;
.global wait_for_SPIF;
.global wait_for_WIP;
.global bit_reverse_command;

.extern flash_curr_page;
.extern sector_base_addr;
.extern read_base_addr;
.extern read_buffer_addr;
.extern read_buffer_length;
.extern write_buffer_addr;
.extern write_base_addr;
.extern write_buffer_length;
.extern file_data;
.extern file_data_verf;
.extern flash_data_out;
.extern flash_data_out.end;
.extern flash_data_verf;
.extern spi_setting;
.extern spi_dma_setting;
.extern status_register;
.extern electronic_signature;
.extern curr_command;
.extern verf_errors;
.extern error_shift;

.section/pm seg_pmco;
//----------------------------------------
//WRITE ENABLE SUBROUTINE (1 Byte)
//Enables the Write Enable Latch of the Flash
//Inputs - none
//Outputs- none
//Core sends the command
write_enable:
	r0=COMMON_SPI_SETTINGS|TIMOD1|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=SPI_WREN;    // Write Enable Command
	dm(TXSPI)=r0;

	call wait_for_SPIF;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end1) until lce;
	_loop_end1:
	nop;

write_enable.end: rts;

//----------------------------------------
//WRITE DISABLE SUBROUTINE (1 Byte)
//Disables the Write Enable Latch of the Flash
//Inputs - none
//Outputs- none
//Core sends the command
write_disable:
	r0=COMMON_SPI_SETTINGS|TIMOD1|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=SPI_WRDI;    // Write Disable Command
	dm(TXSPI)=r0;

	call wait_for_SPIF;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end2) until lce;
	_loop_end2:
	nop;

write_disable.end: rts;

//----------------------------------------
//READ STATUS REGISTER SUBROUTINE (2 Bytes)
//Returns the 8-bit value of the status register.
//Inputs - none
//Outputs- second location of status_register[2],
//         first location is garbage.
//Core sends the command
read_status_register:
	r0=COMMON_SPI_SETTINGS|TIMOD2|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=SPI_RDSR;    //Read Status Register command
	dm(TXSPI)=r0;

	r0=2;
	dm(CSPI)=r0;
	r0=status_register;
	dm(IISPI)=r0;
	r0=1;
	dm(IMSPI)=r0;
	r0=COMMON_SPI_DMA_SETTINGS|SPIRCV;
	dm(spi_dma_setting)=r0;

	call setup_spi_dma;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end3) until lce;
	_loop_end3:
	nop;

read_status_register.end: rts;

//----------------------------------------
//WRITE STATUS REGISTER SUBROUTINE (2 Bytes)
//Writes 8-bit value of the status register.
//Inputs - second location of status_register[2]
//         first location will be corrupted.
//Outputs- none
//1st word of DMA buffer is the command
write_status_register:
	call write_enable;

	r0=COMMON_SPI_SETTINGS|TIMOD2|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=SPI_WRSR;
	dm(status_register)=r0;

	r0=2;
	dm(CSPI)=r0;
	r0=status_register;
	dm(IISPI)=r0;
	r0=1;
	dm(IMSPI)=r0;
	r0=COMMON_SPI_DMA_SETTINGS;
	dm(spi_dma_setting)=r0;

	call setup_spi_dma;
	call wait_for_SPIF;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end4) until lce;
	_loop_end4:
	nop;

	call wait_for_WIP;

	//Read back the register
	call read_status_register;

write_status_register.end: rts;

//----------------------------------------
//READ DATA BYTES SUBROUTINE (read_buffer_length 32-bit words)
//Reads the specified number of words from the Flash.
//Inputs - read_base_addr - Starting Flash address
//       - read_buffer_addr - Address of buffer to write
//       - read_buffer_length - Number of 32-bit words to read
//         plus one
//Outputs- Buffer specified by read_buffer_addr will be updated
//         by the specified number of words plus one. The first
//         32-bit word in the buffer is not valid
//Core sends the command
read_data_bytes:
	r0=SPI_READ;
	dm(curr_command)=r0;
	r0=COMMON_SPI_SETTINGS|TIMOD2|WL32;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=dm(read_base_addr);
	dm(flash_curr_page)=r0;

	call bit_reverse_command;
	r0=dm(curr_command);
	dm(TXSPI)=r0;

	r0=dm(read_buffer_length);
	dm(CSPI)=r0;
	r0=dm(read_buffer_addr);
	dm(IISPI)=r0;
	r0=1;
	dm(IMSPI)=r0;
	r0=COMMON_SPI_DMA_SETTINGS|SPIRCV;
	dm(spi_dma_setting)=r0;

	call setup_spi_dma;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end5) until lce;
	_loop_end5:
	nop;

read_data_bytes.end: rts;

//----------------------------------------
//PAGE PROGRAM SUBROUTINE (write_buffer_length 32-bit words)
//Reads the specified number of words from the Flash.
//Inputs - write_base_addr - Starting Flash address
//       - write_buffer_addr - Address of buffer to read
//       - write_buffer_length - Number of 32-bit words to write
//Outputs- verf_errors - number of errors detected
//1st word of DMA buffer is the command
page_program:
flash_program:
	bit set mode1 CBUFEN;
	b5=dm(write_buffer_addr);
	l5=dm(write_buffer_length);
	r14=dm(write_buffer_length);

	r0=dm(write_base_addr);
	dm(flash_curr_page)=r0;
	
page_write:
	call write_enable;

//Page is PAGE_LENGTH bytes, only 1 page can be programmed
//per command. This loop breaks the data into pages for transmission.
//Set up the page pointers
get_page:
	b6=flash_data_out+1;
	m5=1;
	l6=PAGE_LENGTH;

	r0=PAGE_LENGTH;
	r0=r14-r0;
	if lt l6=r14;

	//Get the page data into a separate buffer
	lcntr = l6, do get_page.end until lce;
	r0=dm(i5,m5);
get_page.end: dm(i6,m5)=r0;

spi_setup:
	r0=COMMON_SPI_SETTINGS|TIMOD1|WL32;
	dm(spi_setting)=r0;
	call setup_spi;

	//Concatentate the write command and 24-bit flash address into 1 32-bit
	//word and bit reverse it. (Since the ADSP-2126x must boot in LSBF mode.)
	r0=SPI_PP;
	dm(curr_command)=r0;
	call bit_reverse_command;
	r0=dm(curr_command);
	dm(flash_data_out)=r0;

	//Determine if this is the last page and is shorter than PAGE_LENGTH
	r13=PAGE_LENGTH;
	r14=r14-r13;
	if GE jump start_transfer;
	//only send remaining number of bytes
	r13=r14+r13;

	//Send an entire page, or if this is the last page
	//only send remaining words.
start_transfer:
	//Send out write command and address
	r13=r13+1;
	b3=flash_data_out;
	l3=0;
	m3=1;
	//Send PAGE_LENGTH+2 words to account for read command and extra word to avoid
	//bit error problems seen in Atmel flashes.
	r13=r13+1;
	lcntr=r13, do writing until lce;
		r0=dm(i3,m3);
		dm(TXSPI)=r0;

		//Pause before continuing
		lcntr=1000, do (pc,_loop_end6) until lce;
		_loop_end6:
		nop;

	writing: call wait_for_SPIF;

	//Set r13 to contain the real amount of page data sent.
	r13=r13-1;
	r13=r13-1;

	ustat1=dm(SPISTAT);
	bit tst ustat1 TXS;
	if tf jump (pc,-2);

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	//Pause before continuing
	lcntr=1000, do (pc,_loop_end7) until lce;
	_loop_end7:
	nop;

	call wait_for_WIP;

	//Wait 5 ms for part to be available in all cases.
	//1000000 cycles @ 200 MHz
	lcntr=1000000; do (pc,_loop_end8) until lce;
	_loop_end8:
	nop;

	//Read back the page just programmed for verification
	r0=dm(flash_curr_page);
	dm(read_base_addr)=r0;
	r0=flash_data_verf;
	dm(read_buffer_addr)=r0;
	r0=@flash_data_verf;
	dm(read_buffer_length)=r0;
	call read_data_bytes;

	//Set up the pointers
	//The first location in each of the buffers corresponds to the command and
	//24-bit address.
	b1=flash_data_out+1;
	b2=flash_data_verf+1;
	m1=1;
	l1=PAGE_LENGTH;
	l2=PAGE_LENGTH;

error_check:
	lcntr=r13, do error_check.end until lce;
		r0=dm(i1,m1);
		r1=dm(i2,m1);
		comp(r0,r1);
		if eq jump error_check.end;
		r0=dm(verf_errors);
		r0=r0+1;
		dm(verf_errors)=r0;
error_check.end: nop;

	//Update the page address
	r1=PAGE_LENGTH*4;
	r0=dm(flash_curr_page);
	r0=r0+r1;
	dm(flash_curr_page)=r0;

	//If r14 < 0, no more data
	r14 = pass r14;
	if gt jump page_write;

page_write.end:
flash_program.end:
page_program.end: rts;

//----------------------------------------
//SECTOR ERASE SUBROUTINE (4 Bytes)
//Erases the sector of the Flash corresponding to the specified address..
//Inputs - sector_base_addr - Starting 24-bit Flash address
//Outputs- none
//Core sends the command
sector_erase:
	call write_enable;

	r0=COMMON_SPI_SETTINGS|TIMOD1|WL32;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=dm(sector_base_addr);
	dm(flash_curr_page)=r0;

	r0=SPI_SE;
	dm(curr_command)=r0;
	call bit_reverse_command;
	r0=dm(curr_command);
	dm(TXSPI)=r0;

	call wait_for_SPIF;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	lcntr=1000, do (pc,_loop_end9) until lce;
	_loop_end9:
	nop;

	call wait_for_WIP;

sector_erase.end: rts;

//----------------------------------------
//CHIP ERASE SUBROUTINE (1 Byte)
//Erases the entire Flash
//Inputs - none
//Outputs- none
//Core sends the command
chip_erase:
	call write_enable;

	r0=COMMON_SPI_SETTINGS|TIMOD1|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r3=SPI_CE;
	dm(TXSPI)=r3;

	call wait_for_SPIF;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	lcntr=1000, do (pc,_loop_end10) until lce;
	_loop_end10:
	nop;

	call wait_for_WIP;

chip_erase.end: rts;

//----------------------------------------
//READ DEVICE ID SUBROUTINE (2 Bytes)
//Returns the electronic signature of the Flash
//Inputs - none
//Outputs- Second location is Electronic_signature
//         First locations is garbage
//Core sends the command
read_device_id:
	r0=COMMON_SPI_SETTINGS|TIMOD2|WL8|MSBF;
	dm(spi_setting)=r0;
	call setup_spi;

	r0=3;
	dm(CSPI)=r0;
	r0=electronic_signature;
	dm(IISPI)=r0;
	r0=1;
	dm(IMSPI)=r0;
	r0=COMMON_SPI_DMA_SETTINGS|SPIRCV;
	dm(spi_dma_setting)=r0;

	r0=SPI_RDID;
	dm(TXSPI)=r0;

	call setup_spi_dma;

	dm(SPICTL)=r15; //Disable SPI
	dm(SPIFLG)=r15;
	dm(SPIBAUD)=r15;

	lcntr=1000, do (pc,_loop_end11) until lce;
	_loop_end11:
	nop;

read_device_id.end: rts;

//----------------------------------------
//SETUP SPI SUBROUTINE (1 Byte)
//Sets up the SPI for mode specified in spi_setting
//Inputs - spi_setting
//Outputs- none
setup_spi:

	r0=0xFE01;
	dm(SPIFLG)=r0;

	r0=BAUD_RATE_DIVISOR;
	dm(SPIBAUD)=r0;

	r0=dm(spi_setting);
	dm(SPICTL)=r0;

setup_spi.end: rts;

//----------------------------------------
//WAIT FOR SPIF SUBROUTINE (1 Byte)
//Polls the SPIF (SPI single word transfer complete) bit
//of SPISTAT until the transfer is complete.
//Inputs - none
//Outputs- none
wait_for_SPIF:
	ustat1=dm(SPISTAT);
	bit tst ustat1 SPIF;
	if not tf jump (pc,-2);
wait_for_SPIF.end: rts;

//----------------------------------------
//SETUP SPI DMA SUBROUTINE (1 Byte)
//Sets up the SPI DMA for mode specified in spi_dma_setting
//Inputs - spi_dma_setting
//Outputs- none

setup_spi_dma:

	ustat1=dm(spi_dma_setting);
	dm(SPIDMAC)=ustat1;
	//Wait for SPI DMA to complete using polling------
	ustat1=dm(SPIDMAC);
	bit tst ustat1 SPIDMAS; // Check SPI DMA Status bit
	IF TF jump (pc,-2);     // SPIDMAS = 1 when DMA in progress

	//Disable DMA
	dm(SPIDMAC)=r15;
setup_spi_dma.end: rts;

//----------------------------------------
//BIT REVERSE COMMAND SUBROUTINE (1 Byte)
//For booting the SHARC EX requires that the data in the Flash
//be sent LSB first, but all PROM/FLASH devices are MSB first
//so the data must be programmed into the Flash LSBF, but the
//command word for the flash must be bit reversed for the Flash
//to recognize the command in LSBF mode.
//Inputs - curr_command - current command to send
//       - flash_curr_page - address of the page to access
//Outputs- curr_command
bit_reverse_command:
	i7=dm(curr_command);
	bitrev(i7,0);
	r0=i7;
	r0=rot r0 by -24;
	i7=dm(flash_curr_page);
	bitrev(i7,0);
	r1=i7;
	r2=BITREV_ADDRESS_MASK;
	r1=r1 and r2;
	r0=r0 or r1;
	dm(curr_command)=r0;
bit_reverse_command.end: rts;

//----------------------------------------
//WAIT FOR WIP SUBROUTINE (1 Byte)
//Polls the WIP (Write In Progress) bit of the Flash's status
//register until the Flash is finished with its access. Accesses
//that are affected by a latency are Page_Program, Sector_Erase,
//and Block_Erase.
//Inputs - none
//Outputs- none
wait_for_WIP:
	call read_status_register;

	ustat1=dm(status_register+1);
	bit tst ustat1 WIP;
	if not tf jump wait_for_WIP.end;

	lcntr=1000, do (pc,_loop_end12) until lce;
	_loop_end12:
	nop;
	jump wait_for_WIP;

wait_for_WIP.end: rts;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -