搜索
bottom↓
回复: 96

【分享】配合前几天发的SPI Flash的驱动,分析MQX驱动架构!

  [复制链接]

出0入0汤圆

发表于 2014-8-31 17:00:52 | 显示全部楼层 |阅读模式
本帖最后由 FSL_TICS_ZJJ 于 2014-9-11 16:05 编辑

首先声明:以下都是我个人在MQX学习、使用过程中的一些见解,当然,里面可能会有一些说的不是很明白,我希望我扔出来的这块砖头,能引来他山之玉

在参考了MQX自带的内部Flash驱动中,我看到Flash其实可以分区进行不同区域来做驱动,比如我自己的这个驱动,就是将一个8M的SPI Flash分为两块,前2M是一块,后面6M是一块,而每个块我们都需要不同的参数来进行标记,我做了一个Flash Block的结构体如下:
  1. typedef struct spi_flash_block
  2. {
  3.     char *block_name;                                //分块名称
  4.     uint32_t block_start_address;                //块起始地址
  5.     uint32_t block_end_address;                //块结束地址
  6.     uint32_t sector_address;                 //当前操作扇区地址
  7.     uint32_t sector_size;                        //驱动大小
  8.     uint8_t *sector_buff;                        //CACHE指针
  9.     bool sector_change_flag;                        //写标志
  10. }SPI_FLASH_BLOCK, *SPI_FLASH_BLOCK_PTR;
复制代码


然后定义两个区,我将一个命名为系统区,另一个命名为用户区:
  1. static SPI_FLASH_BLOCK spi_flash_block_descr[] = {
  2.     {"system", 0x00000000, 0x001FFFFF, 0x00000000, SPI_MEMORY_SECTOR_SIZE, NULL, FALSE},
  3.     {"user",   0x00200000, 0x007FFFFF, 0x00200000, SPI_MEMORY_SECTOR_SIZE, NULL, FALSE},
  4.     {0,        0,          0,          0,          0,                      0         }
  5. };
复制代码


当然还有一个比较重要的参数,就是SPI口了,这个参数可以用来改变SPI口,因为我的Flash挂接在SPI0上,所以如下定义:
  1. #if BSP_SPI_MEMORY_CHANNEL == 0
  2.         #define SPI_CHANNEL SPI0_BASE_PTR
  3. #elif BSP_SPI_MEMORY_CHANNEL == 1
  4.         #define SPI_CHANNEL SPI1_BASE_PTR
  5. #elif BSP_SPI_MEMORY_CHANNEL == 2
  6.         #define SPI_CHANNEL  SPI2_BASE_PTR
  7. #else
  8.      #error Unsupported SPI channel number. Please check settings of BSP_SPI_MEMORY_CHANNEL in BSP.
  9. #endif
复制代码


而为了更方便将来对驱动的修改,我添加了一个公共的数据结构,虽然目前没有其它参数,但如果以后要使用,可以在此结构体里面添加:

  1. typedef struct spi_flash_struct
  2. {
  3.     SPI_MemMapPtr SPIx;
  4. }SPI_FLASH_STRUCT, *SPI_FLASH_STRUCT_PTR;
复制代码


好了,前期的准备工作我们做好了,接下来我们要做驱动了,其实OS的驱动不外乎就是几个函数,我要完成以下几个函数的编写:
  1. _mqx_uint _spi_flash_install(char *identifier, SPI_FLASH_STRUCT const *init_ptr);
  2. _mqx_int _spi_flash_init(const void *init_data_ptr, void **io_info_ptr_ptr);
  3. _mqx_int _spi_flash_open(MQX_FILE_PTR fd_ptr, char *open_name_ptr, char *flags);
  4. _mqx_int _spi_flash_close(MQX_FILE_PTR fd_ptr);
  5. _mqx_int _spi_flash_read(MQX_FILE_PTR fd_ptr, char *data_ptr, _mqx_int num);
  6. _mqx_int _spi_flash_write(MQX_FILE_PTR fd_ptr, char *data_ptr, _mqx_int num);
  7. _mqx_int _spi_flash_ioctl(MQX_FILE_PTR fd_ptr, _mqx_uint cmd, void *param_ptr);
  8. _mqx_int _spi_flash_uninstall(IO_DEVICE_STRUCT_PTR   io_dev_ptr);
复制代码


