AT91SAM7X256操作外部Flash
首先要设置相关的管脚信号:MISO,MOSI,SPCK以及片选信号NPCS(CS0) void InitSpiBus_MsIO(void) 然后使用下面几个函数操作: ?void BufferWrite(UINT16 buffer_addr,BYTE *target,UINT16 size,CS_NO cs_no); 其中BufferWrite是对SDRAM写入,所以掉电后不能保存BufferWrite设置的值。 具体可以参考:AT91SAM7S64 驱动 AT45DB321D DataFlash的程序 使用模拟SPI总线完成-?http://www.pudn.com/downloads263/sourcecode/embed/detail1209624.html 下面是实现函数: //#include<AT91SAM7S64.H> #include "..headerAT91SAM7X256.h" #ifndef __MACRO_H__ #include"macro.h" #endif? #include"spi.h" #ifndef __AT45DB321D_MACRO_H__ #include"AT45DB321D_MACRO.H" #endif #define DONT_CARE_ADDR 0x00 typedef enum _PAGE_SIZE_TYPE { STANDARD_PAGE_SIZE=0,BINARY_PAGE_SIZE=1 }PAGE_SIZE_TYPE; #define BUFFER_SIZE ? 528 BYTE DB321_buf[528]={0}; BYTE ReadStateRegister() { BYTE state=0,busy; CLR_CS0; //拉低片选信号 SpiSendByte(0xD7);//? state = SpiReadByte(); state = SpiReadByte(); SET_CS0; #if 1 if(state&0x80) //^7=0:busy; =1:ready busy =0; else busy =1; #endif return busy; } // read manufacturer Device ID UINT32 ManufacturerDeviceRead() { UINT32 temp =0; BYTE state; while(ReadStateRegister()); CLR_CS0; //拉低片选信号 SpiSendByte(0x9F);//? state = SpiReadByte(); temp = state; state = SpiReadByte(); temp += ((UINT32)state <<8); state = SpiReadByte(); temp += ((UINT32)state <<16); state = SpiReadByte(); temp += ((UINT32)state <<24); SET_CS0; return temp; } // Write data to AT45DB321D's RAM buffer void BufferWrite(UINT16 buffer_addr,CS_NO cs_no) { while(ReadStateRegister()); CLR_CS0; //拉低片选信号 if(!cs_no)//cs_no=0 :buffer 1 ?; ?cs_no=1 :buffer 2 SpiSendByte(Buffer1_Write);// else SpiSendByte(Buffer2_Write);// //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) SpiSendByte(DONT_CARE_ADDR);// SpiSendByte((BYTE)(buffer_addr>>8)); SpiSendByte((BYTE)buffer_addr); //send size bytes data to buffer while(size--) { SpiSendByte(*target++);// } ? SET_CS0; //拉高片选信号 } // Read data from AT45DB321D's RAM buffer to target array void BufferRead(UINT16 buffer_addr,CS_NO cs_no_mode) { //FLAG ready = 0; while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send cmd opcode switch(cs_no_mode) { case 0: SpiSendByte(Buffer1_Read);break;//0xD4 case 1: SpiSendByte(Buffer2_Read);break;//0xD6 case 4: SpiSendByte(Buffer1_Read_Low_Frequency);break;//0xD1 case 5: SpiSendByte(Buffer2_Read_Low_Frequency);break;//0xD3 case 8: SpiSendByte(Legacy_Buf1_Read);break;//0x54 case 9: SpiSendByte(Legacy_Buf2_Read);break;//0x54 } //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) SpiSendByte(DONT_CARE_ADDR);// SpiSendByte((BYTE)(buffer_addr>>8)); SpiSendByte((BYTE)buffer_addr); SpiSendByte(DONT_CARE_ADDR);// //read n size bytes data to buffer while(size--) { *target++ = SpiReadByte(); } SET_CS0; //拉高片选信号 } // ?buffer data write to the AT45DB321D's main memory page void BufferToMainPageProg(UINT16 page_addr,CS_NO cs_no_mode,PAGE_SIZE_TYPE page_size_mode) { while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send cmd opcode switch(cs_no_mode) { case 0: SpiSendByte(Buf1_toMainPageProg_With_Erase);break;//0x83 case 1: SpiSendByte(Buf2_toMainPageProg_With_Erase);break;//0x86 case 8: SpiSendByte(Buf1_toMainPageProg_Without_Erase);break;//0x88 case 9: SpiSendByte(Buf2_toMainPageProg_Without_Erase);break;//0x89 } //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) if(page_size_mode == STANDARD_PAGE_SIZE) { ? SpiSendByte((BYTE)(page_addr>>6));//X.PA12-6 &(A21-A9) SpiSendByte((BYTE)(page_addr<<2));//PA5-0 .xx } else //BINARY_PAGE_SIZE=1 ?(A21-A9) { SpiSendByte((BYTE)(page_addr>>7));//XX.(A21-A16) SpiSendByte((BYTE)(page_addr<<1));//(A15-A9).X } SpiSendByte(DONT_CARE_ADDR); SET_CS0; //拉高片选信号 执行片内写操作开始 } // Data read from main memory page to buffer? void MainPageToBufferTransfer(UINT16 page_addr,PAGE_SIZE_TYPE page_size_mode) { while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send cmd opcode if(!cs_no) SpiSendByte(MainMemPageTo_Buf1_Transfer);// 0x53 else SpiSendByte(MainMemPageTo_Buf2_Transfer);// 0x55 //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) if(page_size_mode == STANDARD_PAGE_SIZE) { ? SpiSendByte((BYTE)(page_addr>>6));//X.PA12-6 &(A21-A9) SpiSendByte((BYTE)(page_addr<<2));//PA5-0 .xx } else //BINARY_PAGE_SIZE=1 ?(A21-A9) { SpiSendByte((BYTE)(page_addr>>7));//XX.(A21-A16) SpiSendByte((BYTE)(page_addr<<1));//(A15-A9).X } SpiSendByte(DONT_CARE_ADDR); SET_CS0; //拉高片选信号 执行片内写操作开始 } /* Program flash(AT45DB) through buffer ? ?need buffer_addr and page_addr ?*/ void MainPageProgThroughBuffer(UINT16 page_addr,PAGE_SIZE_TYPE page_size_mode) { BYTE temp_addr; while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send 1 byte cmd opcode if(!cs_no)//cs_no=0 :buffer 1 ?; ?cs_no=1 :buffer 2 SpiSendByte(MainPageProg_Through_Buf1);// 0x82 else SpiSendByte(MainPageProg_Through_Buf2);// 0x85 //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(page_addr>>6)); //X.PA12-6 &(A21-A9) temp_addr = (BYTE)( (page_addr<<2)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //PA5-0 .BA9-BA8 SpiSendByte((BYTE)buffer_addr); //BA7-BA0 } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(page_addr>>7)); //XX.(A21-A16) temp_addr = (BYTE)( (page_addr<<1)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //(A15-A9).A8 SpiSendByte((BYTE)buffer_addr); //(A7-A0) } //send size bytes data to buffer while(size--) { SpiSendByte(*target++); } SET_CS0; //拉高片选信号 start inself-time program? } /* Main Memory page read to use array ? ?可选择 page中的地址 不必从addr=0 开始读,超过end_page_addr 则回绕到该页的起始地址开始继续读操作 ? ?主存储器页读绕过这两个数据缓冲器和叶缓冲区的内容不变。 ?*/ void MainPageRead(UINT16 page_addr,PAGE_SIZE_TYPE page_size_mode) { BYTE temp_addr,i; while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send 1 byte cmd opcode SpiSendByte(Main_Memory_Page_Read); // 0xD2 //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(page_addr>>6)); //X.PA12-6 &(A21-A9) temp_addr = (BYTE)( (page_addr<<2)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //PA5-0 .BA9-BA8 SpiSendByte((BYTE)buffer_addr); //BA7-BA0 } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(page_addr>>7)); //XX.(A21-A16) temp_addr = (BYTE)( (page_addr<<1)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //(A15-A9).A8 SpiSendByte((BYTE)buffer_addr); //(A7-A0) } //send 4 bytes don't care addr for(i=0;i<4;i++) SpiSendByte(DONT_CARE_ADDR); //read n size bytes data to buffer while(size--) { *target++ = SpiReadByte(); } SET_CS0; //拉高片选信号 } // continuous Array read 可以读多个连续的page -------------------------------------------// void ArrayRead(UINT16 page_addr,PAGE_SIZE_TYPE page_size_mode) { ? ? BYTE temp_addr,i; while(ReadStateRegister()); CLR_CS0; //拉低片选信号 //send 1 byte cmd opcode switch(cs_no_mode) { case 0:SpiSendByte(ARRAY_READ);break; case 1:SpiSendByte(Low_Frequency_Array_Read);break; case 2:SpiSendByte(High_Frequency_Array_Read);break; case 5:SpiSendByte(Legacy_Array_Read);break; ?//没有时序图 } //send 3 bytes buffer addr (512:15don't care bit ?528:14don't care bit) if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(page_addr>>6)); //X.PA12-6 &(A21-A9) temp_addr = (BYTE)( (page_addr<<2)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //PA5-0 .BA9-BA8 SpiSendByte((BYTE)buffer_addr); //BA7-BA0 } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(page_addr>>7)); //XX.(A21-A16) temp_addr = (BYTE)( (page_addr<<1)|(buffer_addr>>8) ); SpiSendByte(temp_addr); //(A15-A9).A8 SpiSendByte((BYTE)buffer_addr); //(A7-A0) } //send n bytes don't care addr (n<=4) switch(cs_no_mode) { case 0:for(i=0;i<4;i++) SpiSendByte(DONT_CARE_ADDR);break; case 1:break; case 2:SpiSendByte(DONT_CARE_ADDR);break; case 5:break; //没有时序图 } //read n size bytes data to buffer while(size--) { *target++ = SpiReadByte(); } SET_CS0; //拉高片选信号 结束 Array Read } //------------------------------------------------------------------------// void DeepPowerDown(void) { while(ReadStateRegister()); CLR_CS0; //拉低片选信号 SpiSendByte(DEEP_POWER_DOWN); SET_CS0; //拉高片选信号 } void ResumeFromDeepPowerDown(void) { ? ? while(ReadStateRegister()); CLR_CS0; //拉低片选信号 SpiSendByte(Resume_From_DeepPowerDown); SET_CS0; //拉高片选信号 } /* 对“2的幂”页面大小是一个一次性可编程(OTP)寄存器,一旦设备被配置为“2的幂”页面大小,不能再重新配置。 */? void PowerofTwoPageSize(void) //建议不修改原有FLash存储结构,1但修改为512Bytes/page 则不能重新配置 { ? ? while(ReadStateRegister()); ? ? CLR_CS0; //拉低片选信号 0x3D,0x2A,0x80,0xA6? SpiSendByte(0x3D); SpiSendByte(0x2A); SpiSendByte(0x80); SpiSendByte(0xA6); SET_CS0; //拉高片选信号 } // page erase operation void PageErase(UINT16 page_addr,PAGE_SIZE_TYPE page_size_mode) { ? while(ReadStateRegister()); ? CLR_CS0; //拉低片选信号? SpiSendByte(PAGE_ERASE); if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(page_addr>>6)); //X.PA12-6 &(A21-A9) SpiSendByte((BYTE)(page_addr<<2)); //PA5-0 .BA9-BA8 } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(page_addr>>7)); //XX.(A21-A16) SpiSendByte((BYTE)(page_addr<<1)); //(A15-A9).A8 } SpiSendByte(DONT_CARE_ADDR);// SET_CS0; //拉高片选信号 } //Block Erase 8 page per block total:1024 blocks void BlockErase(UINT16 block_addr,PAGE_SIZE_TYPE page_size_mode) { ? while(ReadStateRegister()); CLR_CS0; //拉低片选信号? //send 1 byte cmd opcode SpiSendByte(BLOCK_ERASE); if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(block_addr>>3)); //X.PA12-6? SpiSendByte((BYTE)(block_addr<<5)); //PA5-3 .xxxxx } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(block_addr>>4)); //XX.(A21-A16) SpiSendByte((BYTE)(block_addr<<4)); //(A15-A12).xxxx } SpiSendByte(DONT_CARE_ADDR);// SET_CS0; //拉高片选信号 } //Sector Erase 16 block per sector ?total:64 sectors void SectorErase(UINT16 sector_addr,PAGE_SIZE_TYPE page_size_mode) { ? while(ReadStateRegister()); CLR_CS0; //拉低片选信号? //send 1 byte cmd opcode SpiSendByte(BLOCK_ERASE); if(page_size_mode == STANDARD_PAGE_SIZE)//528 bytes per page { ? SpiSendByte((BYTE)(sector_addr>>3)); //X.PA12-9? SpiSendByte(DONT_CARE_ADDR);// SpiSendByte(DONT_CARE_ADDR);// } else //BINARY_PAGE_SIZE=1 ? //512 bytes per page { SpiSendByte((BYTE)(sector_addr>>4)); SpiSendByte((BYTE)(sector_addr<<4)); SpiSendByte(DONT_CARE_ADDR);// } SET_CS0; //拉高片选信号 内部擦出开始 } // chip earse void ChipErase(void) { while(ReadStateRegister()); CLR_CS0; //拉低片选信号 0xC7,0x94,0x9A SpiSendByte(0xC7);// SpiSendByte(0x94);// SpiSendByte(0x80);// SpiSendByte(0x9A);// SET_CS0; //拉高片选信号 内部擦出开始 }(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |