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

📄 main.c

📁 Using the Blackfin Processor SPORT to Emulate a SPI Interface
💻 C
📖 第 1 页 / 共 4 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// VisualDSP++ 3.5 "Flash Programmer" flash driver for use to
// programm SPI flash/EEPROM devices.
//
// (C) Copyright 2006 - Analog Devices, Inc.  All rights reserved.
//
// Basic understanding of the VisualDSP++ 3.5 flash programmer tool, also 
// called "plug-in", is required.
//
// Note: Due to the fact that the plug-in accepts to open intel hex files only
// 		 SPI programming works just for VisualDSP++ version 3.5 and higher!
//
// 		 Ensure that the option intel hex is chosen at the register LOAD
//       under Project Options!
// 
// In general, when the flash programming tool "Tools->Flash Programmer" 
// has been opened a driver file must be loaded. Loading a driver such as this
// one causes VisualDSP++ to upload the driver dxe file to the processor,
// to set a breakpoint at the label "AFP_BreakReady" and to start the processor.
// When the processor halts at the breakpoint the control went back to the 
// flash plug-in. In the box "Load File" a loader file "*.ldr" of a project
// must be selected to program a SPI device.
//
// Note: As a standard flash needs to be erased before programming please 
//       make use of the erase options in surrounding boxes. 
//
// Pressing the button "Load File" will cause the plug-in to access the loader 
// file and to fill the buffer "AFP_Buffer" with the first portion of data.
// Also, the number of words counted in bytes as well as the SPI start address 
// will be stored in certain variables.
//
// The contents of AFP_Buffer will be written to the SPI and sequentially the 
// AFP_Buffer will be filled with the next portion of the loader file. After 
// the whole loader file has been transferred to the SPI the processor halts 
// at the breakpoint as discussed above. 
//
// 
//////////////////////////////////////////////////////////////////////////////


//--------------------------------------------------------------------------//
// Include/Header files														//
//--------------------------------------------------------------------------//
#include <sys\platform.h>
#include <sys\exception.h>
#include "Errors.h"
#include "SPI_Device_Settings.h"
#include <cdefBF537.h>
#include <stdio.h>
#include <ccblkfn.h>


//--------------------------------------------------------------------------//
// Defines																	//
//--------------------------------------------------------------------------//
#define 		asynchronous_SPORT

// Peripheral Interrupt IDs for various interrupts at SIC_IMASK
#define SPORT1_RX_PID	   			7
#define SPORT1_TX_PID	   			8	
#define SPORT1_ERR_PID				2
#define DMA_ERR_PID					1

#define SPI_ADRS_ARM_INTERRUPTS     (0x00<<8)
#define SPI_ADRS_ARM_INT_EN		    (0x04<<8)

#define SPI_ADRS_HOST_INTERRUPTS    (0x08<<8)
#define SPI_ADRS_HOST_INT_EN	    (0x0c<<8)
#define SPI_ADRS_HOST_INT_ACK	    (0x10<<8)

#define SPI_ADRS_GEN_PURP_1   	    (0x14<<8)
#define SPI_ADRS_GEN_PURP_2   	    (0x18<<8)

#define SPI_ADRS_DEV_CTRL_STAT   	(0x26<<8)    // high word

#define SPI_ADRS_DMA_DATA      	    (0x28<<8)

#define SPI_ADRS_DMA_WRITE_CTRL     (0x2c<<8)
#define SPI_ADRS_DMA_WRITE_LEN      (0x2e<<8)
#define SPI_ADRS_DMA_WRITE_BASE     (0x30<<8)

#define SPI_ADRS_DMA_READ_CTRL      (0x34<<8)
#define SPI_ADRS_DMA_READ_LEN       (0x36<<8)
#define SPI_ADRS_DMA_READ_BASE      (0x38<<8)


// Note that these defines are used by the plug-in also. Deleting these defines
// can lead to Plug-in crashs. 
#define TRUE			0x1
#define FALSE			0x0
#define BUFFER_SIZE		0x600
#define NUM_SECTORS		4
#define SECTORBASE		0

typedef unsigned char 	u8;
typedef unsigned short 	u16;
typedef unsigned int 	u32;

typedef struct DMA_1D_Array_Desc 
{
	u16	START_ADDR_L;
	u16	START_ADDR_H;
    u16 CONFIG;
    u16	X_CNT;
    u16	X_MOD;
} DMA_1D_Array_Desc_t;

typedef struct sm_sport_desc						// struct holding descriptors for a sport_read
{
	DMA_1D_Array_Desc_t MOSI_regs_addr;				// MOSI writes one 16-bit target register address 
	DMA_1D_Array_Desc_t MOSI_regs_value;			// MOSI writing register value (or dummy write in case of sm_sport_read)
	DMA_1D_Array_Desc_t MOSI_regs_value2;			// MOSI writing register value2 (or dummy write in case of sm_sport_read)	
	DMA_1D_Array_Desc_t MISO_regs_addr;				// MISO desc when MOSI writes 16-bit target reg addr (always dummy read)
	DMA_1D_Array_Desc_t MISO_regs_value;			// MISO reads register value (or dummy read in case of sm_sport_write)
	u16 dummy_read;									// place holder for dummy_read data
	u16 dummy_write;								// place holder for dummy_write data
}sm_sport_desc_t;


// For the purpose of erase single sectors of the SPI flash the right sector
// must be chosen. This structure will be taken by the plug-in to display memory space.
typedef struct _SECTORLOCATION
{
	long lStartOff;
	long lEndOff;
	
}SECTORLOCATION;

// Flash Programmer commands
// The VisualDSP++ flash progammer plug-in "Flash Programmer Tool" will send commands
// to this driver. These commands will be taken to execute the corresponding C function
// The commands are used at the switch case below.
// Note: As the commands are used by the plug-in deleting or changing can lead to misfuction.
typedef enum
{
	NO_COMMAND,		// 0
	GET_CODES,		// 1
	RESET,			// 2
	WRITE,			// 3
	FILL,			// 4
	ERASE_ALL,		// 5
	ERASE_SECT,		// 6
	READ,			// 7
	GET_SECTNUM,	// 8
}enProgCmds;

//--------------------------------------------------------------------------//
// Variables																//
//--------------------------------------------------------------------------//
sm_sport_desc_t sm_sport_write_8bits_desc, sm_sport_read_multiple_8bits_desc;
sm_sport_desc_t spi_wren_desc, spi_se_desc, sm_sport_read_8bits_desc;

//--------------------------------------------------------------------------//
// Prototypes																//
//--------------------------------------------------------------------------//
EX_INTERRUPT_HANDLER(SPORT1_ISR);
EX_INTERRUPT_HANDLER(HW_ERR_ISR);
EX_INTERRUPT_HANDLER(SYS_ERR_ISR);
EX_INTERRUPT_HANDLER(EXCEP_ISR);
void Init_PLL(void);	
ERROR_CODE EraseFlash(void);
ERROR_CODE GetCodes(void);
ERROR_CODE ResetFlash(void);
ERROR_CODE WriteData(unsigned long ulStart, long lCount, long lStride, int *pnData);
ERROR_CODE ReadData(unsigned long ulStart, long lCount, long lStride, int *pnData);
ERROR_CODE EraseBlock(int nBlock);
ERROR_CODE FillData( unsigned long ulStart, long lCount, long lStride, int *pnData );
ERROR_CODE WriteFlash (unsigned long ulStartAddr, long lTransferCount, long lModify, int *iDataSource, long *lWriteCount);
ERROR_CODE Wait_For_Status(char Statusbit);
ERROR_CODE GetSectorNumber( unsigned long ulOffset, int *pnSector );
ERROR_CODE Wait_For_nStatus(void);
void Init_Descriptors(void);
void Init_SPORT(void);
char ReadStatusRegister(void);
void SendSingleCommand(u8 addr);
void SectorErase(u8 opcode, u8 *addr);
int  sm_spi_read_8bits(u8 addr, u8 *data, u32 len);
void sm_spi_write_8bits(u8 addr, u8 *data, u8 *dataout, u32 len, u32 modify);
void sm_spi_read_multiple_8bits(u8 opcode, u8 *addr, u8 *datain, u32 len); 




// Global data for use with the VisualDSP++ plug-in
// The plug-in will modify some AFP variables to control this driver
char 			*AFP_Title = "ADSP-BF537 EZ-KIT Lite";	// This title will be displayed in the plug-in
char 			*AFP_Description = SPI_Description;		// The description will also be displayed in the plug-in. See the file "SPI_Device_Settings.h".
enProgCmds 		AFP_Command = NO_COMMAND;				// AFP_Command is dedicated to control program flow. Look at the switch case below.
int 			AFP_ManCode = 0x0;						// Some devices have Manufacturer codes to autodetect the device
int 			AFP_DevCode = 0x0;						// Some devices have device codes to autodetect the device
unsigned long 	AFP_Offset = 0;							// AFP_Offset holds the start address to the SPI device
int 			i, *AFP_Buffer;							// The plug-in copies the content of the *.ldr file to the buffer in small portions
long 			AFP_Size = BUFFER_SIZE;					// The AFP_Buffer size can be modified.
long 			AFP_Count = -1;							// The plug-in copies the number of transfers to be executed to the AFP_Count 
long 			AFP_Stride = -1;						// For the plug-in "Fill" function a stride can optionally be inserted
int 			AFP_NumSectors = 0;						// The number of SPI sectors are given for sector erase function
long 			AFP_SectorSize = 0;						// The multiplier factor from sector to sector must be given
int 			AFP_Sector = -1;						// In case of sector erase the right sector must be chosen and hold in here
int 			AFP_Error = 0;							// contains last error encountered
bool 			AFP_Verify = FALSE;						// verify writes or not
long 			AFP_StartOff = 0x0;						// sector start offset
long 			AFP_EndOff = 0x0;						// sector end offset
int				AFP_FlashWidth = 0x8;					// width of the flash device taken
int 			*AFP_SectorInfo;
SECTORLOCATION SectorInfo[NUM_SECTORS];


