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的配置参数:
移植操作(参考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