第一个当然是install函数,我写的函数如下:
  1. _mqx_uint _spi_flash_install ( char *identifier, SPI_FLASH_STRUCT const   *init_ptr)
  2. {
  3.     SPI_FLASH_STRUCT_PTR spi_flash_data = _mem_alloc_system(sizeof(SPI_FLASH_STRUCT));        //定义了公共的变量
  4.    [color=Red] spi_flash_init(spi_flash_data, NULL);                //初始化端口以及数据
  5. [/color]    return (_io_dev_install_ext(                               //进行驱动注册
  6.         identifier,
  7.         _spi_flash_open,
  8.         _spi_flash_close,
  9.         _spi_flash_read,
  10.         _spi_flash_write,
  11.         _spi_flash_ioctl,
  12.         _spi_flash_uninstall,
  13.         spi_flash_data));
  14. }
复制代码

这里我要注明一下,其实很多驱动都可以在驱动OPEN的时候再进行初始化,但是考虑到我初始里面有个公共的变量SPI口的选择,所以我将初始化功能放在了此处。此函数要在使用SPI Flash之前调用,用来注册驱动。使用方法:
  1. _spi_flash_install("spi_flash:", NULL);
复制代码


第二个函数是相对install来说的,就是uninstall函数:
  1. _mqx_int _spi_flash_uninstall( IO_DEVICE_STRUCT_PTR   io_dev_ptr)
  2. {
  3.     SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)io_dev_ptr->DRIVER_INIT_PTR;
  4.     _mem_free(user_data);        //因为在install函数中申请了内存,所以在此要将内存释放掉,不然会造成内存泄漏
  5.     io_dev_ptr->DRIVER_INIT_PTR = NULL; //将驱动数据清空,防止野指针的出现
  6.    return MQX_OK;
  7. }
复制代码


第三个函数当然就是初始化了:
  1. _mqx_int _spi_flash_init( const void  *init_data_ptr, void **io_info_ptr_ptr )
  2. {
  3.     SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)init_data_ptr;
  4.     user_data->SPIx = SPI_CHANNEL;
  5.     hal_spi0_init(user_data->SPIx);
  6.    
  7.     return SPI_FLASH_OK;
  8. }
复制代码

初始化函数就比较简单,我只是选择了SPI接口,然后配置硬件SPI口。

第四个函数是OPEN:
  1. _mqx_int _spi_flash_open ( MQX_FILE_PTR fd_ptr, char   *open_name_ptr, char   *flags)
  2. {
  3.     SPI_FLASH_BLOCK_PTR user_block = NULL;
  4.     int i = 0;
  5.     for(i = 0; spi_flash_block_descr[i].block_name != 0; i++)
  6.     {
  7.         [color=Red]if(0 != strstr(open_name_ptr, spi_flash_block_descr[i].block_name))        //用块名称对块进行查找
  8.         {
  9.             user_block = (SPI_FLASH_BLOCK_PTR)_mem_alloc_system(sizeof(SPI_FLASH_BLOCK));         //找到块之后申请内存作为当前打开块的初始化数据
  10.             memcpy(user_block, &(spi_flash_block_descr[i]), sizeof(SPI_FLASH_BLOCK));        //对块数据进行初始化
  11.             fd_ptr->DEV_DATA_PTR = user_block;     //将块指针赋值给当前打开的驱动数据指针
  12.             break;
  13.         }
  14. [/color]    }
  15.     if(user_block == NULL)
  16.     {
  17.         return IO_ERROR;
  18.     }
  19.     user_block->sector_buff = _mem_alloc_system(user_block->sector_size);    //给CACHE申请内存
  20.     fd_ptr->SIZE = user_block->block_end_address - user_block->block_start_address + 1;  //初始化当前驱动块的尺寸
  21.     fd_ptr->LOCATION = user_block->block_start_address;   //初始化LOCATION
  22.     read_sector(fd_ptr);  //初始化当前CACHE
  23.     return MQX_OK;
  24. }
复制代码

这个函数我也是参考原MQX中Flash驱动中的OPEN函数,这块有点说道,因为Flash分块了,所以在OPEN的时候需要做一件事情,驱动我目前要OPEN的是哪一个块,使用如下:
  1. fopen("spi_flash:system", NULL);
复制代码

