/********************************************************************************
*
* $Workfile: TCC_M25P80.c $
*
* Copyright (C) 2012-2013 All Rights Reserved.
*
* Function: SPI initialize.
*
* Language: C
*
* $Revision: A1 $
*
* $Author: Gongming Song $
*
* $Log: $
*
*******************************************************************************/
#include "TCC_M25P80.h"
extern u32 currentAddress;
#define ADDRESS_STORAGE_LOCATION 0x0000
u8 addressBuffer[4];
#define M25P80_CS0() GPIO_ResetBits(GPIOA,GPIO_Pin_7)
#define M25P80_CS1() GPIO_SetBits(GPIOA,GPIO_Pin_7)
void MP25P80_GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
// ??GPIOB?GPIOA??
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE);
// ??PB13?PB14?PB15?SPI2????
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // SCK
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); // MISO
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // MOSI
// ??SPI??
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// ??PA7?CS??
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_7); // ???????
}
void SPI_Configuration() {
SPI_InitTypeDef SPI_InitStructure;
// ??SPI2??
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
// ??SPI2??
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // ???????
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // ????????????
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // ????CS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE); // ??SPI2
}
void M25P80_INIT(void)
{
// u8 addressBuffer[4];
MP25P80_GPIO_Config();
SPI_Configuration();
M25P80_Read_Bytes(ADDRESS_STORAGE_LOCATION, addressBuffer, 4);
// currentAddress = (addressBuffer[0] << 24) | (addressBuffer[1] << 16) | (addressBuffer[2] << 8) | addressBuffer[3];
if (currentAddress == 0) {
currentAddress = 0x0010;
}
// SPI_InitTypeDef SPI_InitStructure;
// GPIO_InitTypeDef GPIO_InitStructure;
// /* ??GPIO?SPI?? */
// FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );
// FLASH_SPI_SCK_APBxClock_FUN ( FLASH_SPI_SCK_CLK, ENABLE );
// FLASH_SPI_MISO_APBxClock_FUN ( FLASH_SPI_MISO_CLK, ENABLE );
// FLASH_SPI_MOSI_APBxClock_FUN ( FLASH_SPI_MOSI_CLK, ENABLE );
// FLASH_SPI_CS_APBxClock_FUN ( FLASH_SPI_CS_CLK, ENABLE );
// /* ??SPI????:SCK ???? */
// GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
// GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);
// /* ??SPI????:MISO ?????????? */
// GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
// GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);
// /* ??SPI????:MISO ?????????? */
// GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
// GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);
// /* ??SPI????:CS ??Flash???? */
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
// GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
// GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
// /* ??????Flash,???????Flash?????? */
// FLASH_SPI_CS_DISABLE();
// SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
// SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
// SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
// SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
// SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
// SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
// SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
// SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
// SPI_InitStructure.SPI_CRCPolynomial = 7;
// SPI_Init(SPI1 , &SPI_InitStructure);
// /* ??SPI?? */
// SPI_Cmd(SPI1 , ENABLE);
// u8 addressBuffer[4];
// M25P80_Read_Bytes(ADDRESS_STORAGE_LOCATION, addressBuffer, 4);
// currentAddress = (addressBuffer[0] << 24) | (addressBuffer[1] << 16) | (addressBuffer[2] << 8) | addressBuffer[3];
// if (currentAddress == 0) {
// currentAddress = 0x0000;
// }
}
/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
* 8Mbit = 1,048,576 bytes = 16 sectors (512 Kbits, 65536 bytes each) =
* 4096 pages (256 bytes each)
* 1sector = 256 page
* address range 00000 ~ fffffh
*******************************************************************************/
u16 SPI_FLASH_SendByte(u8 byte)
{
/* Loop while DR register in not emplty */
while(SPI_I2S_GetFlagStatus(TCC_SPI, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(TCC_SPI, (uint16_t)byte);
/* Wait to receive a byte */
while(SPI_I2S_GetFlagStatus(TCC_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(TCC_SPI);
}
/*******************************************************************************
* Function Name : void M25P80_CMD1B(u8 cmd)
* Description : 发送一个字节指令
* This function must be used only if the Start_Read_Sequence
* function has been previously called.
* Input : None
* Output : None
* Return : Byte Read from the SPI Flash.
*******************************************************************************/
void M25P80_CMD1B(u8 cmd)
{
M25P80_CS0(); // GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(cmd);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
}
/*******************************************************************************
* Function Name : u8 M25P80_CMD1B_READ1B(u8 cmd)
* Description : 发送一个字节指令并接受返回值
* This function must be used only if the Start_Read_Sequence
* function has been previously called.
* Input : None
* Output : None
* Return : Byte Read from the SPI Flash.
*******************************************************************************/
u16 M25P80_CMD1B_READ1B(u16 cmd)
{
u16 data;
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(cmd);
data = SPI_FLASH_SendByte(0xFF);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
return data;
}
/*******************************************************************************
* Function Name : void M25P80_CMD1B_S1B(u16 cmd , u16 data)
* Description : 写一指令与一数据
* Input : None
* Output : None
* Return : Byte Read from the SPI Flash.
*******************************************************************************/
void M25P80_CMD1B_S1B(u16 cmd , u16 data)
{
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(cmd);
SPI_FLASH_SendByte(data);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
}
/*******************************************************************************
* Function Name : void M25P80_WP_En(void)
* Description : 写使能
* 使能寄存器中的WEL位
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void M25P80_Write_En(void)
{
u16 sta;
//清除 Block Protect位:PB0,PB1,PB2,即取消所有区域保护
sta = M25P80_CMD1B_READ1B(RDSR) & (~0x1C);
M25P80_CMD1B_S1B(WRSR, sta);
// Protected Area Upper sixteenth (Sector 15)以及WEL位
M25P80_CMD1B(WREN);
while(!(M25P80_CMD1B_READ1B(RDSR) & 0x02));
sta = M25P80_CMD1B_READ1B(RDSR);
}
/*******************************************************************************
* Function Name : void M25P80_WP_En(void)
* Description : 写失能
* 使能寄存器中的WEL位
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void M25P80_WP_En(void)
{
u16 sta;
//添加PB0,PB1,PB2的保护位
sta = M25P80_CMD1B_READ1B(RDSR) | 0x1c;
M25P80_CMD1B_S1B(WRSR, sta);
M25P80_CMD1B(WRDI);
}
/*******************************************************************************
* Function Name : u8 M25P80_Busy(void)
* Description : 状态检测
* 最低位WIP为1则正在工作
* Input : None
* Output : None
* Return : return (sta & 0x01);
*******************************************************************************/
u8 M25P80_Busy(void)
{
u8 sta;
sta = M25P80_CMD1B_READ1B(RDSR);
return (sta & 0x01);
}
/*******************************************************************************
* Function Name : void M25P80_Section_Erase(u32 addr)
* Description : 位擦除
* 擦除FLASH固定地址的数据
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void M25P80_Section_Erase(u32 addr)
{
u8 ad[3] ;
// ad[0] = (addr & 0x00ff0000) ;
// ad[1] = (addr & 0x0000ff00) >> 8;
// ad[2] = (addr & 0x000000ff) >> 16;
ad[0] = (addr >> 16) & 0xFF; // ?8?
ad[1] = (addr >> 8) & 0xFF; // ?8?
ad[2] = addr & 0xFF; // ?8?
M25P80_Write_En();
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(SECTOR_ERASER);
SPI_FLASH_SendByte(ad[0]);
SPI_FLASH_SendByte(ad[1]);
SPI_FLASH_SendByte(ad[2]);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
while(M25P80_Busy());
while(M25P80_Busy());
while(M25P80_Busy());
M25P80_CMD1B(WRDI);
//M25P80_WP_En();
while(M25P80_Busy()); // ??????
while(M25P80_Busy());
}
/*******************************************************************************
* Function Name : void M25P80_Bulk_Erase(void)
* Description : 全扇区擦除
* 格式化8MFLASH
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void M25P80_Bulk_Erase(void)
{
M25P80_Write_En();
M25P80_CMD1B(BULK_ERASER);
while(M25P80_Busy());
M25P80_CMD1B(WRDI);
//M25P80_WP_En();
while(M25P80_Busy()); // ??????
while(M25P80_Busy());
}
/*******************************************************************************
* Function Name : void M25P80_Write_1Byte(u32 addr , u8 data)
* Description : 写数据
* 写固定地址的一位数据
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void M25P80_Write_1Byte(u32 addr , u8 data)
{
u8 ad[3] ;
// ad[0] = (addr & 0x00ff0000);
// ad[1] = (addr & 0x0000ff00) >> 8;
// ad[2] = (addr & 0x000000ff) >> 16;
ad[0] = (addr >> 16) & 0xFF; // ?8?
ad[1] = (addr >> 8) & 0xFF; // ?8?
ad[2] = addr & 0xFF; // ?8?
M25P80_Write_En();
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(PAGE_PROG);
SPI_FLASH_SendByte(ad[0]);
SPI_FLASH_SendByte(ad[1]);
SPI_FLASH_SendByte(ad[2]);
SPI_FLASH_SendByte(data);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
while(M25P80_Busy());
M25P80_CMD1B(WRDI);
//M25P80_WP_En();
}
/*******************************************************************************
* Function Name : void M25p80_Write_Bytes(u32 addr , u8* wr_buf_p , u16 no)
* Description : 写数据
* 多字节写入数据
* Input : u32 addr启示地址 , u8* wr_buf_p写入数据初始位指针 ,
* u16 no写入字节个数
* Output : None
* Return : None
*******************************************************************************/
void M25P80_Write_Bytes(u32 addr , u8* wr_buf_p , u16 no)
{
u8 ad[3] ;
// ad[0] = (addr & 0x00ff0000) ;
// ad[1] = (addr & 0x0000ff00) >> 8;
// ad[2] = (addr & 0x000000ff) >> 16;
//
ad[0] = (addr >> 16) & 0xFF; // ?8?
ad[1] = (addr >> 8) & 0xFF; // ?8?
ad[2] = addr & 0xFF; // ?8?
M25P80_Write_En();
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(PAGE_PROG);
SPI_FLASH_SendByte(ad[0]);
SPI_FLASH_SendByte(ad[1]);
SPI_FLASH_SendByte(ad[2]);
for(; no > 0; no--)
{
SPI_FLASH_SendByte(*wr_buf_p);
wr_buf_p++;
}
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
while(M25P80_Busy());
M25P80_CMD1B(WRDI);
//M25P80_WP_En();
}
/*******************************************************************************
* Function Name : u8 M25P80_Read_1Byte(u32 addr )
* Description : 读数据
* 读固定地址的一位数据
* Input : None
* Output : None
* Return : return data;
*******************************************************************************/
u8 M25P80_Read_1Byte(u32 addr )
{
u8 ad[3] , data;
// ad[0] = (addr & 0x00ff0000) ;
// ad[1] = (addr & 0x0000ff00) >> 8;
// ad[2] = (addr & 0x000000ff) >> 16;
ad[0] = (addr >> 16) & 0xFF; // ?8?
ad[1] = (addr >> 8) & 0xFF; // ?8?
ad[2] = addr & 0xFF; // ?8?
//M25P80_CMD1B(WRDI);
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(READ);
SPI_FLASH_SendByte(ad[0]);
SPI_FLASH_SendByte(ad[1]);
SPI_FLASH_SendByte(ad[2]);
data = SPI_FLASH_SendByte(0xff);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
return data;
}
/*******************************************************************************
* Function Name : void M25P80_Read_Bytes(u32 addr , u8* re_buf_p , u16 no)
* Description : 读数据
* 读固定地址的N位数据
* Input : u32 addr地址 , u8* re_buf_p存放数据缓冲指针
* , u16 no读取数据个数N
* Output : None
* Return : return data;
*******************************************************************************/
void M25P80_Read_Bytes(u32 addr , u8* re_buf_p , u16 no)
{
u8 ad[3] ;
// ad[0] = (addr & 0x00ff0000) ;
// ad[1] = (addr & 0x0000ff00) >> 8;
// ad[2] = (addr & 0x000000ff) >> 16;
ad[0] = (addr >> 16) & 0xFF; // ?8?
ad[1] = (addr >> 8) & 0xFF; // ?8?
ad[2] = addr & 0xFF; // ?8?
//M25P80_CMD1B(WRDI);
//M25P80_Write_En();
M25P80_CMD1B(WREN);
M25P80_CS0(); //GPIO_ResetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=0;
SPI_FLASH_SendByte(READ);
SPI_FLASH_SendByte(ad[0]);
SPI_FLASH_SendByte(ad[1]);
SPI_FLASH_SendByte(ad[2]);
for(; no > 0; no--)
*re_buf_p++ = SPI_FLASH_SendByte(0xff);
M25P80_CS1(); //GPIO_SetBits(GPIOA,GPIO_Pin_7); //FLASH_CS=1;
}
/*******************************************************************************
* Function Name :WriteDataToM25P80(u8* data, u16 length)
* Description :
* Input :
*
* Output : None
* Return : return data;
*******************************************************************************/
u32 WriteDataToM25P80(u8* data, u16 length) {
// PAGE ALINE
u32 startAddress = currentAddress;
u32 page_size = 256;
u32 page_offset = currentAddress % page_size;
u16 remainingData;
// u8 addressBuffer[4];
//
if (page_offset != 0) {
remainingData = page_size - page_offset;
if (remainingData > length) {
remainingData = length;
}
M25P80_Write_Bytes(currentAddress, data, remainingData);
currentAddress += remainingData;
length -= remainingData;
data += remainingData;
}
//
while (length >= page_size) {
M25P80_Write_Bytes(currentAddress, data, page_size);
currentAddress += page_size;
length -= page_size;
data += page_size;
}
//
if (length > 0) {
M25P80_Write_Bytes(currentAddress, data, length);
currentAddress += length;
}
// ???????M25P80?????
// u8 addressBuffer[4];
addressBuffer[0] = (currentAddress >> 24) & 0xFF;
addressBuffer[1] = (currentAddress >> 16) & 0xFF;
addressBuffer[2] = (currentAddress >> 8) & 0xFF;
addressBuffer[3] = currentAddress & 0xFF;
M25P80_Write_Bytes(ADDRESS_STORAGE_LOCATION, addressBuffer, 4);
// M25P80_Write_Bytes(currentAddress, addressBuffer, 4);
return startAddress;
}
/*******************************************************************************
* Function Name :ReadAllDataFromM25P80
* Description : read all data in the chip
* Input :
* Output : None
* Return : return data;
*******************************************************************************/
//#define M25P80_SIZE 0x800000 // 8MB size of M25P80
void ReadAllDataFromM25P80(u8* buffer)
{
u32 addr;
for (addr = 0; addr < M25P80_SIZE; addr += 256) {
M25P80_Read_Bytes(addr, &buffer[addr], 256);
}
}
u8 M25P80_ReadID(void) {
u8 id;
M25P80_CS0();
SPI_FLASH_SendByte(0x9F); // ?ID??
id = SPI_FLASH_SendByte(0xFF);
M25P80_CS1();
return id;
}
在这个m25p80的驱动程序中,这个WriteDataToM25P80函数是否能够正常使用