嵌入式系统应用-拓展-FLASH之操作 SFUD (Serial Flash Universal Driver)之KEIL应用

这里已经假设SFUD代码已经移植到工程下面成功了,如果读者对SFUD移植还不了解。可以参考笔者这篇文章:SFUD (Serial Flash Universal Driver)之KEIL移植
这里主要介绍测试和应用

1 硬件设计

这里采用windbond 的W25Q32这款芯片用于SFUD测试。

W25Q32是一款由Winbond(温邦)公司生产的串行闪存器件,具有以下特点和规格:

容量: W25Q32的容量为32 Megabits(Mb),即4 Megabytes(MB)。
接口: 采用串行外围接口(SPI)进行通信,支持快速的串行数据传输。
工作电压: 标准的工作电压范围为2.7V至3.6V,也有一些版本支持低电压工作(1.65V至2.0V)。
速度: 支持不同的时钟速度,例如在单线SPI模式下,最高速度可达到104MHz。
擦除和编程: 支持扇区擦除和页编程操作,有多种擦除模式可选。
保护功能: 支持硬件数据保护功能,可以通过设置保护位来保护特定的存储区域。

W25Q32广泛应用于嵌入式系统中,如智能手机、数字相机、网络设备、工业控制系统等,用于存储固件、配置数据、日志记录等信息。它的高速度、可靠性和丰富的功能使其成为许多嵌入式系统中的理想选择。在这里插入图片描述
主控芯片采用gd32f103系列芯片,远远满足固件移植的需要。 引脚对应的接口,用是SPI0接口。
在这里插入图片描述

2 驱动准备

2.1 硬件驱动移植

打开sfud_port.c 文件, 这里需要添加对应的驱动,添加硬件驱动代码

static void rcc_configuration(void) {
 
  rcu_periph_clock_enable(RCU_GPIOA);
  rcu_periph_clock_enable(RCU_SPI0);
  rcu_periph_clock_enable(RCU_AF);

}

static void gpio_configuration(void) 
{    

	/* SPI0 GPIO config:SCK/PA5, MOSI/PA7, NSS/PA4 */
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5|GPIO_PIN_7);   

	/* SPI0 GPIO config: MISO/PA6*/
	gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
}

static void spi_configuration(void) {
     spi_parameter_struct spi_init_struct;
    /* deinitilize SPI and the parameters */
    spi_i2s_deinit(SPI0);
 
    spi_struct_para_init(&spi_init_struct);

    /* configure SPI0 parameter */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_2;   // 54MHz
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);  

	spi_nss_output_enable(SPI0);
		
	spi_enable(SPI0);
}

static void spi_lock(void) {
    __disable_irq();
}

static void spi_unlock(void) {
    __enable_irq();
}

2.1.1 添加初始化代码

在以下的地方添加初始化代码:
在这里插入图片描述

/* about 100 microsecond delay */
static void retry_delay_100us(void) {
    uint32_t delay = 120;
    while(delay--);
}

sfud_err sfud_spi_port_init(sfud_flash *flash) {
    sfud_err result = SFUD_SUCCESS;


     * add your port spi bus and device object initialize code like this:
     * 1. rcc initialize
     * 2. gpio initialize
     * 3. spi device initialize
     * 4. flash->spi and flash->retry item initialize
     *    flash->spi.wr = spi_write_read; //Required
     *    flash->spi.qspi_read = qspi_read; //Required when QSPI mode enable
     *    flash->spi.lock = spi_lock;
     *    flash->spi.unlock = spi_unlock;
     *    flash->spi.user_data = &spix;
     *    flash->retry.delay = null;
     *    flash->retry.times = 10000; //Required
     */

```c
    switch (flash->index) {
		
		case SFUD_XXXX_DEVICE_INDEX: {
			/* RCC 初始化 */
			rcc_configuration();
			/* GPIO 初始化 */
			gpio_configuration();
			/* SPI 外设初始化 */
			spi_configuration();
			/* 同步 Flash 移植所需的接口及数据 */
			flash->spi.wr = spi_write_read;
			flash->spi.lock = spi_lock;
			flash->spi.unlock = spi_unlock;
			//flash->spi.user_data = &spi1;
			/* about 100 microsecond delay */
			flash->retry.delay = retry_delay_100us;
			/* adout 60 seconds timeout */
			flash->retry.times = 60 * 10000;

			break;
    }

    return result;
}

2.1.2 添加读写代码

在这里插入图片描述

2.2 软件驱动准备

  sfud_err result = SFUD_SUCCESS;
    const sfud_flash *flash = sfud_get_device_table() + 0;
    size_t i;
    /* prepare write data */
    for (i = 0; i < size; i++) {
        data[i] = i;
    }
    /* erase test */
    result = sfud_erase(flash, addr, size);
    if (result == SFUD_SUCCESS) {
        printf("Erase the %s flash data finish. Start from 0x%08X, size is %ld.\r\n", flash->name, addr,
                size);
    } else {
        printf("Erase the %s flash data failed.\r\n", flash->name);
        return;
    }
    /* write test */
    result = sfud_write(flash, addr, size, data);
    if (result == SFUD_SUCCESS) {
        printf("Write the %s flash data finish. Start from 0x%08X, size is %ld.\r\n", flash->name, addr,
                size);
    } else {
        printf("Write the %s flash data failed.\r\n", flash->name);
        return;
    }
    /* read test */
    result = sfud_read(flash, addr, size, data);
    if (result == SFUD_SUCCESS) {
        printf("Read the %s flash data success. Start from 0x%08X, size is %ld. The data is:\r\n", flash->name, addr,
                size);
        printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");
        for (i = 0; i < size; i++) {
            if (i % 16 == 0) {
                printf("[%08X] ", addr + i);
            }
            printf("%02X ", data[i]);
            if (((i + 1) % 16 == 0) || i == size - 1) {
                printf("\r\n");
            }
        }
        printf("\r\n");
    } else {
        printf("Read the %s flash data failed.\r\n", flash->name);
    }
    /* data check */
    for (i = 0; i < size; i++) {
        if (data[i] != i % 256) {
            printf("Read and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
			break;
        }
    }
    if (i == size) {
        printf("The %s flash test is success.\r\n", flash->name);
    }

3 测试代码

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HHONGQI123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值