或者
  1. fopen("spi_flash:user, NULL);
复制代码


第五个函数close,这个函数相对比较简单,就是释放Open时申请的所有资源,然后将指针清空:
  1. _mqx_int _spi_flash_close ( MQX_FILE_PTR fd_ptr )
  2. {
  3.     SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
  4.     fflush(fd_ptr);
  5.    [color=Red] _mem_free(user_block->sector_buff);
  6.     _mem_free(user_block);
  7.     fd_ptr->DEV_DATA_PTR = NULL;
  8. [/color]    return MQX_OK;   
  9. }
复制代码


第六个函数read,这个函数其实也没什么,直接从Flash中读数据,但是这里需要注意的是要改变CACHE的切换:
  1. _mqx_int _spi_flash_read ( MQX_FILE_PTR fd_ptr,char   *data_ptr, _mqx_int   num )
  2. {   
  3.     SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
  4.     uint32_t sector_start = user_block->sector_address;
  5.     uint32_t sector_next_start = user_block->sector_address + user_block->sector_size;
  6.     uint8_t *buff_ptr;
  7.     _mqx_int location = fd_ptr->LOCATION;
  8.     _mqx_int over_num = num;
  9.     _mqx_int read_num_one_time;
  10.     do
  11.     {
  12.         if((location < sector_start) || (location >= sector_next_start))
  13.         {
  14.             [color=Red]uint32_t error = switching_sector(fd_ptr, location);                //如果地址范围超出当前CACHE,要进行切换
  15. [/color]            if(error != SPI_FLASH_OK)
  16.             {
  17.                 return error;
  18.             }
  19.             sector_start = user_block->sector_address;
  20.             sector_next_start = user_block->sector_address + user_block->sector_size;
  21.         }
  22.         buff_ptr = user_block->sector_buff + (location & (user_block->sector_size - 1));
  23.         read_num_one_time = ((location + over_num) >= sector_next_start) ? sector_next_start - location : over_num;
  24.         memcpy(data_ptr, buff_ptr,  read_num_one_time);
  25.         data_ptr += read_num_one_time;
  26.         location += read_num_one_time;
  27.         over_num -= read_num_one_time;
  28.     }while(over_num > 0);
  29.     fd_ptr->LOCATION += num;
  30.     return num;
  31. }
复制代码


第七个函数write,写函数跟读函数一样,要注意CACHE切换,另外,写函数还要注意一定要将写标志置起来,此标志是为了CACHE切换时知道Flash是否需要改变:
  1. _mqx_int _spi_flash_write (MQX_FILE_PTR fd_ptr,char     *data_ptr, _mqx_int     num )
  2. {
  3.     SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
  4.     uint32_t sector_start = user_block->sector_address;
  5.     uint32_t sector_next_start = user_block->sector_address + user_block->sector_size;
  6.     uint8_t *buff_ptr;
  7.     _mqx_int location = fd_ptr->LOCATION;
  8.     _mqx_int write_num_one_time;
  9.     _mqx_int over_num = num;
  10.     do
  11.     {
  12.         if((location < sector_start) || (location >= sector_next_start))
  13.         {
  14.             [color=Red]uint32_t error = switching_sector(fd_ptr, location);[/color]
  15.             if(error != SPI_FLASH_OK)
  16.             {
  17.                 return error;
  18.             }
  19.             sector_start = user_block->sector_address;
  20.             sector_next_start = user_block->sector_address + user_block->sector_size;
  21.         }
  22.         buff_ptr = user_block->sector_buff + (location & (user_block->sector_size - 1));
  23.         write_num_one_time = ((location + over_num) >= sector_next_start) ? sector_next_start - location : over_num;
  24.         memcpy(buff_ptr, data_ptr, write_num_one_time);
  25.        [color=Red] user_block->sector_change_flag = TRUE;
  26. [/color]        data_ptr += write_num_one_time;
  27.         location += write_num_one_time;
  28.         over_num -= write_num_one_time;
  29.         if(location >= sector_next_start)
  30.         {
  31.             write_sector(fd_ptr);
  32.         }
  33.     }while(over_num > 0);
  34.     fd_ptr->LOCATION += num;
  35.     return num;
  36. }
复制代码


最后一个IOCTRL函数,在驱动中,此函数的重要性我想我就不用说了,下面是我的函数,因为只用到了一部分命令,所以函数不算太大,MQX中Flash的IOCTRL函数那才叫个大呢:
  1. _mqx_int _spi_flash_ioctl (MQX_FILE_PTR fd_ptr, _mqx_uint    cmd,void        *param_ptr )
  2. {
  3.     SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)fd_ptr->DEV_PTR->DRIVER_INIT_PTR;
  4.     SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
  5.     _mqx_int                           result = MQX_OK;
  6.     _mqx_uint_ptr                      uparam_ptr;
  7.     switch(cmd)
  8.     {
  9.         [color=Red]case IO_IOCTL_FLUSH_OUTPUT:                        //Flush功能,这个功能很有用,我一开始没有加此命令,结果文件写完后下次开机就不见了,大家知道原因吧,哈哈
  10.             write_sector(fd_ptr);
  11.             break;[/color]
  12.         case FLASH_IOCTL_ERASE_CHIP:            
  13.             hal_spi_dev_flash_erase_dev(user_data->SPIx);
  14.             hal_spi_dev_flash_read(user_data->SPIx, user_block->sector_address, user_block->sector_buff, user_block->sector_size);
  15.             break;

  16.         case IO_IOCTL_DEVICE_IDENTIFY:
  17.             /*
  18.             ** This is to let the upper layer know what kind of device this is.
  19.             ** It's a physical flash device, capable of being erased, read, seeked,
  20.             ** and written. Flash devices are not interrupt driven, so
  21.             ** IO_DEV_ATTR_POLL is included.
  22.             */   
  23.             uparam_ptr = (_mqx_uint_ptr)param_ptr;
  24.             uparam_ptr[0] = IO_DEV_TYPE_PHYS_FLASHX;
  25.             uparam_ptr[1] = IO_DEV_TYPE_LOGICAL_MFS;
  26.             uparam_ptr[2] = IO_DEV_ATTR_ERASE | IO_DEV_ATTR_POLL
  27.                              | IO_DEV_ATTR_READ | IO_DEV_ATTR_SEEK |
  28.                              IO_DEV_ATTR_WRITE;
  29.             break;
  30.         
  31.         case IO_IOCTL_GET_NUM_SECTORS:
  32.             *(uint32_t *)param_ptr = fd_ptr->SIZE / SPI_MEMORY_SECTOR_SIZE;
  33.             break;
  34.         case IO_IOCTL_GET_BLOCK_SIZE:      
  35.         case FLASH_IOCTL_GET_SECTOR_SIZE:
  36.             /* returns the fixed size for MFS sector size */
  37.             *(uint32_t *)param_ptr = user_block->sector_size;
  38.             break;
  39. [color=Red]        case IO_IOCTL_SEEK:                     //这个命令一定要添加,因为我们Flash分块了,所以起始地址不一样,如果不加此功能,那么它起始地址都是默认从0开始,那第二个                                                                   //块肯定会读写错误[/color]
  40.             fd_ptr->LOCATION += user_block->block_start_address;
  41.             break;
  42.         default:
  43.             result = IO_ERROR_INVALID_IOCTL_CMD;
  44.     }
  45.     return result;
  46. }
