SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.sydtek.com/
提前说明
SYD8811/SYD8810/SYD8801以及其他SYDTEK下的芯片,都支持内部空间的操作,因为在SYD8801的时候ProfileData空间(芯片默认给用户预留的空间,不用配置就存在),所以这里用3K来代表ProfileData,也不是所有芯片的ProfileData都是3k空间,比如SYD8821就是4K,各个芯片的API名字可能不完全一样,但是原理是一致的。和ProfileData一样,这里使用24K来代表FlashData,FlashData的空间大小是开发者可以配置的,在Studio的Setting中有如下功能,这里选择合适的大小后点击"Write"按钮即可配置自己需要的大小:
SYD8801的falsh空间安排(请看之前博客:http://blog.csdn.net/chengdong1314/article/details/54956664)如下:
SYD8801的flash中有两个区域给用户存储数据使用,一个空间是3K,一个空间是24K.
3K空间操作方法
在库的头文件(lib.h)中定义了如下函数:
/* read&write flash */
extern uint8_t ReadProfileData(uint16_t addr , uint16_t len, uint8_t *p_buf); 返回1代表成功 0代表失败
extern uint8_t WriteProfileData(uint16_t addr , uint16_t len, uint8_t *p_buf); 返回1代表成功 0代表失败
这两个函数可以操作用户3k空间,也就是上面那个图中最后的Profile Paratemers,操作这个空间不需要调用擦除函数,只需要读写就行。
注意:WriteProfileData函数交由底层代码负责写操作,调用WriteProfileData函数的时候底层代码会先把数据放在缓冲区,只用调用了ble_sched_execute函数的时候真正的写flash操作才会起效,因为写flash的时间比较长,所以ble_schedK_execute函数一般在主函数的主循环调用,ble_sched_execute函数相关内容具体请看:http://blog.csdn.net/chengdong1314/article/details/76169279
这里使用如下的测试代码:
while(1)
{
if(get_key()==1){
err=ReadProfileData( currer_address,10,read_buff );
dbg_printf("Read currer_address:%04x \r\n",currer_address);
dbg_printf("[syd8801] err:%04x \r\n",err);
dbg_hexdump("buff:\r\n",read_buff,10);
GPO_CTRL->GPO_4=~GPO_CTRL->GPO_4;
delay_ms(300);
}else if(get_key()==2){
err=WriteProfileData( currer_address,10,buff );
dbg_printf("Write currer_address:%04x \r\n",currer_address);
dbg_printf("[syd8801] err:%04x \r\n",err);
dbg_hexdump("buff:\r\n",buff,10);
GPO_CTRL->GPO_5=~GPO_CTRL->GPO_5;
for(i=0;i<10;i++){
buff[i]++;
}
delay_ms(300);
}else if(get_key()==3){
currer_address +=5;
dbg_printf("currer_address:%04x \r\n",currer_address);
GPO_CTRL->GPO_6=~GPO_CTRL->GPO_6;
delay_ms(300);
}else if(get_key()==4){
currer_address -=5;
dbg_printf("currer_address:%04x \r\n",currer_address);
GPO_CTRL->GPO_7=~GPO_CTRL->GPO_7;
delay_ms(300);
}
led_turn(LED0);
}
当按下开发板的SW1的时候对currer_address地址进行读操作,然后调用dbg_hexdump("buff:\r\n",read_buff,10);把读到的信息答应出来,按下SW2进行写操作,然后调用dbg_hexdump("buff:\r\n",read_buff,10);把学信息答应出来,按下SW3读写地址自加5,按下SW4读写地址自减5.
上面这套程序已经测试OK
注意:这里的写函数都会进行整个扇区的擦除操作,不管写入的数据是多少字节!
这里上传上本博客工程代码:http://download.csdn.net/detail/chengdong1314/9775236
下面是带上蓝牙功能的工程:http://download.csdn.net/detail/chengdong1314/9885501
24K空间操作方法
注意:对于SYD8811/8810,24K空间就是指FLASHDATA,这个空间是用户自己分配的,调用API传入的首地址是0(API接口内部已经自动做了偏移),关于flash分配的问题请看文章:https://blog.csdn.net/chengdong1314/article/details/118210536 ,请使用Studio工具在setting选择卡中的FLASH DATA进行空间分配!
正常情况下从0x19000开始的24K空间用户都是可以使用的,在库的头文件(lib.h)中定义了如下函数:
extern uint8_t ble_flash_erase(uint32_t address, uint8_t num);
extern uint8_t ble_flash_read(uint32_t address, uint8_t len, uint8_t *p_buf);
extern uint8_t ble_flash_write(uint32_t address, uint8_t len, uint8_t *p_buf);
注意:这里的擦除函数ble_flash_erase很关键,使用的时候需谨慎,其中的num变量代表的是要删除多少个扇区,而不是要擦除那个扇区(相对address的偏移),因为擦除函数会参数flash上的内容,所以使用的时候要注意不要擦除不应该擦除的地址!
这些算是flash标准擦除读写函数,这里可以使用下面的测试代码
if(get_key()==1){
/*
uint8_t ble_flash_erase(uint32_t address, uint8_t );
参数 address:要擦除扇区的首地址
num:要擦除的扇区数
注:一个扇区的大小是4096B
用户能够使用的是从0x00019000开始的24KB的空间,最后一个扇区留给协议栈使用
uint8_t ble_flash_read(uint32_t address, uint8_t len, uint8_t *p_buf);
参数 address:要读取flash的首地址
len:要读取flash的长度,单位为byte
p_buf:读取数据保存的位置
uint8_t ble_flash_write(uint32_t address, uint8_t len, uint8_t *p_buf);
参数 address:要写入的flash的首地址
len:要写入flash的长度,单位为byte
p_buf:写入数据保存的位置
*/
//erase
if(sector>=6) sector=0;
dbg_printf("erase user flash addr:%x sector_num:%x start\r\n",USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector,1);
err=ble_flash_erase (USER_FLASH_BASE_ADDR, sector);
if(err) dbg_printf("erase user flash OK\r\n");
else {dbg_printf("erase user flash error\r\n"); break;}
//write
dbg_printf("write user flash addr:%x size:%x start\r\n",USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024,sizeof(write_buff));
err=ble_flash_write (USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024, sizeof(write_buff),write_buff);
if(err) dbg_printf("write user flash OK \r\n");
else {dbg_printf("write user flash error \r\n"); break;}
//read
dbg_printf("read user flash addr:%x size:%x start\r\n",USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024,sizeof(read_buff));
err=ble_flash_read (USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024, sizeof(read_buff),read_buff);
if(err) dbg_printf("read user flash OK\r\n");
else {dbg_printf("read user flash error \r\n"); break;}
//compare
dbg_printf("compare read and write data size:%x start\r\n",sizeof(read_buff));
for(i=0;i<200;i++){
if(write_buff[i] != read_buff[i]) break;
}
if(i<200) dbg_printf("flash operation error \r\n");
else dbg_printf("flash operation ok \r\n");
//disaply
dbg_hexdump("read_buff[0:50]:\r\n",read_buff,50);
sector++;
if(sector>=6) sector=0;
delay_ms(300);
}else if(get_key()==2){
if(sector>=6) continue;
//read
dbg_printf("read user flash addr:%x size:%x start\r\n",USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024,sizeof(read_buff));
err=ble_flash_read (USER_FLASH_BASE_ADDR+USER_FLASH_SECTOR_SIZE*sector+1024, sizeof(read_buff),read_buff);
if(err) dbg_printf("read user flash OK");
else {dbg_printf("read user flash error \r\n"); break;}
//disaply
dbg_hexdump("read_buff[0:50]:\r\n",read_buff,50);
sector++;
if(sector>=6) sector=0;
delay_ms(300);
}
}
这里按下按键1则会进行擦除、写入、读取、比较工作,同时扇区数将会自加,也就是说按下6次按键就能够擦除所有的用户flash空间,按下按键按键2只会进行读取操作,同时扇区数将会自加。
以上代码已经测试成功!
注意:这里的写函数都会进行整个扇区的擦除操作,不管写入的数据是多少字节!
这里上传上本博客使用的工程代码:
http://download.csdn.net/detail/chengdong1314/9775295