目录
概述
本文主要是使用AT32F403A开发板,基于V2库spim外设的使用,分为和操作内部flash一样用来保存数据以及把代码放到外部flash中跑。
串口工具使用的Atlink-ez自带的串口功能。
工程建立、调试工具配置在前面章节有详细介绍。
硬件
硬件方面使用的是参考官方AT32F437 SURF 板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。
如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可):
如下为实物图:
本章是测试的spim的功能,相关原理图如下:
SPIM
AT32F403A支持外部存储器 ,透过spim来扩展flash。spim最大地址段为0x08400000 - 0x093FFFFF(16MB),是AT32 MCU独有的一种flash访问方式。用户可以使用自己的flash作为AT32 MCU的外挂flash。该方式有别于片上Bank1/Bank2,用户可根据具体需求选择是否开启。主要的功能就是可以和主存储器一样用来存放代码以及用来存放数据,spim的操作和主存储器的操作基本一致,但是spim仅允许按字(32bit)或者半字(16bit)操作,在执行读、编程、擦除SPIM前,必须首先执行初始化及解锁操作。
这个和我们上一章的flash的使用基本一致,但是地址是从0x08400000开始,16M的大小。同时基本操作单位为4KB,也就是4KB每页,而且spim是作为外设的所以需要初始化外设。
软件
初始化
板子上接到spim接口的flash的型号是W25QH128A。IO上使用pin PA8、PB10、PB11、PB1、PB6、PB7并都为推挽复用输出模式,因为PB10、PB11是使用spim的重映射功能,所以还需要开启IOMUX时钟和配置重映射功能。
spim io重映射图:
硬件部分初始化完后,就是针对spim接的flash特性设置参数,然后解锁spim。此板子的上使用的W25q128,经过测试使用的FLASH_SPIM_MODEL2,正常运行。
外部flash参数:
初始化代码
/**
* @brief init the spim flash
* @param none
* @retval none
*/
void spim_init(void)
{
gpio_init_type gpio_init_struct;
/* enable the clock */
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE); //开启MUX复用时钟
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); //开启gpio时钟
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); //开启gpiob时钟
/* init spim io */
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //推挽输出模式
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; //复用
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; //无上下拉
gpio_init_struct.gpio_pins = GPIO_PINS_8; //PA8
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_1 | GPIO_PINS_6 | GPIO_PINS_7 | GPIO_PINS_10 | GPIO_PINS_11; //PB1、PB6、PB7、PB10、PB11
gpio_init(GPIOB, &gpio_init_struct);
/* enable spim, and select pb10, pb11 as spim io */
gpio_pin_remap_config(EXT_SPIM_GMUX_1001, TRUE); //spim IO 复用设置
/* in this example, use on-board en25qh128a as spim flash */
flash_spim_model_select(FLASH_SPIM_MODEL2); //选择外部flash 类型
/* unlock the spim flash program erase controller */
while(flash_flag_get(FLASH_SPIM_OBF_FLAG));
flash_spim_unlock(); //spim解锁
while(FLASH->ctrl3_bit.oplk);
/* if the data written to spim flash need to be scrambled, please specify the scrambled range */
flash_spim_encryption_range_set(0); //spim 加密写入结束地址
return;
}
保存数据到spim
解锁都正常后,就可以和操作主存储器的一样了,使用的也是主存储器的api函数,但是写入只能是字和半字的操作,这是用户程序直接访问spim地址并存储数据的功能。
擦除函数:flash_sector_erase(uint32_t sector_address)
写函数(字):flash_word_program(uint32_t address, uint32_t data)
上锁函数:flash_spim_lock(void);
解锁函数:flash_spim_unlock(void);
run in spim
下面是把代码放到spim口接的flash里面运行。
首先先设定keil的rom地址,增加rom2,起始地址为0x08400000,大小为16M,也就是0x1000000,但是不需要勾选。
其次选择flash烧录算法。这个是根据外部flash和IO来选择的,当IO需要重映射的时候选择REMAP1,不重映射时选择REMAP0;flash的闪存选择寄存器是哪种类型的,则Type就选择哪个,所以本文需要选择的是type 2 REMAY1的外部烧录算法。
如下图:
最后把要存储在外部flash的c文件保存到对应地址里面。先右键对应的c文件选择Options for File 选项,然后如下图操作。
最后编译,即可下载到AT32F403A开发板。
测试
测试代码
保存数据的从外部flash的2M地址开始写入4KB大小的数据,然后读出来和写入的数据进行对比。代码在spim中运行的,则是写的每1s输出一次log。
测试结果
对比数据成功通过,并且每1s都输出了正确的log。
最后
有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。