复制代码


最后的最后,还有一个函数我必须得说明一下,切换扇区,需要注意的是一开始定义的写标志在这里起了作用,看代码:
  1. uint32_t switching_sector(MQX_FILE_PTR fd_ptr, _mqx_int address)
  2. {
  3.     SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
  4.     uint32_t error_code;
  5.     //取旧扇区的起始地址
  6.     _mqx_int sector_start_address = address & (~(user_block->sector_size - 1));
  7.     //写Flash
  8. [color=Red]    if(user_block->sector_change_flag)
  9.          error_code = write_sector(fd_ptr);[/color]
  10.     if(error_code != SPI_FLASH_OK)
  11.     {
  12.         return error_code;
  13.     }
  14.     //更新扇区的起始地址参数
  15.     user_block->sector_address = sector_start_address;
  16.     //重新填充CACHE
  17.     error_code = read_sector(fd_ptr);
  18.     if(error_code != SPI_FLASH_OK)
  19.     {
  20.         return error_code;
  21.     }
  22.     return SPI_FLASH_OK;
  23. }
复制代码


OK了,其它的一些再底层的函数我就没有必要一一说明了!尾部再将源文件传上来:


砖来了,玉在哪?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2014-8-31 17:05:46 | 显示全部楼层
感谢分享,这个确实实用,收藏先
楼主辛苦

出0入0汤圆

发表于 2014-8-31 17:10:39 | 显示全部楼层
哈,楼主讲得好详细,这个可以加精

出0入0汤圆

 楼主| 发表于 2014-8-31 17:12:25 | 显示全部楼层
浪里白条 发表于 2014-8-31 17:10
哈,楼主讲得好详细,这个可以加精

谢谢捧场啊,你的飞币飞升啊! 为了追赶你,得搞有质量的帖子才成啊!

出0入0汤圆

 楼主| 发表于 2014-8-31 17:13:43 | 显示全部楼层
本帖最后由 wangpengcheng 于 2014-8-31 17:15 编辑

晕,代码里面想加红,没加上,希望大家看的时候要多注意带[color   =   read]字样的那些代码行!

出0入0汤圆

发表于 2014-8-31 17:15:55 | 显示全部楼层
wangpengcheng 发表于 2014-8-31 17:12
谢谢捧场啊,你的飞币飞升啊! 为了追赶你,得搞有质量的帖子才成啊! ...

哈哈,那一起加油,早点拿到TOWER

出0入0汤圆

 楼主| 发表于 2014-8-31 17:17:20 | 显示全部楼层
浪里白条 发表于 2014-8-31 17:15
哈哈,那一起加油,早点拿到TOWER

一起努力,哈哈!

出0入0汤圆

