ThreadX + LevelX+ FileX在STM32+NorFlash的移植

ThreadX + LevelX+ FileX在STM32+NorFlash的移植

开发平台:

IDE:MDK + STM32Cubemx
MCU:STM32F767IGT6;
NorFlash:W25Q256;
SPI:四线。

本教程是基于STM32 + SPI NorFlash 完成的,此历程相对上一个LevelX的历程中增加了使用ThreadX 与FileX的支持,同时,SPI Flash驱动增加DMA收发支持。实际使用过程中与芯片没什么紧密关系,均可使用,也不局限与SPI NorFlash 。实际上无论什么接口、什么类型的FLASH,除移植过程中对接口操作进行修改其余均可参照此教程进行移植。这里仅仅使用 SPI NorFlash进行举例,其余均可举一反三进行对照移植。

关于SPI 的DMA支持可以直接看BSP驱动代码。

STM32CubeMX中NorFlash SPI的配置参数:

CubeMX的SPI5配置
CubeMX SPI5 DMA配置

移植操作(参考LevelX移植)

LevelX将一个NorFlash的物理Block(块)主动分成由N个每128字的大小的扇区组成,所用的NorFlash实际扇区一般都不等于128字即512字节,在移植过程中,只需要将操作的地址进行转换一下,至于绝对操作地址相关的接口即可。

本次增加了LevelX的移植操作,过程比较简单,具体可以在安富莱电子论坛中查找到ThreadX的移植操作。

FileX的移植主要是修改FileX的 DriverEntry入口,因为在LevelX的移植过程中,已经对SPI驱动层移植完毕,所以只用将LevelX的接口一FileX的驱动入口初始一下即可。这里粘贴一下修改完毕的代码:

FileX的Driver entry调用

    if(Nor_Format)
    {
        Nor_Format = 0;
		fx_media_format(&nor_disk,
								nor_flash_driver,   // Driver entry
								FX_NULL,                          // Unused
								media_memory,                     // Media buffer pointer
								sizeof(media_memory),             // Media buffer size
								"MY_NOR_DISK",                    // Volume Name
								1,                                // Number of FATs
								32,                               // Directory Entries
								0,                                // Hidden sectors
								(W25Q256FV_FLASH_SIZE / 512) - 1, // Total sectors
								512,            // Sector size
								8,                                // Sectors per cluster
								1,                                // Heads
								1);                               // Sectors per track
    }
    
    
            /* Open the NOR disk.  */
        status =  fx_media_open(&nor_disk, "NOR DISK", nor_flash_driver, FX_NULL, media_memory, sizeof(media_memory));

读写驱动移植

