/*
* Driver_FlashParam.c
*
* Created on: 2017年5月27日
* Author: Administrator
*/
#ifndef LIB_DRI_FLASHPARAM
#define LIB_DRI_FLASHPARAM
#include "driver_includes.h"
#endif
#define DEV_PATH "/sys/class/gpio/gpio22/value" // 输入输出电平值设备
#define EXPORT_PATH "/sys/class/gpio/export" // GPIO设备导出设备
#define DIRECT_PATH "/sys/class/gpio/gpio22/direction" // GPIO输入输出控制设备
#define OUT "out"
#define IN "in"
#define GPIO "22" // GPIO1_22----CS引脚
#define HIGH_LEVEL "1"
#define LOW_LEVEL "0"
int FLASH_CS_FD_DEV;
int FLASH_CS_FD_EXP;
int FLASH_CS_FD_DIR;
int FLASH_SPI_FD_DIR;
static const char *device = "/dev/spidev0.0";
uint8_t SPI_MODE;
uint8_t SPI_BITS;
uint16_t SPI_SPEED;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
//fm25L256 cmd
#define FM_OPT_WREN 0x06//写允许
#define FM_OPT_WRDI 0x04//写操作不允许
#define FM_OPT_RDSR 0x05//读状态
#define FM_OPT_WRSR 0x01//写状态
#define FM_OPT_ERAD 0x03//读存储器数据
#define FM_OPT_WRIT 0x02//写存储器数据
#define FM_OPT_ADDR 0x0
static uint16_t gOptAddr = FM_OPT_ADDR;
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;//这里是ioctl会有警告,是隐式声明的
static int spi_write_only(int fd, const uint8_t *wbuf, int wlen, uint8_t *rbuf, int rlen){
int ret = 0;
usleep(5);
Flash_CS_LOW();
usleep(5);
Flash_CS_HIGH();
usleep(10);
Flash_CS_LOW();
struct spi_ioc_transfer tr[1] = {
{
.tx_buf = (unsigned long)wbuf,
.rx_buf = 0,
.len = wlen,
.speed_hz = 5000000,
.delay_usecs = 0,
.bits_per_word = 8,
},
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr);
usleep(5);
Flash_CS_HIGH();
usleep(5);
return ret;
}
static int spi_write_read(int fd, const uint8_t *wbuf, int wlen, uint8_t *rbuf, int rlen)
{
int ret = 0;
usleep(5);
Flash_CS_LOW();
usleep(5);
Flash_CS_HIGH();
usleep(10);
Flash_CS_LOW();
struct spi_ioc_transfer tr[2] = {
{
.tx_buf = (unsigned long)wbuf,
.rx_buf = 0,
.len = wlen,
.speed_hz = 5000000,
.delay_usecs = 0,
.bits_per_word = 8,
},
{
.tx_buf = 0,
.rx_buf = (unsigned long)rbuf,
.len = rlen,
.speed_hz = 5000000,
.delay_usecs = 0,
.bits_per_word = 8,
},
};
ret = ioctl(fd, SPI_IOC_MESSAGE(2), tr);
usleep(5);
Flash_CS_HIGH();
usleep(5);
return ret;
}
static void FRAM_Write8bits(uint8_t u8Data)
{
int ret;
usleep(5);
Flash_CS_LOW();
usleep(5);
Flash_CS_HIGH();
usleep(10);
Flash_CS_LOW();
uint8_t tx[] = {u8Data};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx, //定义发送缓冲区指针
.rx_buf = 0, //定义接收缓冲区指针
.len = ARRAY_SIZE(tx),
.delay_usecs = 0,
.speed_hz = 5000000,
.bits_per_word = 8,
};
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0)
printf("can't send spi message1
");
usleep(5);
Flash_CS_HIGH();
usleep(5);
}
int Flash_CS_IO_Init(void)
{
int ret;
FLASH_CS_FD_EXP = open(EXPORT_PATH, O_WRONLY); // 打开GPIO设备导出设备
if(FLASH_CS_FD_EXP < 0) {
perror("open export:");
return -1;
}
write(FLASH_CS_FD_EXP, GPIO, strlen(GPIO));
FLASH_CS_FD_DIR = open(DIRECT_PATH, O_RDWR);
if(FLASH_CS_FD_DIR < 0) {
perror("open gpio dir:");
return -1;
}
ret = write(FLASH_CS_FD_DIR, OUT, strlen(OUT)); // 设置为输出模式
if(ret < 0)
{
close(FLASH_CS_FD_DIR);
perror("write gpio dir:");
return -1;
}
FLASH_CS_FD_DEV = open(DEV_PATH, O_RDWR); // 先打开设备
if(FLASH_CS_FD_DEV < 0) {
perror("open gpio value:");
close(FLASH_CS_FD_DEV);
return -1;
}
return 0;
}
void Flash_CS_LOW(void)//低电平有效
{
int ret;
ret = write(FLASH_CS_FD_DEV,LOW_LEVEL,strlen(HIGH_LEVEL));
if(ret < 0)
{
perror("write gpio_cs low :");
}
}
void Flash_CS_HIGH(void)
{
int ret;
ret = write(FLASH_CS_FD_DEV,HIGH_LEVEL,strlen(HIGH_LEVEL));
if(ret < 0)
{
perror("write gpio_cs high :");
}
}
void Flash_init(uint8_t mode,uint8_t bits,uint32_t speed)
{
int ret;
Flash_CS_IO_Init();
FLASH_SPI_FD_DIR = open(device, O_RDWR);
if (FLASH_SPI_FD_DIR < 0)
{
perror("can't open device");
}
mode = SPI_MODE_0;
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_MODE,&mode);//设置模式
if(ret < 0)
{
perror("can't set mode");
}
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_MODE,&mode);//设置模式
if(ret < 0)
{
perror("can't set mode");
}
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_BITS_PER_WORD, &bits);//设置SPI每字的数据长度
if(ret < 0)
{
perror("can't set bits");
}
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_BITS_PER_WORD, &bits);//设置SPI每字的数据长度
if(ret < 0)
{
perror("can't set bits");
}
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_MAX_SPEED_HZ, &speed);//设置SPI最大总线速度
if (ret < 0)
{
perror("can't set max speed hz");
}
ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_MAX_SPEED_HZ, &speed);//设置SPI最大总线速度
if (ret < 0)
{
perror("can't set max speed hz");
}
SPI_MODE = mode;
SPI_BITS = bits;
SPI_SPEED = speed;
printf("spi mode: %d
", mode);
printf("bits per word: %d
", bits);
printf("max speed: %d Hz (%d KHz)
", speed, speed/1000);
}
void Flash_Update_Thread(void)
{
int ret;
int i;
int tmpSize;
uint8_t wrBuf[128];
uint8_t rdBuf[128];
int index;
int optSize;
wrBuf[0] = FM_OPT_WRSR;
wrBuf[1] = 0;
wrBuf[2] = 0;
tmpSize = 128;
while(1)
{
sleep(1);
Flash_CS_LOW();
FRAM_Write8bits(FM_OPT_WREN);
index = 0;
wrBuf[index++] = FM_OPT_WRIT;
wrBuf[index++] = (gOptAddr>>8)&0xff;
wrBuf[index++] = (gOptAddr>>0)&0xff;
srand((unsigned)time(NULL));
printf("write data =
");
if(tmpSize){
for(i = 0; i < tmpSize; i++){
rdBuf[i] = 1 + rand()%100+1;
printf("%02x ", rdBuf[i]);
}
}
else{
tmpSize = 128;
for(i = 0; i < tmpSize; i++){
rdBuf[i] = 0;
printf("%02x ", rdBuf[i]);
}
}
printf("
");
memcpy(&wrBuf[index], rdBuf,tmpSize);
index += tmpSize;
optSize = index;
ret = spi_write_only(FLASH_SPI_FD_DIR, wrBuf,optSize, 0, 0);
if(ret < 0)
printf("write error,err = %d
", ret);
else
printf("write ok.ret = %d
", ret);
memset(rdBuf, 0, sizeof(rdBuf));
FRAM_Write8bits(FM_OPT_WREN);
FRAM_Write8bits(FM_OPT_ERAD);//这里十分重要,不然读取数据为全为0
index = 0;
wrBuf[index++] = FM_OPT_ERAD;
wrBuf[index++] = (gOptAddr>>8)&0xff;
wrBuf[index++] = (gOptAddr>>0)&0xff;
ret = spi_write_read(FLASH_SPI_FD_DIR, wrBuf, index, rdBuf, sizeof(rdBuf));
if(ret < 0){
printf("read error, err = %d
", ret);
}
else{
printf("read ok.ret = %d, data =
", ret);
for(index = 0; index < sizeof(rdBuf); index++){
printf("%02x ", rdBuf[index]);
}
printf("
");
Flash_CS_HIGH();
}
}
}
具体数据手册请参考:http://pdf1.alldatasheet.com/datasheet-pdf/view/107175/ETC/FM25L256.html
演示结果为:
欢迎关注并加入物联网行业联盟,积累行业人脉和资源。