[资料] 原创,sam4s16c的片内flash读写

[复制链接]

版主

发表于 2016-11-8 09:28:00   1044 查看 9 回复 显示全部楼层 倒序浏览
分享
本帖最后由 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.0\sam\services\flash_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的读,步骤是
解锁,读取,上锁,这个很简单,不在此处多说。
水平和经验有限,请大家多指点,谢谢!

本帖子中包含更多资源

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

x

评分

参与人数 2积分 +25 收起 理由
neomissing + 5
ElecFans处女座 + 20 原创技术先锋,加分鼓励!

查看全部评分

标签:flash

版主

发表于 2016-11-8 10:08:14    楼主|
谢谢论坛的鼓励,我一定坚持多发原创
回复

点赞 举报

工程师

发表于 2016-11-8 13:07:35  
生活就像一盒巧克力,你不知道你的下一块口味是什么。
回复

点赞 举报

版主

发表于 2016-11-9 00:40:40    楼主|
是的,真理啊,,,,
回复

举报

实习生

发表于 2016-11-11 13:35:31  
atmel被收购了
回复

举报

版主

发表于 2016-11-12 15:48:40    楼主|
恩,高通,又一个巨无霸产生了
回复

点赞 举报

助理工程师

发表于 2016-11-13 10:53:41  
谢谢大家的分享。谢谢。
回复

举报

技术员

发表于 2016-11-13 11:06:05  
学习一下,希望可以互相交流3026827905
回复

点赞 举报

版主

发表于 2016-11-13 11:09:13    楼主|
可以啊,你是哪的?
回复

举报

版主

发表于 2016-11-15 00:23:56    楼主|
我的帖子被很多人推荐了,谢谢支持
回复

点赞 举报

高级模式
您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐 上一条 /8 下一条

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

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区