/****************************************Copyright (c)****************************************************
** Beijing Highlander Digital Technology Co.,LTD.
**
** http://www.highlander.com.cn
**
**--------------File Info---------------------------------------------------------------------------------
** File name: spi_flash.c
** Last modified Date: 2013-04-26
** Last Version: V1.1
** Descriptions: Driver for SPI Flash MX25L512MI
**
**--------------------------------------------------------------------------------------------------------
** Created by: Sam Qin
** Created date: 2012-07-06
** Version: V1.1 从
** Descriptions: 工程主文件
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
** Rechecked by:
*********************************************************************************************************/
#include <ctype.h>
#include <stdlib.h>
#include <setjmp.h>
#include <rt_misc.h>
#include "..\config.h"
#include "spi_flash.h"
#define SSP0_ACTIVE
//#define SPI_ACTIVE
/* 移植本软件包时需要修改以下的函数或宏 */
#ifdef SSP0_ACTIVE
#define SPI_POWER_ON() (PCONP |= (1 << 21))
#define SPI_PIN_SET() (PINSEL3 |= (3 << 8) | (3 << 14) | (3 << 16))
#define SPI_CS (1 << 21) // P1.21口为25VF016B的片选,该脚为低时,SST25VF016B芯片被使能
#define CE_OUTPUT() (FIO1DIR |= SPI_CS)
#define CE_LOW() (FIO1CLR |= SPI_CS)
#define CE_HIGH() (FIO1SET |= SPI_CS)
/*
#define SPI_POWER_ON() (PCONP |= (1 << 21))
#define SPI_PIN_SET() (PINSEL0 |= ((INT32U)2 << 30)); (PINSEL1 |= (2<<2)|(2<<4))
#define SPI_CS (1 << 16) // P0.16口为25VF016B的片选,该脚为低时,SST25VF016B芯片被使能
#define CE_OUTPUT() (FIO0DIR |= SPI_CS)
#define CE_LOW() (FIO0CLR |= SPI_CS)
#define CE_HIGH() (FIO0SET |= SPI_CS)
*/
#endif
#ifdef SPI_ACTIVE
#define SPI_POWER_ON() (PCONP |= (1 << 8))
#define SPI_PIN_SET() (PINSEL0 |= (3 << 30)); (PINSEL1 |= (3<<2)|(3<<4))
#define SPI_CS (1 << 16) // P0.16口为25VF016B的片选,该脚为低时,SST25VF016B芯片被使能
#define CE_OUTPUT() (FIO0DIR |= SPI_CS)
#define CE_LOW() (FIO0CLR |= SPI_CS)
#define CE_HIGH() (FIO0SET |= SPI_CS)
#endif
static INT8U sec_data_tmp_buffer[SEC_SIZE];
/*********************************************************************************************************
** 函数名称: send_byte
** 函数功能:通过硬件SPI发送一个字节到MX25L512
** 入口参数:data
** 出口参数:无
*********************************************************************************************************/
void send_byte(INT8U data)
{
#ifdef SSP0_ACTIVE
while ((SSP0SR & 0x01) == 0); /* 等待发送FIFO留出空? */
SSP0DR = data;
while ((SSP0SR & 0x10) == 0x10); /* 等待数据帧发送完毕 */
data = SSP0DR; /* 清空无用的接收数据 */
#endif
#ifdef SPI_ACTIVE
S0SPDR = data;
while ( 0 == (S0SPSR & 0x80)); // 等待SPIF置位,即等待数据发送完毕
data = S0SPSR; // 清除SPIF标志
#endif
}
/*********************************************************************************************************
** 函数名称:get_byte
** 函数功能:通过硬件SPI接口接收一个字节到处理器
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
INT8U get_byte(void)
{
#ifdef SSP0_ACTIVE
INT8U temp;
//while ((SSP0SR & 0x04) == 0x04) temp = SSP0DR;
SSP0DR = 0xff;
while ((SSP0SR & 0x10) == 0x10); /* 等待数据帧发送完毕 */
while ((SSP0SR & 0x04) == 0x00);
temp = (INT8U)(SSP0DR);
return temp;
#endif
#ifdef SPI_ACTIVE
INT8U temp;
S0SPDR = 0xff; // 发送该数据用以产生时钟,数据本身没有用处
while ( 0 == (S0SPSR & 0x80)); // 等待SPIF置位,即等待数据发送完毕
temp = S0SPSR; // 清除SPIF标志
temp = temp;
return (INT8U)(S0SPDR); // 返回接收到的数据
#endif
}
/*********************************************************************************************************
** 函数名称:flash_read
** 函数功能:MX25L512的读函数,可选择读ID和读数据操作
** 入口参数:
** INT32U sour_addr:读取地址首字节,范围 0x0 - MAX_ADDR(MAX_ADDR = 0x10000)
** INT32U bytes: 要读取的数据字节数
** INT8U* rcv_buf:接收缓存的指针
** 出口参数:操作成功则返回OK,失败则返回ERROR
** 注 意:若某功能下,某一入口参数无效,可在该入口参数处填Invalid,该参数将被忽略
*********************************************************************************************************/
INT8U flash_read(INT32U sour_addr, INT8U* rcv_buf, INT32U bytes)
{
INT32U i = 0;
INT8U state_reg_val = 0;
if ((sour_addr+bytes > MAX_ADDR)||(bytes == 0)) return (ERROR); // 检查入口参数
do {
CE_LOW();
send_byte(0x05); // 发送读状态寄存器命令
state_reg_val = get_byte(); // 保存读得的状态寄存器值
CE_HIGH();
} while ((state_reg_val&0x01) == 0x01);
CE_LOW();
send_byte(0x0B); // 发送读命令
send_byte(((sour_addr & 0xFFFFFF) >> 16)); // 发送地址信息:该地址由3个字节组成
send_byte(((sour_addr & 0xFFFF) >> 8));
send_byte(sour_addr & 0xFF);
send_byte(0xFF); // 发送一个哑字节以读取数据
for (i = 0; i < bytes; i++) {
rcv_buf[i] = get_byte();
}
CE_HIGH();
return (OK);
}
/*********************************************************************************************************
** 函数名称:flash_read_id
** 函数功能:MX25L512的读ID函数,可选择读ID和读数据操作
** 入口参数:
** idtype id_type:ID类型。用户可在Jedec_ID,Dev_ID,Manu_ID三者里选择
** INT32U* rcv_buf:存储ID变量的指针
** 出口参数:操作成功则返回OK,失败则返回ERROR
** 注 意:若填入的参数不符合要求,则返回ERROR
*********************************************************************************************************/
INT8U flash_read_id(idtype id_type, INT32U* rcv_buf)
{
INT32U temp = 0;
if (id_type == Jedec_ID) {
CE_LOW();
send_byte(0x9F); // 发送读JEDEC ID命令(9Fh)
temp = (temp | get_byte()) << 8;// 接收数据
temp = (temp | get_byte()) << 8;
temp = (temp | get_byte()); // 在本例中,temp的值应为0xBF2541
CE_HIGH();
*rcv_buf = temp;
return (OK);
}
if ((id_type == Manu_ID) || (id_type == Dev_ID) ) {
CE_LOW();
send_byte(0x90); // 发送读ID命令 (90h or ABh)
send_byte(0x00); // 发送地址
send_byte(0x00); // 发送地址
send_byte(id_type); // 发送地址 - 不是00H就是01H
temp = get_byte(); // 接收获取的数据字节
CE_HIGH();
*rcv_buf = temp;
return (OK);
}
else {
return (ERROR);
}
}
/*********************************************************************************************************
** 函数名称:flash_erase
** 函数功能:根据指定的扇区号选取最高效的算法擦除
** 入口参数:
** INT32U sec1:起始扇区号,范围(0~16)
** INT32U sec2:终止扇区号,范围(0~16)
** 出口参数:操作成功则返回OK,失败则返回ERROR
*********************************************************************************************************/
INT8U flash_erase(INT32U sec1, INT32U sec2)
{
INT8U temp1 = 0,temp2 = 0,state_reg_val = 0;
INT32U sec_start_addr = 0;
INT32U sectors_to_erase = 0; // 要擦除的扇区数目
INT32U
- 1
- 2
- 3
前往页