VOID  nor_flash_driver(FX_MEDIA *media_ptr)
{

UCHAR       *source_buffer;
UCHAR       *destination_buffer;
ULONG       logical_sector;
ULONG       i;
UINT        status;


    /* There are several useful/important pieces of information contained in the media
       structure, some of which are supplied by FileX and others are for the driver to
       setup. The following is a summary of the necessary FX_MEDIA structure members
       Media结构中包含了一些有用的/重要的信息,其中一些是由FileX提供的,另一些则是由驱动程序设置的。以下是必要的FX_MEDIA结构成员的概要。:

            FX_MEDIA Member                              Meaning

        fx_media_driver_request             FileX request type. Valid requests from FileX are
                                            as follows:

                                                    FX_DRIVER_READ
                                                    FX_DRIVER_WRITE
                                                    FX_DRIVER_FLUSH
                                                    FX_DRIVER_ABORT
                                                    FX_DRIVER_INIT
                                                    FX_DRIVER_BOOT_READ
                                                    FX_DRIVER_RELEASE_SECTORS
                                                    FX_DRIVER_BOOT_WRITE
                                                    FX_DRIVER_UNINIT

        fx_media_driver_status              This value is RETURNED by the driver. If the
                                            operation is successful, this field should be
                                            set to FX_SUCCESS for before returning. Otherwise,
                                            if an error occurred, this field should be set
                                            to FX_IO_ERROR.

        fx_media_driver_buffer              Pointer to buffer to read or write sector data.
                                            This is supplied by FileX.

        fx_media_driver_logical_sector      Logical sector FileX is requesting.

        fx_media_driver_sectors             Number of sectors FileX is requesting.


       The following is a summary of the optional FX_MEDIA structure members:

            FX_MEDIA Member                              Meaning

        fx_media_driver_info                指向任何附加信息或内存的指针。
                                            这对于驱动程序来说是可选的,由fx_media_open调用来设置。RAM磁盘使用这个指针作为RAM磁盘内存本身的指针。.

        fx_media_driver_write_protect       当介质被写保护时,DRIVER会将其设置为FX_TRUE。这通常在初始化时完成,但也可以在任何时候完成。.

        fx_media_driver_free_sector_update  当DRIVER需要知道集群何时被释放时,会将此设置为FX_TRUE。这对于FLASH损耗均衡驱动来说是很重要的.

        fx_media_driver_system_write        如果被写入的扇区是系统扇区,例如,启动、FAT或目录扇区,FileX将此标志设置为FX_TRUE。
                                            驱动程序可以选择使用这个标志来启动错误恢复逻辑,以获得更大的容错能力。.

        fx_media_driver_data_sector_read    如果被读取的扇区是文件数据扇区,即不是系统扇区,FileX将此标志设置为FX_TRUE。.

        fx_media_driver_sector_type         FileX将此变量设置为被读取或写入的扇区的特定类型。以下是扇区的类型:

                                                    FX_UNKNOWN_SECTOR
                                                    FX_BOOT_SECTOR
                                                    FX_FAT_SECTOR
                                                    FX_DIRECTORY_SECTOR
                                                    FX_DATA_SECTOR
    */
    /*处理媒体控制块中指定的驱动程序请求。*/
    switch(media_ptr -> fx_media_driver_request)
    {
        case FX_DRIVER_READ:
        {
            /* 设置目标缓冲区和逻辑扇区。*/
            logical_sector =      media_ptr -> fx_media_driver_logical_sector;
            destination_buffer =  (UCHAR *) media_ptr -> fx_media_driver_buffer;

            /*循环读取闪存中的扇区。 */
            for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
            {
                /*从NOR闪存中读取一个扇区。*/
                status =  lx_nor_flash_sector_read(&nor_flash, logical_sector, destination_buffer);

                /*确定读取是否成功。 */
                if (status != LX_SUCCESS)
                {
                    /* Return an I/O error to FileX.  */
                    media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                    return;
                }
                /* 移动到下一个条目。*/
                logical_sector++;
                destination_buffer =  destination_buffer + 512;
            }
            /*驱动请求成功。 */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_WRITE:
        {
            /*设置源缓冲区和逻辑扇区。*/
            logical_sector =      media_ptr -> fx_media_driver_logical_sector;
            source_buffer =       (UCHAR *) media_ptr -> fx_media_driver_buffer;

            /* 循环向闪存写入扇区。*/
            for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
            {
                /*向NOR闪存写入一个扇区。*/
                status =  lx_nor_flash_sector_write(&nor_flash, logical_sector, source_buffer);

                /* Determine if the write was successful.
                确定写入是否成功。*/
                if (status != LX_SUCCESS)
                {
                    /* Return an I/O error to FileX.  */
                    media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                    return;
                }
                /* Move to the next entries.  */
                logical_sector++;
                source_buffer =  source_buffer + 512;
            }

            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_RELEASE_SECTORS:
        {

            /*设置逻辑扇区 */
            logical_sector =  media_ptr -> fx_media_driver_logical_sector;

            /*释放扇区:*/
            for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
            {

                /* Release NOR flash sector.  */
                status =  lx_nor_flash_sector_release(&nor_flash, logical_sector);

                /* Determine if the sector release was successful.  */
                if (status != LX_SUCCESS)
                {
                    /* Return an I/O error to FileX.  */
                    media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                    return;
                }
                /* Move to the next entries.  */
                logical_sector++;
            }
            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_FLUSH:
        {
            /* Return driver success.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_ABORT:
        {
            /* Return driver success.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_INIT:
        {

            /* FLASH驱动程序负责设置媒体结构中的几个字段,如下所示
                    media_ptr -> fx_media_driver_free_sector_update
                    media_ptr -> fx_media_driver_write_protect
               fx_media_driver_free_sector_update标志用于指示FileX在没有使用扇区时通知驱动程序。
               这对于FLASH管理者来说特别有用,因为他们不需要为不再使用的扇区维护映射。

              驱动程序可以在任何时候设置fx_media_driver_write_protect标志,
               以指示媒体不可写。 当这个标志被设置时,写入尝试会被返回为错误。*/

            /*在这里执行基本的初始化......直到引导记录将在随后被读取,并再次请求卷名。*/

            /* 使用闪存磨损水平,FileX应该在扇区不再使用时告诉磨损水平。*/
            media_ptr -> fx_media_driver_free_sector_update =  FX_TRUE;

            /* Open the NOR flash simulation.  */
            status =  lx_nor_flash_open(&nor_flash, "sim nor flash", nor_driver_initialize);

            /* Determine if the flash open was successful.  */
            if (status != LX_SUCCESS)
            {
                /* Return an I/O error to FileX.  */
                media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                return;
            }
            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_UNINIT:
        {

            /* 在这种情况下,RAM驱动是没有什么可做的。 对于实际设备,可能需要进行一些关机处理。*/
            /* Close the NOR flash simulation.  */
            status =  lx_nor_flash_close(&nor_flash);

            /* Determine if the flash close was successful.  */
            if (status != LX_SUCCESS)
            {
                /* Return an I/O error to FileX.  */
                media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                return;
            }

            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_BOOT_READ:
        {
            /*读取boot记录并返回给调用者*/
            /*设置目标缓冲区。*/
            destination_buffer =  (UCHAR *) media_ptr -> fx_media_driver_buffer;

            /* Read boot sector from NOR flash.  */
            status =  lx_nor_flash_sector_read(&nor_flash, 0, destination_buffer);

            /*对于NOR驱动,确定启动记录是否有效。*/
            if ((destination_buffer[0] != (UCHAR) 0xEB) ||
                (destination_buffer[1] != (UCHAR) 0x34) ||
                (destination_buffer[2] != (UCHAR) 0x90))
            {
                /* Invalid boot record, return an error!  */
                media_ptr -> fx_media_driver_status =  FX_MEDIA_INVALID;
                return;
            }

            /* Determine if the boot read was successful.  */
            if (status != LX_SUCCESS)
            {
                /* Return an I/O error to FileX.  */
                media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                return;
            }
            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break;
        }

        case FX_DRIVER_BOOT_WRITE:
        {
            /* Write the boot record and return to the caller.  */
            /* Setup the source buffer.  */
            source_buffer =       (UCHAR *) media_ptr -> fx_media_driver_buffer;

            /* Write boot sector to NOR flash.  */
            status =  lx_nor_flash_sector_write(&nor_flash, 0, source_buffer);

            /* Determine if the boot write was successful.  */
            if (status != LX_SUCCESS)
            {
                /* Return an I/O error to FileX.  */
                media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
                return;
            }
            /* Successful driver request.  */
            media_ptr -> fx_media_driver_status =  FX_SUCCESS;
            break ;
        }

        default:
        {
            /* Invalid driver request.  */
            media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
            break;
        }
    }
}

本次工程文件:ThreadX + LevelX+ FileX在STM32+NorFlash的移植工程

更新:

在昨天刚写完此贴后,ST就上传了字节的关于ThreadX LevelX FileX的SDIO设备以及SPI NOR设备的代码工程。大概看了一下移植大概都是一样的,感兴趣的可以看看ST的官方github代码库中的代码。
x-cube-azrtos-h7

声明 我所有的资源下载都是免C币的,下载时需要C币是优快云要的,我修改不了。

<think>好的,我现在需要处理用户关于STM32 FLASH擦除结构定义和参数说明的问题。首先,用户提到参考了SDL相关的引用,但可能引用内容不太相关,需要确认是否有误。不过重点还是STM32的FLASH擦除结构。 首先,我应该回顾STM32的FLASH模块的基本知识。STM32的闪存模块由多个扇区(Sectors)或页(Pages)组成,不同型号的STM32扇区大小可能不同,比如F1系列通常每个扇区1KB或2KB,而F4或H7系列可能有更大的扇区,甚至分为不同的Bank。擦除操作通常以扇区为单位,或者整个Bank,但需要具体型号的信息。 接下来,擦除结构定义可能涉及几个方面:擦除类型(扇区擦除、批量擦除)、起始地址、扇区编号、擦除延迟时间等。参数可能包括擦除时间、电压要求、操作模式等。需要注意不同系列STM32的HAL库函数参数可能不同,比如HAL_FLASHEx_Erase函数的参数可能是一个结构体指针,包含TypeErase、Sector、Banks等字段。 然后,用户可能需要示例代码来说明如何调用擦除函数,比如使用HAL库的步骤:解锁FLASH,执行擦除,锁定FLASH。同时需要提到擦除前的注意事项,比如中断处理、数据备份等。 还需要考虑可能的错误处理,比如擦除过程中的错误标志,如何检查操作是否成功。此外,STM32的擦除操作会影响Flash的寿命,每个扇区有最大擦写次数,这也是参数说明的一部分。 用户的问题可能还涉及到擦除后的验证,如何确认擦除完成,以及不同型号之间的差异。比如F1和F7系列的擦除函数参数结构可能不同,需要区分。 最后,生成的相关问题需要围绕擦除操作展开,比如步骤、错误处理、优化寿命的方法、不同型号区别等。需要确保回答结构清晰,分点说明,并引用正确的参考资料,尽管用户提供的引用似乎有误,可能需要忽略或指出。</think>[系统级回答] ### STM32 FLASH擦除结构定义及参数解析 #### 1. 擦除结构体定义 在STM32 HAL库中,擦除操作通过`HAL_FLASHEx_Erase()`函数实现,其输入参数为`FLASH_EraseInitTypeDef`结构体: ```c typedef struct { uint32_t TypeErase; // 擦除类型选择 uint32_t Banks; // BANK选择(双BANK器件) uint32_t Sector; // 扇区编号 uint32_t NbSectors; // 连续擦除扇区数 uint32_t VoltageRange; // 电压范围设置 } FLASH_EraseInitTypeDef; ``` #### 2. 关键参数说明 | 参数 | 取值范围 | 说明 | |----------------|--------------------------------------------------------------------------|----------------------------------------------------------------------| | TypeErase | `FLASH_TYPEERASE_SECTORS`<br>`FLASH_TYPEERASE_MASSERASE` | 扇区擦除或整片擦除 | | Banks | `FLASH_BANK_1`<br>`FLASH_BANK_BOTH`(双BANK器件) | 指定操作的存储区 | | Sector | 0-11(STM32F4)<br>0-7(STM32F1) | 起始扇区编号,具体范围依芯片型号 | | NbSectors | 1-(MaxSector - Sector) | 连续擦除的扇区数量 | | VoltageRange | `FLASH_VOLTAGE_RANGE_1`<br>`FLASH_VOLTAGE_RANGE_2`<br>`FLASH_VOLTAGE_RANGE_3` | 根据VDD电压设置(影响编程速度) | #### 3. 典型擦除流程 ```c HAL_FLASH_Unlock(); // 解锁FLASH FLASH_EraseInitTypeDef erase; erase.TypeErase = FLASH_TYPEERASE_SECTORS; erase.Sector = FLASH_SECTOR_2; erase.NbSectors = 3; erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; uint32_t SectorError = 0; HAL_FLASHEx_Erase(&erase, &SectorError); // 执行擦除 HAL_FLASH_Lock(); // 重新上锁 ``` #### 4. 重要注意事项 - 擦除最小单位为**扇区**,不同系列扇区大小不同: - STM32F1系列:1KB/2KB扇区 - STM32F4系列:16KB-128KB扇区 - STM32H7系列:128KB双BANK架构[^1] - 擦除时间典型值: - 扇区擦除:约40ms - 整片擦除:约1s(与容量相关) - 擦写寿命: - 工业级:10,000次(-40~85℃) - 汽车级:100,000次(特殊工艺)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值