发表于 2014-8-31 17:32:05 | 显示全部楼层
楼主最近帖子质量很高啊  都是原创的   给力!

出0入0汤圆

 楼主| 发表于 2014-8-31 17:33:19 | 显示全部楼层
abszy 发表于 2014-8-31 17:32
楼主最近帖子质量很高啊  都是原创的   给力!

一切为了TOWER

出0入0汤圆

发表于 2014-8-31 17:36:12 | 显示全部楼层


楼主最近再多发发原创的心得  让大家一起跟着学学   

希望莫大能多给原创帖子加精

出0入0汤圆

 楼主| 发表于 2014-8-31 17:37:50 | 显示全部楼层
abszy 发表于 2014-8-31 17:36
楼主最近再多发发原创的心得  让大家一起跟着学学   

希望莫大能多给原创帖子加精 ...

回头我再整理看看,看有没有能放出来的

出0入0汤圆

发表于 2014-8-31 18:05:07 | 显示全部楼层
玉在哪?同求,嘿嘿

出0入4汤圆

发表于 2014-8-31 18:53:11 | 显示全部楼层
不明觉厉

出100入101汤圆

发表于 2014-8-31 20:07:47 | 显示全部楼层
LZ帖子质量很高!

出0入0汤圆

 楼主| 发表于 2014-8-31 20:10:28 | 显示全部楼层

其实不难的,呵呵!

出0入0汤圆

发表于 2014-8-31 20:42:23 | 显示全部楼层
谢谢楼主提供的资料

出0入0汤圆

发表于 2014-8-31 21:17:29 | 显示全部楼层
不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢

出0入0汤圆

发表于 2014-8-31 21:24:44 | 显示全部楼层
楼主的原创帖好厉害啊

出0入0汤圆

发表于 2014-8-31 21:25:36 | 显示全部楼层
支持原创作品,感谢分享

出0入0汤圆

发表于 2014-8-31 21:26:27 | 显示全部楼层

这个趋势,应该快了啊

出0入0汤圆

 楼主| 发表于 2014-8-31 22:25:46 | 显示全部楼层
qinshiysb 发表于 2014-8-31 21:26
这个趋势,应该快了啊

谢谢捧场哦!

出10入0汤圆

发表于 2014-8-31 23:54:56 来自手机 | 显示全部楼层
mark!学习了!!

出0入0汤圆

 楼主| 发表于 2014-9-1 00:03:59 | 显示全部楼层
dgtg 发表于 2014-8-31 23:54
mark!学习了!!

有问题可以交流啊!

出0入0汤圆

发表于 2014-9-1 00:07:08 | 显示全部楼层
收下  谢谢楼主               

出0入0汤圆

发表于 2014-9-1 00:12:28 | 显示全部楼层
谢谢楼主  分享               

出0入0汤圆

 楼主| 发表于 2014-9-1 10:08:12 | 显示全部楼层

谢谢参观

出0入0汤圆

发表于 2014-9-1 10:23:16 | 显示全部楼层
好贴就得顶!!

出0入0汤圆

发表于 2014-9-1 11:27:30 | 显示全部楼层
分析MQX驱动架构

架构是个什么意思呢?

出0入0汤圆

发表于 2014-9-1 12:51:55 | 显示全部楼层
好长,不明觉厉~

出0入0汤圆

 楼主| 发表于 2014-9-1 20:25:56 | 显示全部楼层
songjie 发表于 2014-9-1 11:27
分析MQX驱动架构

架构是个什么意思呢?

找不到合适的词,呵呵,语文学的不好!

出0入0汤圆

发表于 2014-9-1 20:33:17 来自手机 | 显示全部楼层
谢谢分享,楼主真厉害呀

出0入0汤圆

 楼主| 发表于 2014-9-1 20:49:52 | 显示全部楼层
wxfje 发表于 2014-9-1 20:33
谢谢分享,楼主真厉害呀

从MQX源码中一点一点学,有可能断章取义了,但能用,呵呵

出0入0汤圆

发表于 2014-9-1 21:19:06 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 20:49
从MQX源码中一点一点学,有可能断章取义了,但能用,呵呵

这已经很厉害了
想问下楼主,这种flash怎么防止坏块呢

出0入0汤圆

 楼主| 发表于 2014-9-1 21:23:20 | 显示全部楼层
wxfje 发表于 2014-9-1 21:19
这已经很厉害了
想问下楼主,这种flash怎么防止坏块呢

我用的时候用文件系统,会自己检测坏块,原理没研究过!

出0入0汤圆

发表于 2014-9-1 21:29:11 | 显示全部楼层
支持原创,,支持精华··········
话说马上也要进入MQX学习了,先收藏先

出0入0汤圆

