NIOS下的配置flash芯片的参数读写
项目中使用了基于FPGA下的NIOS嵌入式系统>,本来俺只是一个arm下的小码农,无奈实验室没人弄,结果被老师拿过去顶了,虽然对FPGA不怎么熟悉,但是在 寒假回家期间恶补了一下基于FPAG的NIOS嵌入式的verilog编程,终于有所进步了,现在整个项目只有我一个人在做,虽然很累,但是工资高啊. 感谢老师的培养和信任. 这几天项目中需要把工程运行的一些参数保存在flash中,无奈板子上没有其他操作方便的的闲置存储芯片,虽然有个SD卡,但是我嫌弃操作麻烦,于是就开始打这块FPGA配置芯片的主意了.研究了资料后,发现还是atera公司原版的英文手册讲的最清楚,其他一些资料其实都是直接翻译altera公司的英文资料的. altera公司介绍了两种操作flash的函数,分别是Simple Flash Access和Fine-Grained Flash Access,区别大家就去查看手册吧,自己懂就ok啦.我使用的是Fine-Grained Flash Access存取方法.Fine-Grained Flash Access有三个通用函数分别是: ■ alt_get_flash_info() ■ alt_erase_flash_block() ■ alt_write_flash_block() 手册上给出历程如下:
/*Using the Fine-Grained Flash Access API Functions*/ #include <string.h> #include "sys/alt_flash.h" #include "stdtypes.h" #include "system.h" #define BUF_SIZE 100 int main (void) { flash_region* regions; alt_flash_fd* fd; int number_of_regions; int ret_code; char write_data[BUF_SIZE]; /* Set write_data to all 0xa */ memset(write_data,0xA,BUF_SIZE); fd = alt_flash_open_dev(EXT_FLASH_NAME); if (fd) { ret_code = alt_get_flash_info(fd,®ions,&number_of_regions); if (number_of_regions && (regions->offset == 0)) { /* Erase the first block */ ret_code = alt_erase_flash_block(fd,regions->offset,regions->block_size); if (ret_code == 0) { /* * Write BUF_SIZE bytes from write_data 100 bytes to * the first block of the flash */ ret_code = alt_write_flash_block ( fd,regions->offset+0x100,write_data,BUF_SIZE ); } } } return 0; } 大致看懂后开始修改.大家都知道flash这个小芯片虽然容量大,价格便宜,但是写之前都需要擦除要写的扇区,一一点好麻烦啊,于是我们还要考虑在写一个字节也要对这个扇区中的其他字节做备份后再全部写入.我就简单的开了个ram空间的数组把对应的数据备份起来.
#include "Incflash.h" #include "stdio.h" #include "system.h" #include "altera_avalon_epcs_flash_controller.h" #include "epcs_commands.h" #include "sys/alt_flash.h" #include "sys/alt_flash_dev.h" #include "Inc/uart.h" #include "Inc/menu.h" float FlashParament[PARAMENTCONT] ; /* */ uint8_t WriteParament(void) { flash_region* regions; alt_flash_fd* fd; int number_of_regions; int ret_code; extern LABLE Lable_Set_ExtractMnVolume ; extern LABLE Lable_Set_DropKMnO4Volume ; extern LABLE Lable_Set_KMnO4Concentration ; extern LABLE Lable_Set_Hue_Hereshod ; fd = alt_flash_open_dev(EPCS_FLASH_CONTROLLER_0_NAME); if(fd) { ret_code = alt_get_flash_info(fd,&number_of_regions); if (number_of_regions && (regions->offset == 0)) { /* Erase the first block */ ret_code = alt_read_flash(fd,regions->offset+FLASHSEGMENT0,FlashParament,PARAMENTCONT); ret_code = alt_erase_flash_block(fd,regions->block_size); if (ret_code == 0) { FlashParament[FLASH_ONEDROPKMNO4VOLUME_OFFSET] = Lable_Set_DropKMnO4Volume.volue ; FlashParament[FLASH_INMNVOLUME_OFFSET] = Lable_Set_ExtractMnVolume.volue ; FlashParament[FLASH_TITRATIONKMNO4_OFFSET] = Lable_Set_KMnO4Concentration.volue ; FlashParament[HUE_THRESHOD] = Lable_Set_Hue_Hereshod.volue ; //H 值得阈值 /* * Write BUF_SIZE bytes from write_data 100 bytes to * the first block of the flash */ ret_code = alt_write_flash_block (fd,PARAMENTCONT*sizeof(float)); return 1 ; } } } return 0 ; } uint8_t ReadParament(void) { flash_region* regions; alt_flash_fd* fd; int number_of_regions; int ret_code; extern LABLE Lable_Set_ExtractMnVolume ; extern LABLE Lable_Set_DropKMnO4Volume ; extern LABLE Lable_Set_KMnO4Concentration ; extern LABLE Lable_Set_Hue_Hereshod ; fd = alt_flash_open_dev(EPCS_FLASH_CONTROLLER_0_NAME) ; if(fd) { ret_code = alt_get_flash_info(fd,&number_of_regions); if (number_of_regions && (regions->offset == 0)) { /* Erase the first block */ //ret_code = alt_erase_flash_block(fd,regions->block_size); ret_code = alt_read_flash(fd,PARAMENTCONT*sizeof(float)); if (ret_code == 0) { Lable_Set_DropKMnO4Volume.volue = FlashParament[FLASH_ONEDROPKMNO4VOLUME_OFFSET] ; Lable_Set_ExtractMnVolume.volue = FlashParament[FLASH_INMNVOLUME_OFFSET]; Lable_Set_KMnO4Concentration.volue = FlashParament[FLASH_TITRATIONKMNO4_OFFSET] ; Lable_Set_Hue_Hereshod.volue = FlashParament[HUE_THRESHOD]; //H 值得阈值 Uart1_printf("%ft%ft%ft%fnn",Lable_Set_DropKMnO4Volume.volue,Lable_Set_ExtractMnVolume.volue,Lable_Set_KMnO4Concentration.volue,Lable_Set_Hue_Hereshod.volue) ; return 1 ; } } } return 0 ; } uint8_t WriteDefaultParament(void) { flash_region* regions; alt_flash_fd* fd; int number_of_regions; int ret_code; extern LABLE Lable_Set_ExtractMnVolume ; extern LABLE Lable_Set_DropKMnO4Volume ; extern LABLE Lable_Set_KMnO4Concentration ; extern LABLE Lable_Set_Hue_Hereshod ; fd = alt_flash_open_dev(EPCS_FLASH_CONTROLLER_0_NAME); Lable_Set_DropKMnO4Volume.volue = 0.2 ; Lable_Set_ExtractMnVolume.volue = 2.0 ; Lable_Set_KMnO4Concentration.volue = 0.05 ; Lable_Set_Hue_Hereshod.volue = 170.0 ; if(fd) { ret_code = alt_get_flash_info(fd,&number_of_regions); if (number_of_regions && (regions->offset == 0)) { /* Erase the first block */ //ret_code = alt_read_flash(fd,T,regions->block_size); if (ret_code == 0) { FlashParament[FLASH_ONEDROPKMNO4VOLUME_OFFSET] = Lable_Set_DropKMnO4Volume.volue ; FlashParament[FLASH_INMNVOLUME_OFFSET] = Lable_Set_ExtractMnVolume.volue ; FlashParament[FLASH_TITRATIONKMNO4_OFFSET] = Lable_Set_KMnO4Concentration.volue ; FlashParament[HISTORYCOUNT] = 0.0 ; FlashParament[HISTORY0] = 0.0 ; FlashParament[HISTORY1] = 0.0 ; FlashParament[HISTORY2] = 0.0 ; FlashParament[HISTORY3] = 0.0 ; FlashParament[HISTORY4] = 0.0 ; FlashParament[HISTORY5] = 0.0 ; FlashParament[HISTORY6] = 0.0 ; FlashParament[HISTORY7] = 0.0 ; FlashParament[HISTORY8] = 0.0 ; FlashParament[HISTORY9] = 0.0 ; FlashParament[HUE_THRESHOD] = Lable_Set_Hue_Hereshod.volue ; //H 值得阈值 //FlashParament[PARAMENTCONT] = (HISTORYCOUNT+1) ; /* * Write BUF_SIZE bytes from write_data 100 bytes to * the first block of the flash */ ret_code = alt_write_flash_block (fd,PARAMENTCONT*sizeof(float)); return 1 ; } } } return 0 ; } //保存本次测试的浓度值到flash uint8_t SaveTestHistory(float saveCon) { int i ; ReadParament() ; i = (uint8_t)FlashParament[HISTORYCOUNT] - 1 ; for(i ; i > 0 ;i--) //删除最早保存的记录 { FlashParament[HISTORY0 + i] = FlashParament[HISTORY0 + i - 1]; } FlashParament[HISTORY0] = saveCon ; //保存最新记录到flash WriteParament() ;// return 1 ; } 这是调试正常后的代码,虽然很多东西需要优化,但是我马上要去青岛了,来不及优化了,只能留点悬念给学弟学妹吧.慢慢优化吧. 代码上正常工作了,但是前面还是让手册里面的资料坑了一把.也许是我的理解错了. int alt_write_flash_block( alt_flash_fd* fd,int block_offset,int data_offset,const void *data,int length) 这个函数,最后一个参数应该表述有问题,length不是data的长度,而是数组data的大小,即sizeof(data).开始一直以为是数组的长度.希望使用时注意吧. 也许这是在吉首大学发的最后一个博客,最后一个没有技术含量的博客,希望去了海大后,能继续提高自己吧.加油青岛见. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |