【分享】配合前几天发的SPI Flash的驱动,分析MQX驱动架构!
本帖最后由 FSL_TICS_ZJJ 于 2014-9-11 16:05 编辑首先声明:以下都是我个人在MQX学习、使用过程中的一些见解,当然,里面可能会有一些说的不是很明白,我希望我扔出来的这块砖头,能引来他山之玉{:titter:}
在参考了MQX自带的内部Flash驱动中,我看到Flash其实可以分区进行不同区域来做驱动,比如我自己的这个驱动,就是将一个8M的SPI Flash分为两块,前2M是一块,后面6M是一块,而每个块我们都需要不同的参数来进行标记,我做了一个Flash Block的结构体如下:
typedef struct spi_flash_block
{
char *block_name; //分块名称
uint32_t block_start_address; //块起始地址
uint32_t block_end_address; //块结束地址
uint32_t sector_address; //当前操作扇区地址
uint32_t sector_size; //驱动大小
uint8_t *sector_buff; //CACHE指针
bool sector_change_flag; //写标志
}SPI_FLASH_BLOCK, *SPI_FLASH_BLOCK_PTR;
然后定义两个区,我将一个命名为系统区,另一个命名为用户区:
static SPI_FLASH_BLOCK spi_flash_block_descr[] = {
{"system", 0x00000000, 0x001FFFFF, 0x00000000, SPI_MEMORY_SECTOR_SIZE, NULL, FALSE},
{"user", 0x00200000, 0x007FFFFF, 0x00200000, SPI_MEMORY_SECTOR_SIZE, NULL, FALSE},
{0, 0, 0, 0, 0, 0 }
};
当然还有一个比较重要的参数,就是SPI口了,这个参数可以用来改变SPI口,因为我的Flash挂接在SPI0上,所以如下定义:
#if BSP_SPI_MEMORY_CHANNEL == 0
#define SPI_CHANNEL SPI0_BASE_PTR
#elif BSP_SPI_MEMORY_CHANNEL == 1
#define SPI_CHANNEL SPI1_BASE_PTR
#elif BSP_SPI_MEMORY_CHANNEL == 2
#define SPI_CHANNELSPI2_BASE_PTR
#else
#error Unsupported SPI channel number. Please check settings of BSP_SPI_MEMORY_CHANNEL in BSP.
#endif
而为了更方便将来对驱动的修改,我添加了一个公共的数据结构,虽然目前没有其它参数,但如果以后要使用,可以在此结构体里面添加:
typedef struct spi_flash_struct
{
SPI_MemMapPtr SPIx;
}SPI_FLASH_STRUCT, *SPI_FLASH_STRUCT_PTR;
好了,前期的准备工作我们做好了,接下来我们要做驱动了,其实OS的驱动不外乎就是几个函数,我要完成以下几个函数的编写:
_mqx_uint _spi_flash_install(char *identifier, SPI_FLASH_STRUCT const *init_ptr);
_mqx_int _spi_flash_init(const void *init_data_ptr, void **io_info_ptr_ptr);
_mqx_int _spi_flash_open(MQX_FILE_PTR fd_ptr, char *open_name_ptr, char *flags);
_mqx_int _spi_flash_close(MQX_FILE_PTR fd_ptr);
_mqx_int _spi_flash_read(MQX_FILE_PTR fd_ptr, char *data_ptr, _mqx_int num);
_mqx_int _spi_flash_write(MQX_FILE_PTR fd_ptr, char *data_ptr, _mqx_int num);
_mqx_int _spi_flash_ioctl(MQX_FILE_PTR fd_ptr, _mqx_uint cmd, void *param_ptr);
_mqx_int _spi_flash_uninstall(IO_DEVICE_STRUCT_PTR io_dev_ptr);
第一个当然是install函数,我写的函数如下:
_mqx_uint _spi_flash_install ( char *identifier, SPI_FLASH_STRUCT const *init_ptr)
{
SPI_FLASH_STRUCT_PTR spi_flash_data = _mem_alloc_system(sizeof(SPI_FLASH_STRUCT)); //定义了公共的变量
spi_flash_init(spi_flash_data, NULL); //初始化端口以及数据
return (_io_dev_install_ext( //进行驱动注册
identifier,
_spi_flash_open,
_spi_flash_close,
_spi_flash_read,
_spi_flash_write,
_spi_flash_ioctl,
_spi_flash_uninstall,
spi_flash_data));
}
这里我要注明一下,其实很多驱动都可以在驱动OPEN的时候再进行初始化,但是考虑到我初始里面有个公共的变量SPI口的选择,所以我将初始化功能放在了此处。此函数要在使用SPI Flash之前调用,用来注册驱动。使用方法:
_spi_flash_install("spi_flash:", NULL);
第二个函数是相对install来说的,就是uninstall函数:
_mqx_int _spi_flash_uninstall( IO_DEVICE_STRUCT_PTR io_dev_ptr)
{
SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)io_dev_ptr->DRIVER_INIT_PTR;
_mem_free(user_data); //因为在install函数中申请了内存,所以在此要将内存释放掉,不然会造成内存泄漏
io_dev_ptr->DRIVER_INIT_PTR = NULL; //将驱动数据清空,防止野指针的出现
return MQX_OK;
}
第三个函数当然就是初始化了:
_mqx_int _spi_flash_init( const void*init_data_ptr, void **io_info_ptr_ptr )
{
SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)init_data_ptr;
user_data->SPIx = SPI_CHANNEL;
hal_spi0_init(user_data->SPIx);
return SPI_FLASH_OK;
}
初始化函数就比较简单,我只是选择了SPI接口,然后配置硬件SPI口。
第四个函数是OPEN:
_mqx_int _spi_flash_open ( MQX_FILE_PTR fd_ptr, char *open_name_ptr, char *flags)
{
SPI_FLASH_BLOCK_PTR user_block = NULL;
int i = 0;
for(i = 0; spi_flash_block_descr.block_name != 0; i++)
{
if(0 != strstr(open_name_ptr, spi_flash_block_descr.block_name)) //用块名称对块进行查找
{
user_block = (SPI_FLASH_BLOCK_PTR)_mem_alloc_system(sizeof(SPI_FLASH_BLOCK)); //找到块之后申请内存作为当前打开块的初始化数据
memcpy(user_block, &(spi_flash_block_descr), sizeof(SPI_FLASH_BLOCK)); //对块数据进行初始化
fd_ptr->DEV_DATA_PTR = user_block; //将块指针赋值给当前打开的驱动数据指针
break;
}
}
if(user_block == NULL)
{
return IO_ERROR;
}
user_block->sector_buff = _mem_alloc_system(user_block->sector_size); //给CACHE申请内存
fd_ptr->SIZE = user_block->block_end_address - user_block->block_start_address + 1;//初始化当前驱动块的尺寸
fd_ptr->LOCATION = user_block->block_start_address; //初始化LOCATION
read_sector(fd_ptr);//初始化当前CACHE
return MQX_OK;
}
这个函数我也是参考原MQX中Flash驱动中的OPEN函数,这块有点说道,因为Flash分块了,所以在OPEN的时候需要做一件事情,驱动我目前要OPEN的是哪一个块,使用如下:
fopen("spi_flash:system", NULL);
或者
fopen("spi_flash:user, NULL);
第五个函数close,这个函数相对比较简单,就是释放Open时申请的所有资源,然后将指针清空:
_mqx_int _spi_flash_close ( MQX_FILE_PTR fd_ptr )
{
SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
fflush(fd_ptr);
_mem_free(user_block->sector_buff);
_mem_free(user_block);
fd_ptr->DEV_DATA_PTR = NULL;
return MQX_OK;
}
第六个函数read,这个函数其实也没什么,直接从Flash中读数据,但是这里需要注意的是要改变CACHE的切换:
_mqx_int _spi_flash_read ( MQX_FILE_PTR fd_ptr,char *data_ptr, _mqx_int num )
{
SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
uint32_t sector_start = user_block->sector_address;
uint32_t sector_next_start = user_block->sector_address + user_block->sector_size;
uint8_t *buff_ptr;
_mqx_int location = fd_ptr->LOCATION;
_mqx_int over_num = num;
_mqx_int read_num_one_time;
do
{
if((location < sector_start) || (location >= sector_next_start))
{
uint32_t error = switching_sector(fd_ptr, location); //如果地址范围超出当前CACHE,要进行切换
if(error != SPI_FLASH_OK)
{
return error;
}
sector_start = user_block->sector_address;
sector_next_start = user_block->sector_address + user_block->sector_size;
}
buff_ptr = user_block->sector_buff + (location & (user_block->sector_size - 1));
read_num_one_time = ((location + over_num) >= sector_next_start) ? sector_next_start - location : over_num;
memcpy(data_ptr, buff_ptr,read_num_one_time);
data_ptr += read_num_one_time;
location += read_num_one_time;
over_num -= read_num_one_time;
}while(over_num > 0);
fd_ptr->LOCATION += num;
return num;
}
第七个函数write,写函数跟读函数一样,要注意CACHE切换,另外,写函数还要注意一定要将写标志置起来,此标志是为了CACHE切换时知道Flash是否需要改变:
_mqx_int _spi_flash_write (MQX_FILE_PTR fd_ptr,char *data_ptr, _mqx_int num )
{
SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
uint32_t sector_start = user_block->sector_address;
uint32_t sector_next_start = user_block->sector_address + user_block->sector_size;
uint8_t *buff_ptr;
_mqx_int location = fd_ptr->LOCATION;
_mqx_int write_num_one_time;
_mqx_int over_num = num;
do
{
if((location < sector_start) || (location >= sector_next_start))
{
uint32_t error = switching_sector(fd_ptr, location);
if(error != SPI_FLASH_OK)
{
return error;
}
sector_start = user_block->sector_address;
sector_next_start = user_block->sector_address + user_block->sector_size;
}
buff_ptr = user_block->sector_buff + (location & (user_block->sector_size - 1));
write_num_one_time = ((location + over_num) >= sector_next_start) ? sector_next_start - location : over_num;
memcpy(buff_ptr, data_ptr, write_num_one_time);
user_block->sector_change_flag = TRUE;
data_ptr += write_num_one_time;
location += write_num_one_time;
over_num -= write_num_one_time;
if(location >= sector_next_start)
{
write_sector(fd_ptr);
}
}while(over_num > 0);
fd_ptr->LOCATION += num;
return num;
}
最后一个IOCTRL函数,在驱动中,此函数的重要性我想我就不用说了,下面是我的函数,因为只用到了一部分命令,所以函数不算太大,MQX中Flash的IOCTRL函数那才叫个大呢:
_mqx_int _spi_flash_ioctl (MQX_FILE_PTR fd_ptr, _mqx_uint cmd,void *param_ptr )
{
SPI_FLASH_STRUCT_PTR user_data = (SPI_FLASH_STRUCT_PTR)fd_ptr->DEV_PTR->DRIVER_INIT_PTR;
SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
_mqx_int result = MQX_OK;
_mqx_uint_ptr uparam_ptr;
switch(cmd)
{
case IO_IOCTL_FLUSH_OUTPUT: //Flush功能,这个功能很有用,我一开始没有加此命令,结果文件写完后下次开机就不见了,大家知道原因吧,哈哈
write_sector(fd_ptr);
break;
case FLASH_IOCTL_ERASE_CHIP:
hal_spi_dev_flash_erase_dev(user_data->SPIx);
hal_spi_dev_flash_read(user_data->SPIx, user_block->sector_address, user_block->sector_buff, user_block->sector_size);
break;
case IO_IOCTL_DEVICE_IDENTIFY:
/*
** This is to let the upper layer know what kind of device this is.
** It's a physical flash device, capable of being erased, read, seeked,
** and written. Flash devices are not interrupt driven, so
** IO_DEV_ATTR_POLL is included.
*/
uparam_ptr = (_mqx_uint_ptr)param_ptr;
uparam_ptr = IO_DEV_TYPE_PHYS_FLASHX;
uparam_ptr = IO_DEV_TYPE_LOGICAL_MFS;
uparam_ptr = IO_DEV_ATTR_ERASE | IO_DEV_ATTR_POLL
| IO_DEV_ATTR_READ | IO_DEV_ATTR_SEEK |
IO_DEV_ATTR_WRITE;
break;
case IO_IOCTL_GET_NUM_SECTORS:
*(uint32_t *)param_ptr = fd_ptr->SIZE / SPI_MEMORY_SECTOR_SIZE;
break;
case IO_IOCTL_GET_BLOCK_SIZE:
case FLASH_IOCTL_GET_SECTOR_SIZE:
/* returns the fixed size for MFS sector size */
*(uint32_t *)param_ptr = user_block->sector_size;
break;
case IO_IOCTL_SEEK: //这个命令一定要添加,因为我们Flash分块了,所以起始地址不一样,如果不加此功能,那么它起始地址都是默认从0开始,那第二个 //块肯定会读写错误
fd_ptr->LOCATION += user_block->block_start_address;
break;
default:
result = IO_ERROR_INVALID_IOCTL_CMD;
}
return result;
}
最后的最后,还有一个函数我必须得说明一下,切换扇区,需要注意的是一开始定义的写标志在这里起了作用,看代码:
uint32_t switching_sector(MQX_FILE_PTR fd_ptr, _mqx_int address)
{
SPI_FLASH_BLOCK_PTR user_block = (SPI_FLASH_BLOCK_PTR)fd_ptr->DEV_DATA_PTR;
uint32_t error_code;
//取旧扇区的起始地址
_mqx_int sector_start_address = address & (~(user_block->sector_size - 1));
//写Flash
if(user_block->sector_change_flag)
error_code = write_sector(fd_ptr);
if(error_code != SPI_FLASH_OK)
{
return error_code;
}
//更新扇区的起始地址参数
user_block->sector_address = sector_start_address;
//重新填充CACHE
error_code = read_sector(fd_ptr);
if(error_code != SPI_FLASH_OK)
{
return error_code;
}
return SPI_FLASH_OK;
}
OK了,其它的一些再底层的函数我就没有必要一一说明了!尾部再将源文件传上来:
砖来了,玉在哪?{:titter:}
感谢分享,这个确实实用,收藏先
楼主辛苦 哈,楼主讲得好详细,这个可以加精 浪里白条 发表于 2014-8-31 17:10
哈,楼主讲得好详细,这个可以加精
谢谢捧场啊,你的飞币飞升啊!{:lol:} 为了追赶你,得搞有质量的帖子才成啊! 本帖最后由 wangpengcheng 于 2014-8-31 17:15 编辑
晕,代码里面想加红,没加上{:titter:},希望大家看的时候要多注意带字样的那些代码行! wangpengcheng 发表于 2014-8-31 17:12
谢谢捧场啊,你的飞币飞升啊! 为了追赶你,得搞有质量的帖子才成啊! ...
哈哈,那一起加油,早点拿到TOWER 浪里白条 发表于 2014-8-31 17:15
哈哈,那一起加油,早点拿到TOWER
一起努力,哈哈! 楼主最近帖子质量很高啊都是原创的 给力! abszy 发表于 2014-8-31 17:32
楼主最近帖子质量很高啊都是原创的 给力!
一切为了TOWER{:titter:} wangpengcheng 发表于 2014-8-31 17:33
一切为了TOWER
楼主最近再多发发原创的心得让大家一起跟着学学
希望莫大能多给原创帖子加精 abszy 发表于 2014-8-31 17:36
楼主最近再多发发原创的心得让大家一起跟着学学
希望莫大能多给原创帖子加精 ...
回头我再整理看看,看有没有能放出来的{:titter:} 玉在哪?同求,嘿嘿 不明觉厉 LZ帖子质量很高! oner 发表于 2014-8-31 18:53
不明觉厉
其实不难的,呵呵! 谢谢楼主提供的资料 不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢 楼主的原创帖好厉害啊 支持原创作品,感谢分享 wangpengcheng 发表于 2014-8-31 17:33
一切为了TOWER
这个趋势,应该快了啊 qinshiysb 发表于 2014-8-31 21:26
这个趋势,应该快了啊
谢谢捧场哦! mark!学习了!! dgtg 发表于 2014-8-31 23:54
mark!学习了!!
有问题可以交流啊! 收下谢谢{:handshake:}楼主 谢谢楼主分享{:handshake:} zwei99999999 发表于 2014-9-1 00:12
谢谢楼主分享
谢谢参观 好贴就得顶!! 分析MQX驱动架构
架构是个什么意思呢? 好长,不明觉厉~ songjie 发表于 2014-9-1 11:27
分析MQX驱动架构
架构是个什么意思呢?
找不到合适的词,呵呵,语文学的不好! 谢谢分享,楼主真厉害呀 wxfje 发表于 2014-9-1 20:33
谢谢分享,楼主真厉害呀
从MQX源码中一点一点学,有可能断章取义了,但能用,呵呵 wangpengcheng 发表于 2014-9-1 20:49
从MQX源码中一点一点学,有可能断章取义了,但能用,呵呵
这已经很厉害了
想问下楼主,这种flash怎么防止坏块呢 wxfje 发表于 2014-9-1 21:19
这已经很厉害了
想问下楼主,这种flash怎么防止坏块呢
我用的时候用文件系统,会自己检测坏块,原理没研究过! 支持原创,,支持精华··········
话说马上也要进入MQX学习了,先收藏先 wangpengcheng 发表于 2014-9-1 20:25
找不到合适的词,呵呵,语文学的不好!
没有, 我看很多的 招聘上面都是要 熟悉什么什么 架构,
不是很 明白 架构的 意思~~~
songjie 发表于 2014-9-1 22:20
没有, 我看很多的 招聘上面都是要 熟悉什么什么 架构,
不是很 明白 架构的 意思~~~
框架中构造,呵呵! wangpengcheng 发表于 2014-9-1 22:21
框架中构造,呵呵!
还是不明白~ songjie 发表于 2014-9-1 22:22
还是不明白~
你写程序之前是不是得先考虑大概的框架啊! wangpengcheng 发表于 2014-9-1 22:23
你写程序之前是不是得先考虑大概的框架啊!
不是都差不多啊~~~·.c .h~ songjie 发表于 2014-9-1 22:24
不是都差不多啊~~~·.c .h~
呵呵,建议你多看看小的OS,像UCOS、RTT、MQX、RTOS、FREEOS之类的代码,那里面有一些软件思想可以学习! songjie 发表于 2014-9-1 22:24
不是都差不多啊~~~·.c .h~
哈哈,典型的想到哪写到哪
如果有一定的框架的话,以后写程序就按这个框架模式走,就不用做很多重复的工作
要做的就是在框架下不断的添加功能应用,开发效率会高很多
想到哪写到哪就会导致很多重复劳动,而且程序看起来也不是很有条理 wangpengcheng 发表于 2014-9-1 22:27
呵呵,建议你多看看小的OS,像UCOS、RTT、MQX、RTOS、FREEOS之类的代码,那里面有一些软件思想可以学习! ...
正在看 ucos ~
RTOS 了解过~ cn_x 发表于 2014-9-1 22:29
哈哈,典型的想到哪写到哪
如果有一定的框架的话,以后写程序就按这个框架模式走,就不用做很多重复的工 ...
您的意思是 模块化 吧~~~在相关的模块中,增加 相关的函数 ?
类似于 C++ 的类 ,增加 删除 功能? songjie 发表于 2014-9-1 22:30
您的意思是 模块化 吧~~~在相关的模块中,增加 相关的函数 ?
类似于 C++ 的类 ,增加 删除 功能? ...
差不多! wangpengcheng 发表于 2014-9-1 22:31
差不多!
IC的 一个 .c . H
SPI 的 一个.c.h
Uart 的一个 .c 。h
LCD 的
LED 的
按键的
7816的
14443的
Rf的
USB 的
等等吧 用哪个挂那个的 include<.h>吧 ,不能的 屏蔽掉吧 ~~~~
框架大概是 这个 意思吧?????????????? 当然还有很多 中断的
timer 的
GPIO的 ,
各种宏的
各种结构体的
数据结构的·~~~
等等 songjie 发表于 2014-9-1 22:35
IC的 一个 .c . H
SPI 的 一个.c.h
Uart 的一个 .c 。h
不尽然是!呵呵,你看UCOS,你觉得他那里的驱动程序怎么样?是不是都差不多?一个OPEN、一个WRITE、一个READ、一个CLOSE、一个IOCTRL,但是就这几个函数就可以做出不同的底层驱动!也就是说,你在编程的时候往往需要先考虑好怎么做最方便,而你考虑好之后执行的时候那个思路,就叫作大概的程序架构! songjie 发表于 2014-9-1 22:36
当然还有很多 中断的
timer 的
我觉得是一种思路,不是具体的哪个东西! wangpengcheng 发表于 2014-9-1 22:39
我觉得是一种思路,不是具体的哪个东西!
高手 请教一下呢
比如我有了
uart.c uart.h
gsm.c gsm.h
main.c
我gsm.c中需要调用uart.c中的函数,这种做法合理不
如果不合理,改进的办法是什么呢
wangpengcheng 发表于 2014-9-1 22:39
不尽然是!呵呵,你看UCOS,你觉得他那里的驱动程序怎么样?是不是都差不多?一个OPEN、一个WRITE、一个R ...
让我先 理解理解~~ 浪里白条 发表于 2014-9-1 22:46
高手 请教一下呢
比如我有了
uart.c uart.h
你要分两个对像来处理的话,为了移植方便,比如下次你用gsm模块调用的是SPI模块的同样的一个函数,我一般的做法是在GSM模块中添加一个函数指针,然后在初始化的时候从UART模块或SPI模块中把函数地址拿出来初始化此指针,而此指针就是GSM模块中的变量,需要注意的是在用此函数的之前要判断他是否已经被赋值,不然很容易出现野指针,呵呵! 这一套驱动都是从linux来得,看来linux才是鼻祖 还不错!!!!!!!!! wangpengcheng 发表于 2014-9-1 22:51
你要分两个对像来处理的话,为了移植方便,比如下次你用gsm模块调用的是SPI模块的同样的一个函数,我一般 ...
感谢回复,又学到知识了。 rootxie 发表于 2014-9-2 08:01
这一套驱动都是从linux来得,看来linux才是鼻祖
那当然,无数人的智慧积累啊! 浪里白条 发表于 2014-9-2 08:25
感谢回复,又学到知识了。
呵呵,多交流啊! wangpengcheng 发表于 2014-9-1 21:23
我用的时候用文件系统,会自己检测坏块,原理没研究过!
这样呀,谢谢您 rootxie 发表于 2014-8-31 21:17
不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢
这个可以设置的,但一般都采用默认的 rootxie 发表于 2014-8-31 21:17
不明觉厉,貌似结构体编译器都会字节对齐,很浪费内存呢
不一定哦,前几天发现不能全靠编译器! wangpengcheng 发表于 2014-9-2 21:14
不一定哦,前几天发现不能全靠编译器!
编译器在大部份情况下还是靠得住的 holts2 发表于 2014-9-2 21:17
编译器在大部份情况下还是靠得住的
呵呵,有些情况还真不好查,我那个问题后来是靠猜的!{:titter:} wangpengcheng 发表于 2014-9-2 21:21
呵呵,有些情况还真不好查,我那个问题后来是靠猜的!
能否开个贴细说分享下哈 holts2 发表于 2014-9-2 21:27
能否开个贴细说分享下哈
不好说,呵呵,能开早就开了,还能赚飞币,具体情况比较复杂!{:titter:} 了解一下这方面的知识,虽然用不上 taojie 发表于 2014-9-2 21:46
了解一下这方面的知识,虽然用不上
要做单片机,迟早能用上,呵呵! 来看详解的 这个不错 mark mark下 备用 flash 要处理写平衡、坏块管理吧 swap2013 发表于 2014-9-27 22:17
flash 要处理写平衡、坏块管理吧
好像文件系统中有! linux和MQX的驱动结构原理是一样的吗? 收藏{:biggrin:}{:biggrin:} 谢谢了,支持一下 帮顶,标记一下。 飞思卡尔SPI驱动 谢谢分享!! 顶 顶 可以像 epprom那样随即写不,擦除算法均衡不? 楼主费心了{:lol:} MQX自带的内部Flash驱动 支持哪些厂家的芯片 好像不同的厂家需要进行移植才能用 感谢分享,这个确实实用,收藏先
楼主辛苦 谢谢分享,lz辛苦 楼主,请教一下,MQX的驱动不知道和Linux的相比怎么样?是不是都有现成的? 在开发包里 craigtao 发表于 2014-12-31 09:40
楼主,请教一下,MQX的驱动不知道和Linux的相比怎么样?是不是都有现成的? 在开发包里 ...
有BSP与PSP,一般不用改动! wangpengcheng 发表于 2015-1-1 11:36
有BSP与PSP,一般不用改动!
哦哦,这么说开发起来还是挺容易的? wangpengcheng 发表于 2015-1-1 11:36
有BSP与PSP,一般不用改动!
这么说开发还是挺容易的? craigtao 发表于 2015-1-1 20:00
这么说开发还是挺容易的?
肯定不容易,是会者不 难 holts2 发表于 2015-1-1 20:11
肯定不容易,是会者不 难
哈哈,,下一个目标是K46? craigtao 发表于 2015-1-1 20:13
哈哈,,下一个目标是K46?
不,还是K02 holts2 发表于 2015-1-1 20:20
不,还是K02
嗯嗯,,加油啊,看来你是要搭建一个大的系统啊,,以后向你学习啊, craigtao 发表于 2015-1-3 10:07
嗯嗯,,加油啊,看来你是要搭建一个大的系统啊,,以后向你学习啊,
没有啦,我只是玩点简单的 holts2 发表于 2015-1-3 11:35
没有啦,我只是玩点简单的
不要谦虚了啦, 好长的代码 Juggernaut 发表于 2015-1-3 19:48
好长的代码
还好吧!函数大小都在要求之内 wangpengcheng 发表于 2015-1-5 10:45
还好吧!函数大小都在要求之内
哈哈,看的眼花
页:
[1]