发表于 2014-9-1 22:20:19 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 20:25
找不到合适的词,呵呵,语文学的不好!

没有, 我看很多的 招聘上面都是要 熟悉什么什么 架构,

不是很 明白 架构的 意思~~~

出0入0汤圆

 楼主| 发表于 2014-9-1 22:21:42 | 显示全部楼层
songjie 发表于 2014-9-1 22:20
没有, 我看很多的 招聘上面都是要 熟悉什么什么 架构,

不是很 明白 架构的 意思~~~

框架中构造,呵呵!

出0入0汤圆

发表于 2014-9-1 22:22:19 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:21
框架中构造,呵呵!

还是不明白~

出0入0汤圆

 楼主| 发表于 2014-9-1 22:23:30 | 显示全部楼层

你写程序之前是不是得先考虑大概的框架啊!

出0入0汤圆

发表于 2014-9-1 22:24:14 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:23
你写程序之前是不是得先考虑大概的框架啊!

不是都差不多啊~~~·  .c .h~

出0入0汤圆

 楼主| 发表于 2014-9-1 22:27:26 | 显示全部楼层
songjie 发表于 2014-9-1 22:24
不是都差不多啊~~~·  .c .h~

呵呵,建议你多看看小的OS,像UCOS、RTT、MQX、RTOS、FREEOS之类的代码,那里面有一些软件思想可以学习!

出0入0汤圆

发表于 2014-9-1 22:29:01 | 显示全部楼层
songjie 发表于 2014-9-1 22:24
不是都差不多啊~~~·  .c .h~

哈哈,典型的想到哪写到哪
如果有一定的框架的话,以后写程序就按这个框架模式走,就不用做很多重复的工作
要做的就是在框架下不断的添加功能应用,开发效率会高很多
想到哪写到哪就会导致很多重复劳动,而且程序看起来也不是很有条理

出0入0汤圆

发表于 2014-9-1 22:29:05 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:27
呵呵,建议你多看看小的OS,像UCOS、RTT、MQX、RTOS、FREEOS之类的代码,那里面有一些软件思想可以学习! ...

正在看 ucos ~  

RTOS 了解过~

出0入0汤圆

发表于 2014-9-1 22:30:13 | 显示全部楼层
cn_x 发表于 2014-9-1 22:29
哈哈,典型的想到哪写到哪
如果有一定的框架的话,以后写程序就按这个框架模式走,就不用做很多重复的工 ...

您的意思是 模块化 吧~~~  在相关的模块中,增加 相关的函数 ?

类似于 C++ 的类 ,增加 删除 功能?

出0入0汤圆

 楼主| 发表于 2014-9-1 22:31:43 | 显示全部楼层
songjie 发表于 2014-9-1 22:30
您的意思是 模块化 吧~~~  在相关的模块中,增加 相关的函数 ?

类似于 C++ 的类 ,增加 删除 功能? ...

差不多!

出0入0汤圆

发表于 2014-9-1 22:35:10 | 显示全部楼层

IC的 一个 .c . H
SPI 的 一个.c  .h
Uart 的一个 .c 。h

LCD 的

LED 的

按键的

7816的

14443的

Rf的

USB 的

等等  吧     用哪个  挂那个的 include<.h>吧 ,不能的 屏蔽掉吧 ~~~~

   框架大概是 这个 意思吧??????????????

出0入0汤圆

发表于 2014-9-1 22:36:06 | 显示全部楼层
当然还有很多 中断的

timer 的

GPIO的 ,

各种宏的

各种结构体的

数据结构的·~~~

等等

出0入0汤圆

 楼主| 发表于 2014-9-1 22:39:08 | 显示全部楼层
songjie 发表于 2014-9-1 22:35
IC的 一个 .c . H
SPI 的 一个.c  .h
Uart 的一个 .c 。h

不尽然是!呵呵,你看UCOS,你觉得他那里的驱动程序怎么样?是不是都差不多?一个OPEN、一个WRITE、一个READ、一个CLOSE、一个IOCTRL,但是就这几个函数就可以做出不同的底层驱动!也就是说,你在编程的时候往往需要先考虑好怎么做最方便,而你考虑好之后执行的时候那个思路,就叫作大概的程序架构!

出0入0汤圆

 楼主| 发表于 2014-9-1 22:39:52 | 显示全部楼层
songjie 发表于 2014-9-1 22:36
当然还有很多 中断的

timer 的

我觉得是一种思路,不是具体的哪个东西!

出0入0汤圆

发表于 2014-9-1 22:46:16 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:39
我觉得是一种思路,不是具体的哪个东西!


高手 请教一下呢
比如我有了
uart.c uart.h
gsm.c gsm.h
main.c

