完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 lee_st 于 2016-11-8 10:01 编辑
最近一直在玩sam4s16c,网上的所有论坛基本找不到atmel的资料,真心的不喜欢,但是工作需要,没办法。只能静下心来仔细研究Datasheet,别无他径。 内部flash的组织架构见下图 由图可知,flash是由很多的page组成,这个mcu的page size是512bits,而且,每个lock bit锁存8192bits,就是8k。 erase可以是全部,块,页等。 sam4s16c的片内flash大小的1m,0x100000.在片内的起始地址是0x400000,所有的读写都要从这个地址开始。不然会跑飞,我在调试时,试验了。很苦涩。 找了1天的原因,后来发现是我少写了个“0”,写成0x47000了,可能是自己不仔细,也可能是笔者经验不足,当然都是借口。 flash的写步骤是, 第一,先解锁 需要调用解锁函数flash_unlock()在xdk-asf-3.32.0samservicesflash_efc目录下的flash_efc.c文件里 里面很复杂,起初看的很晕。我是一遍又一遍的单步调试才搞明白的。 大家有兴趣可以研究一下,附上代码 uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) { Efc *p_efc; uint32_t ul_actual_start, ul_actual_end; uint16_t us_start_page, us_end_page; uint32_t ul_error; uint16_t us_num_pages_in_region = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; /* Compute actual unlock range and store it */ compute_lock_range(ul_start, ul_end, &ul_actual_start, &ul_actual_end); if (pul_actual_start != NULL) { *pul_actual_start = ul_actual_start; } if (pul_actual_end != NULL) { *pul_actual_end = ul_actual_end; } /* Compute page numbers */ translate_address(&p_efc, ul_actual_start, &us_start_page, 0); translate_address(0, ul_actual_end, &us_end_page, 0); /* Unlock all pages */ while (us_start_page < us_end_page) { ul_error = efc_perform_command(p_efc, EFC_FCMD_CLB, us_start_page); if (ul_error) { return ul_error; } us_start_page += us_num_pages_in_region; } return FLASH_RC_OK; } 第二步 解锁完成后要先擦除,可以选,全部,块或页。 调用库函数flash_erase_sector(),路径同上 这个函数看起来比较简单些,代码如下,有兴趣可以自己研究。 uint32_t flash_erase_sector(uint32_t ul_address) { Efc *p_efc; uint16_t us_page; translate_address(&p_efc, ul_address, &us_page, NULL); if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_ES, us_page)) { return FLASH_RC_ERROR; } return FLASH_RC_OK; } 第三步,可以开始写数据。 调用flash_write()函数,路径同上 代码如下 uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag) { Efc *p_efc; uint32_t ul_fws_temp; uint16_t us_page; uint16_t us_offset; uint32_t writeSize; uint32_t ul_page_addr; uint16_t us_padding; uint32_t ul_error; uint32_t ul_idx; uint32_t *p_aligned_dest; uint8_t *puc_page_buffer = (uint8_t *) gs_ul_page_buffer; translate_address(&p_efc, ul_address, &us_page, &us_offset); #if SAM3S || SAM3N || SAM3XA || SAM3U /* According to the errata, set the wait state value to 6. */ ul_fws_temp = efc_get_wait_state(p_efc); efc_set_wait_state(p_efc, 6); #else UNUSED(ul_fws_temp); #endif /* Write all pages */ while (ul_size > 0) { /* Copy data in temporary buffer to avoid alignment problems. */ writeSize = Min((uint32_t) IFLASH_PAGE_SIZE - us_offset, ul_size); compute_address(p_efc, us_page, 0, &ul_page_addr); us_padding = IFLASH_PAGE_SIZE - us_offset - writeSize; /* Pre-buffer data */ memcpy(puc_page_buffer, (void *)ul_page_addr, us_offset); /* Buffer data */ memcpy(puc_page_buffer + us_offset, p_buffer, writeSize); /* Post-buffer data */ memcpy(puc_page_buffer + us_offset + writeSize, (void *)(ul_page_addr + us_offset + writeSize), us_padding); /* Write page. * Writing 8-bit and 16-bit data is not allowed and may lead to * unpredictable data corruption. */ p_aligned_dest = (uint32_t *) ul_page_addr; for (ul_idx = 0; ul_idx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ul_idx) { *p_aligned_dest++ = gs_ul_page_buffer[ul_idx]; } if (ul_erase_flag) { ul_error = efc_perform_command(p_efc, EFC_FCMD_EWP, us_page); } else { ul_error = efc_perform_command(p_efc, EFC_FCMD_WP, us_page); } if (ul_error) { return ul_error; } /* Progression */ p_buffer = (void *)((uint32_t) p_buffer + writeSize); ul_size -= writeSize; us_page++; us_offset = 0; } #if SAM3S || SAM3N || SAM3XA || SAM3U /* According to the errata, restore the wait state value. */ efc_set_wait_state(p_efc, ul_fws_temp); #endif return FLASH_RC_OK; } 这个函数嵌套很深,比较复杂,笔者也是单步调试,好多遍才搞懂。水平有限。 第四步,就是上锁 调用flash_lock()函数,路径同上 代码附上 uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) { Efc *p_efc; uint32_t ul_actual_start, ul_actual_end; uint16_t us_start_page, us_end_page; uint32_t ul_error; uint16_t us_num_pages_in_region = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; /* Compute actual lock range and store it */ compute_lock_range(ul_start, ul_end, &ul_actual_start, &ul_actual_end); if (pul_actual_start != NULL) { *pul_actual_start = ul_actual_start; } if (pul_actual_end != NULL) { *pul_actual_end = ul_actual_end; } /* Compute page numbers */ translate_address(&p_efc, ul_actual_start, &us_start_page, 0); translate_address(0, ul_actual_end, &us_end_page, 0); /* Lock all pages */ while (us_start_page < us_end_page) { ul_error = efc_perform_command(p_efc, EFC_FCMD_SLB, us_start_page); if (ul_error) { return ul_error; } us_start_page += us_num_pages_in_region; } return FLASH_RC_OK; } 官方的库函数,都是很复杂,目前没有简单的寄存器版本,看的很累。有兴趣的自己研究。 片内flash的读,步骤是 解锁,读取,上锁,这个很简单,不在此处多说。 水平和经验有限,请大家多指点,谢谢! 评分
|
||
相关推荐
|
||
生活就像一盒巧克力,你不知道你的下一块口味是什么。
|
|
|
|
|
|
atmel被收购了
|
|
|
|
|
|
请问怎么读取数据呢?
|
|
|
|
|
|
《DNESP32S3使用指南-IDF版_V1.6》第三十章 DHT11数字温湿度传感器
464 浏览 0 评论
643 浏览 0 评论
【敏矽微ME32G070开发板免费体验】之原厂2812测试例程解析
942 浏览 0 评论
1028 浏览 2 评论
《DNESP32S3使用指南-IDF版_V1.6》第二十六章 INFRARED_RECEPTION实验
724 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12043 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-27 05:51 , Processed in 0.746664 second(s), Total 62, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号