// exit flag
bool bExit = FALSE;

//--------------------------------------------------------------------------//
// Function:	main														//
//																			//
// Parameters:	None														//
//																			//
// Return:		None														//
//																			//
// Description:	main routine												//
//--------------------------------------------------------------------------//
main()
{
 	int i = 0;
 	
	// By making AFP_Buffer as big as possible the plug-in can send and
	// receive more data at a time making the data transfer quicker.
	//
	// By allocating it on the heap the compiler does not create an
	// initialized array therefore making the driver image smaller
	// and faster to load.
	//
	// We have modified the linker description file (LDF) so that the heap
	// is large enough to store BUFFER_SIZE elements at this point
	
	// The AFP_Buffer gets filled by the programmer plug-in. The data the plug-in fetches
	// from the *.ldr file will be stored in the AFP_Buffer byte wise to avoid gaps in the buffer.
	// The verify command uses the buffer to store the data read from the SPI flash for comparison.
	// The fill command uses the first address of the buffer to hold the value to be filled.
	
	// -In case of loading the code to the SPI flash the plug-in will fill the buffer automatically 
	//  so that this driver just has to fetch the data from the buffer and transfer it to the SPI flash.
	// -In case of reading the data from the SPI flash (plug-in command "VERIFY") this driver just has 
	//  to fetch the data from the SPI flash and store it in the buffer.


	Init_PLL();		
	GetCodes();		// Instead of getting manufacturer codes this driver does organize the 

	
	AFP_Buffer = (int *)malloc(BUFFER_SIZE);
                	// memory stucture "sectors" in the function GetCodes().
	
	// AFP_Buffer will be NULL if we could not allocate storage for the
	// buffer
	if ( AFP_Buffer == NULL )
	{
		// tell GUI that our buffer was not initialized
		AFP_Error = BUFFER_IS_NULL;
	}
	
	Init_Descriptors();
	Init_SPORT();
	
	AFP_SectorInfo = (int*)&SectorInfo[0];	//Points to the beginnig of the sector table.

	// The while loop below is inserted to give the programmer plug-in control over this driver

	// The plug-in will set a breakpoint at "AFP_BreakReady" forcing the processor to halt.
	// After the plug-in starts the processor again the function which is selected by AFP_Command will be executed.
	// After execution the function the processor halts again at the breadpoint at "AFP_BreakReady".
	// Now the plug-in can place the next command in AFP_Command and start the processor again. 
		
	while ( !bExit )
	{
		asm("AFP_BreakReady:");	// After loading the driver to the processor it halt at this point.
				
		if ( FALSE )
			asm("jump AFP_BreakReady;");

		// switch on the command
 		switch ( AFP_Command )
		{
			//In this driver GetCodes does create the sector table
			case GET_CODES:
				AFP_Error = GetCodes();
				break;

			// The plug-in offers to reset the flash. This function will send a "write disable command to the SPI flash.
			//  Additionally, it checks the status register for the write enable bit "WEL" to be cleared.
			case RESET:
				AFP_Error = ResetFlash();
				break;

			// By taking the parameters the function "WriteData" will program the flash.
			// AFP_Offset points to the SPI destination address, AFP_Count holds the number of transfers to execute.
			// AFP_Stride holds the address increment and finally AFP_Buffer points to the source buffer.
			case WRITE:
				AFP_Error = WriteData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

			// As the programmer plug-in allows to simply fill the SPI flash with any value the 
			// "FILL" function includes the code. The AFP_Offset points to the destination while the AFP_Count 
			// holds the number of locations where the value will be placed. AFP_Stride holds the increment
			// while AFP_Buffer points to the memory source.
			case FILL:
				AFP_Error = FillData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

			// Pushing the "Erase" button on the programmer plug-in the driver executes an erase all command.
			case ERASE_ALL:
		#ifdef	SPI_FLASH	//just flashs can be erased!
				AFP_Error = EraseFlash();
		#endif
				break;

			// Pushing the "Erase Sectors" button on the programmer plug-in makes the driver to take the value from
			// AFP_Sector and sends the erase sector command followed by the start address of the dedicated sector.
			// The AFP_Sector gets filled by running the function GET_SECTNUM driven by the plug-in

			case ERASE_SECT:
		#ifdef	SPI_FLASH	//just flashs can be erased!
				AFP_Error = EraseBlock( AFP_Sector );
		#endif
				break;

			// In order to verify the data that has been programmed to the flash the data must been read.
			// This function will be entered when pushing the Verify button.
			case READ:
				AFP_Error = ReadData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

⌨️ 快捷键说明

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