我gsm.c中需要调用uart.c中的函数,这种做法合理不
如果不合理,改进的办法是什么呢

出0入0汤圆

发表于 2014-9-1 22:49:17 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:39
不尽然是!呵呵,你看UCOS,你觉得他那里的驱动程序怎么样?是不是都差不多?一个OPEN、一个WRITE、一个R ...

让我先 理解理解~~

出0入0汤圆

 楼主| 发表于 2014-9-1 22:51:16 | 显示全部楼层
浪里白条 发表于 2014-9-1 22:46
高手 请教一下呢
比如我有了
uart.c uart.h

你要分两个对像来处理的话,为了移植方便,比如下次你用gsm模块调用的是SPI模块的同样的一个函数,我一般的做法是在GSM模块中添加一个函数指针,然后在初始化的时候从UART模块或SPI模块中把函数地址拿出来初始化此指针,而此指针就是GSM模块中的变量,需要注意的是在用此函数的之前要判断他是否已经被赋值,不然很容易出现野指针,呵呵!

出0入0汤圆

发表于 2014-9-2 08:01:30 来自手机 | 显示全部楼层
这一套驱动都是从linux来得,看来linux才是鼻祖

出0入0汤圆

发表于 2014-9-2 08:13:09 | 显示全部楼层
还不错!!!!!!!!!

出0入0汤圆

发表于 2014-9-2 08:25:23 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 22:51
你要分两个对像来处理的话,为了移植方便,比如下次你用gsm模块调用的是SPI模块的同样的一个函数,我一般 ...

感谢回复,又学到知识了。

出0入0汤圆

 楼主| 发表于 2014-9-2 12:25:40 | 显示全部楼层
rootxie 发表于 2014-9-2 08:01
这一套驱动都是从linux来得,看来linux才是鼻祖

那当然,无数人的智慧积累啊!

出0入0汤圆

 楼主| 发表于 2014-9-2 12:32:43 | 显示全部楼层
浪里白条 发表于 2014-9-2 08:25
感谢回复,又学到知识了。

呵呵,多交流啊!

出0入0汤圆

发表于 2014-9-2 21:10:45 | 显示全部楼层
wangpengcheng 发表于 2014-9-1 21:23
我用的时候用文件系统,会自己检测坏块,原理没研究过!

这样呀,谢谢您

出0入0汤圆

发表于 2014-9-2 21:12:48 | 显示全部楼层
rootxie 发表于 2014-8-31 21:17
不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢

这个可以设置的,但一般都采用默认的

出0入0汤圆

 楼主| 发表于 2014-9-2 21:14:13 | 显示全部楼层
rootxie 发表于 2014-8-31 21:17
不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢

不一定哦,前几天发现不能全靠编译器!

出0入0汤圆

发表于 2014-9-2 21:17:10 | 显示全部楼层
wangpengcheng 发表于 2014-9-2 21:14
不一定哦,前几天发现不能全靠编译器!

编译器在大部份情况下还是靠得住的

出0入0汤圆

 楼主| 发表于 2014-9-2 21:21:44 | 显示全部楼层
holts2 发表于 2014-9-2 21:17
编译器在大部份情况下还是靠得住的

呵呵,有些情况还真不好查,我那个问题后来是靠猜的!

出0入0汤圆

发表于 2014-9-2 21:27:07 | 显示全部楼层
wangpengcheng 发表于 2014-9-2 21:21
呵呵,有些情况还真不好查,我那个问题后来是靠猜的!

能否开个贴细说分享下哈

出0入0汤圆

 楼主| 发表于 2014-9-2 21:28:15 | 显示全部楼层
holts2 发表于 2014-9-2 21:27
能否开个贴细说分享下哈

不好说,呵呵,能开早就开了,还能赚飞币,具体情况比较复杂!

出0入0汤圆

发表于 2014-9-2 21:46:29 | 显示全部楼层
了解一下这方面的知识,虽然用不上

出0入0汤圆

 楼主| 发表于 2014-9-2 21:47:33 | 显示全部楼层
taojie 发表于 2014-9-2 21:46
了解一下这方面的知识,虽然用不上

要做单片机,迟早能用上,呵呵!

出0入0汤圆

发表于 2014-9-2 23:26:39 | 显示全部楼层
来看详解的           

出0入0汤圆

发表于 2014-9-2 23:31:29 来自手机 | 显示全部楼层
这个不错

出0入0汤圆

发表于 2014-9-4 10:57:49 | 显示全部楼层
mark            

出0入0汤圆

发表于 2014-9-27 20:45:24 | 显示全部楼层
mark下 备用

出0入0汤圆

发表于 2014-9-27 22:17:11 | 显示全部楼层
flash 要处理写平衡、坏块管理吧

出0入0汤圆

 楼主| 发表于 2014-9-27 23:35:52 | 显示全部楼层
swap2013 发表于 2014-9-27 22:17
flash 要处理写平衡、坏块管理吧

好像文件系统中有!

出0入0汤圆

发表于 2014-9-28 17:38:44 | 显示全部楼层
linux和MQX的驱动结构原理是一样的吗?

出0入0汤圆

发表于 2014-9-30 14:55:16 | 显示全部楼层
收藏

出0入0汤圆

发表于 2014-10-1 10:23:12 | 显示全部楼层
谢谢了,支持一下

出0入0汤圆

发表于 2014-11-30 20:23:22 | 显示全部楼层
帮顶,标记一下。 飞思卡尔SPI驱动

出0入0汤圆

发表于 2014-12-1 12:11:03 | 显示全部楼层
谢谢分享!!

出0入0汤圆

发表于 2014-12-1 12:21:54 | 显示全部楼层
顶                                             

出0入0汤圆

发表于 2014-12-1 12:22:16 | 显示全部楼层
顶                                                                                                            

出0入0汤圆

发表于 2014-12-1 13:42:53 | 显示全部楼层
可以像 epprom那样随即写不,擦除算法均衡不?

出0入0汤圆

发表于 2014-12-1 13:53:39 | 显示全部楼层
楼主费心了

出0入0汤圆

发表于 2014-12-1 13:58:07 | 显示全部楼层
MQX自带的内部Flash驱动 支持哪些厂家的芯片 好像不同的厂家需要进行移植才能用

出0入0汤圆

发表于 2014-12-2 13:44:39 | 显示全部楼层
感谢分享,这个确实实用,收藏先
楼主辛苦

出0入0汤圆

发表于 2014-12-2 14:55:22 | 显示全部楼层
谢谢分享,lz辛苦

出0入0汤圆

发表于 2014-12-31 09:40:25 | 显示全部楼层
楼主,请教一下,MQX的驱动不知道和Linux的相比怎么样?  是不是都有现成的? 在开发包里

出0入0汤圆

 楼主| 发表于 2015-1-1 11:36:52 | 显示全部楼层
craigtao 发表于 2014-12-31 09:40
楼主,请教一下,MQX的驱动不知道和Linux的相比怎么样?  是不是都有现成的? 在开发包里 ...

有BSP与PSP,一般不用改动!

出0入0汤圆

发表于 2015-1-1 19:58:50 | 显示全部楼层
wangpengcheng 发表于 2015-1-1 11:36
有BSP与PSP,一般不用改动!

哦哦,这么说开发起来还是挺容易的?

出0入0汤圆

发表于 2015-1-1 20:00:00 | 显示全部楼层
wangpengcheng 发表于 2015-1-1 11:36
有BSP与PSP,一般不用改动!

这么说开发还是挺容易的?

出0入0汤圆

发表于 2015-1-1 20:11:04 | 显示全部楼层
craigtao 发表于 2015-1-1 20:00
这么说开发还是挺容易的?

肯定不容易,是会者不 难

出0入0汤圆

发表于 2015-1-1 20:13:01 | 显示全部楼层
holts2 发表于 2015-1-1 20:11
肯定不容易,是会者不 难

哈哈,,下一个目标是K46?

出0入0汤圆

发表于 2015-1-1 20:20:15 | 显示全部楼层
craigtao 发表于 2015-1-1 20:13
哈哈,,下一个目标是K46?

不,还是K02

出0入0汤圆

发表于 2015-1-3 10:07:29 | 显示全部楼层

嗯嗯,,加油啊,看来你是要搭建一个大的系统啊,,以后向你学习啊,

出0入0汤圆

发表于 2015-1-3 11:35:05 | 显示全部楼层
craigtao 发表于 2015-1-3 10:07
嗯嗯,,加油啊,看来你是要搭建一个大的系统啊,,以后向你学习啊,

没有啦,我只是玩点简单的

出0入0汤圆

发表于 2015-1-3 14:54:06 | 显示全部楼层
holts2 发表于 2015-1-3 11:35
没有啦,我只是玩点简单的

不要谦虚了啦,

出0入0汤圆

发表于 2015-1-3 19:48:28 | 显示全部楼层
好长的代码

出0入0汤圆

 楼主| 发表于 2015-1-5 10:45:39 | 显示全部楼层

还好吧!函数大小都在要求之内

出0入0汤圆

发表于 2015-1-5 10:56:28 | 显示全部楼层
wangpengcheng 发表于 2015-1-5 10:45
还好吧!函数大小都在要求之内

哈哈,看的眼花
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-1 21:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表