RT-Thread FANKE STM32 FK750M1-VBT6开发板BSP说明
RT-Thread FANKE STM32 FK750M1-VBT6开发板BSP说明
简介
本文档为 FANKE FK750M1-VBT6 开发板的 BSP (板级支持包) 说明。
主要内容如下:
- 开发板资源介绍
- BSP 快速上手
- 进阶使用方法
通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。
开发板介绍
FK750M1-VBT6 是 FANKE 推出的一款基于 ARM Cortex-M7 内核的核心板,最高频率为480Mhz,具有128KB ROM、1MB RAM,外接 8MB QSPI Flash,板载资源如下:
- 外扩 W25Q64,容量 8M 字节
- 1 个复位按键,1 个用户按键
- 1 个 BOOT 按键
- 1 个用户 LED
- 1 个 Type C 接口
- 1 个 TF 卡接口
- 1 个SPI 液晶和摄像头接口
- 引出 73 个 IO 口
开发板外观如下图所示:
外设支持
本 BSP 目前对外设的支持情况如下:
板载外设 | 支持情况 | 备注 |
---|---|---|
TF Card | 待支持 | |
QSPI Flash | 待支持 | W25Q64JV |
OV2640 Camera | 支持 | |
OV5640 Camera | 待支持 | |
0.96’ LCD | 待支持 | 160*80 |
1.14’ LCD | 待支持 | 240*135 |
1.30’ LCD | 支持 | 240*240 |
1.54’ LCD | 待支持 | 240*240 |
1.69’ LCD | 待支持 | 240*280 |
2.00’ LCD | 待支持 | 240*320 |
片上外设 | 支持情况 | 备注 |
GPIO | 支持 | |
UART | 支持 | USART1 |
SPI | 支持 | |
RTC | 支持 | |
USB Device | 待支持 |
使用说明
使用说明分为如下两个章节:
-
快速上手
本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。
-
进阶使用
本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。
快速上手
本 BSP 为开发者提供 MDK5 和 IAR 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。
硬件连接
使用数据线连接开发板到 PC。使用 usb 转串口工具连接 PA9 ( USART1_TX ) 和 PA10 ( USART1_RX )。
编译下载
双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。
运行结果
下载程序成功之后,系统会自动运行,LED闪烁。
连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息:
\ | /
- RT - Thread Operating System
/ | \ 5.0.0 build Mar 22 2023 00:10:44
2006 - 2022 Copyright by RT-Thread team
msh />
进阶使用
此 BSP 默认只开启了 GPIO 和 串口1 的功能,如果需使用更多高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下:
- 在 bsp 下打开 env 工具。
- 输入
menuconfig
命令配置工程,配置好之后保存退出。 - 输入
pkgs --update
命令更新软件包。 - 输入
scons --target=mdk4/mdk5/iar
命令重新生成工程。
本章节更多详细的介绍请参考 STM32 系列 BSP 外设驱动使用教程。
注意事项
-
目前仅测试 V1.1 版本硬件,较老的 V1.0 暂未测试
-
默认仅开启 LCD 功能,此时生成的固件大小约为 110k 左右,如果开启其他功能固件超过 128k ,可以通过如下方式:
- H750 实际上可以使用片内 2M ram,但是 128k 后 ST 不保证可用性,此时可以:
- 在 keil 中芯片选为 H743 ,此时会出现 2MB Flash 的下载算法,选择此下载算法下载程序
- bsp\stm32\stm32h750-weact-ministm32h7xx 目录下会提供一份 h750 的 keil 内部 ram 的下载算法,可以采用下载算法
- 通过 bootloader 从片外 qspi flash 启动
- H750 实际上可以使用片内 2M ram,但是 128k 后 ST 不保证可用性,此时可以:
-
调试串口为串口1 映射说明
PA9 ------> USART1_TX
PA10 ------> USART1_RX
示例代码
…\bsp\stm32\libraries\HAL_Drivers\drv_qspi.c
#include "board.h"
#include "drv_qspi.h"
#include "drv_config.h"
#ifdef RT_USING_QSPI
#define DRV_DEBUG
#define LOG_TAG "drv.qspi"
#include <drv_log.h>
#if defined(BSP_USING_QSPI)
struct stm32_qspi_bus
{
QSPI_HandleTypeDef QSPI_Handler;
char *bus_name;
#ifdef BSP_QSPI_USING_DMA
DMA_HandleTypeDef hdma_quadspi;
#endif
};
struct rt_spi_bus _qspi_bus1;
struct stm32_qspi_bus _stm32_qspi_bus;
static int stm32_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
{
int result = RT_EOK;
unsigned int i = 1;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(qspi_cfg != RT_NULL);
struct rt_spi_configuration *cfg = &qspi_cfg->parent;
struct stm32_qspi_bus *qspi_bus = device->parent.bus->parent.user_data;
rt_memset(&qspi_bus->QSPI_Handler, 0, sizeof(qspi_bus->QSPI_Handler));
QSPI_HandleTypeDef QSPI_Handler_config = QSPI_BUS_CONFIG;
qspi_bus->QSPI_Handler = QSPI_Handler_config;
#if defined(SOC_SERIES_STM32MP1)
while (cfg->max_hz < HAL_RCC_GetACLKFreq() / (i + 1))
#else
while (cfg->max_hz < HAL_RCC_GetHCLKFreq() / (i + 1))
#endif
{
i++;
if (i == 255)
{
LOG_E("QSPI init failed, QSPI frequency(%d) is too low.", cfg->max_hz);
return -RT_ERROR;
}
}
/* 80/(1+i) */
qspi_bus->QSPI_Handler.Init.ClockPrescaler = i;
if (!(cfg->mode & RT_SPI_CPOL))
{
/* QSPI MODE0 */
qspi_bus->QSPI_Handler.Init.ClockMode = QSPI_CLOCK_MODE_0;
}
else
{
/* QSPI MODE3 */
qspi_bus->QSPI_Handler.Init.ClockMode = QSPI_CLOCK_MODE_3;
}
/* flash size */
qspi_bus->QSPI_Handler.Init.FlashSize = POSITION_VAL(qspi_cfg->medium_size) - 1;
result = HAL_QSPI_Init(&qspi_bus->QSPI_Handler);
if (result == HAL_OK)
{
LOG_D("qspi init success!");
}
else
{
LOG_E("qspi init failed (%d)!", result);
}
#ifdef BSP_QSPI_USING_DMA
/* QSPI interrupts must be enabled when using the HAL_QSPI_Receive_DMA */
HAL_NVIC_SetPriority(QSPI_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(QSPI_IRQn);
HAL_NVIC_SetPriority(QSPI_DMA_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(QSPI_DMA_IRQ);
/* init QSPI DMA */
if(QSPI_DMA_RCC == RCC_AHB1ENR_DMA1EN)
{
__HAL_RCC_DMA1_CLK_ENABLE();
}
else
{
__HAL_RCC_DMA2_CLK_ENABLE();
}
HAL_DMA_DeInit(qspi_bus->QSPI_Handler.hdma);
DMA_HandleTypeDef hdma_quadspi_config = QSPI_DMA_CONFIG;
qspi_bus->hdma_quadspi = hdma_quadspi_config;
if (HAL_DMA_Init(&qspi_bus->hdma_quadspi) != HAL_OK)
{
LOG_E("qspi dma init failed (%d)!", result);
}
__HAL_LINKDMA(&qspi_bus->QSPI_Handler, hdma, qspi_bus->hdma_quadspi);
#endif /* BSP_QSPI_USING_DMA */
return result;
}
static void qspi_send_cmd(struct stm32_qspi_bus *qspi_bus, struct rt_qspi_message *message)
{
RT_ASSERT(qspi_bus != RT_NULL);
RT_ASSERT(message != RT_NULL);
QSPI_CommandTypeDef Cmdhandler;
/* set QSPI cmd struct */
Cmdhandler.Instruction = message->instruction.content;
Cmdhandler.Address = message->address.content;
Cmdhandler.DummyCycles = message->dummy_cycles;
if (message->instruction.qspi_lines == 0)
{
Cmdhandler.InstructionMode = QSPI_INSTRUCTION_NONE;
}
else if (message->instruction.qspi_lines == 1)
{
Cmdhandler.InstructionMode = QSPI_INSTRUCTION_1_LINE;
}
else if (message->instruction.qspi_lines == 2)
{
Cmdhandler.InstructionMode = QSPI_INSTRUCTION_2_LINES;
}
else if (message->instruction.qspi_lines == 4)
{
Cmdhandler.InstructionMode = QSPI_INSTRUCTION_4_LINES;
}
if (message->address.qspi_lines == 0)
{
Cmdhandler.AddressMode = QSPI_ADDRESS_NONE;
}
else if (message->address.qspi_lines == 1)
{
Cmdhandler.AddressMode = QSPI_ADDRESS_1_LINE;
}
else if (message->address.qspi_lines == 2)
{
Cmdhandler.AddressMode = QSPI_ADDRESS_2_LINES;
}
else if (message->address.qspi_lines == 4)
{
Cmdhandler.AddressMode = QSPI_ADDRESS_4_LINES;
}
if (message->address.size == 24)
{
Cmdhandler.AddressSize = QSPI_ADDRESS_24_BITS;
}
else
{
Cmdhandler.AddressSize = QSPI_ADDRESS_32_BITS;
}
if (message->qspi_data_lines == 0)
{
Cmdhandler.DataMode = QSPI_DATA_NONE;
}
else if (message->qspi_data_lines == 1)
{
Cmdhandler.DataMode = QSPI_DATA_1_LINE;
}
else if (message->qspi_data_lines == 2)
{
Cmdhandler.DataMode = QSPI_DATA_2_LINES;
}
else if (message->qspi_data_lines == 4)
{
Cmdhandler.DataMode = QSPI_DATA_4_LINES;
}
Cmdhandler.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
Cmdhandler.DdrMode = QSPI_DDR_MODE_DISABLE;
Cmdhandler.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
Cmdhandler.NbData = message->parent.length;
HAL_QSPI_Command(&qspi_bus->QSPI_Handler, &Cmdhandler, 5000);
}
static rt_ssize_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
rt_ssize_t result = 0;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
struct stm32_qspi_bus *qspi_bus = device->bus->parent.user_data;
const rt_uint8_t *sndb = message->send_buf;
rt_uint8_t *rcvb = message->recv_buf;
rt_int32_t length = message->length;
#ifdef BSP_QSPI_USING_SOFTCS
if (message->cs_take && (device->cs_pin != PIN_NONE))
{
rt_pin_write(device->cs_pin, PIN_LOW);
}
#endif
/* send data */
if (sndb)
{
qspi_send_cmd(qspi_bus, qspi_message);
if (qspi_message->parent.length != 0)
{
if (HAL_QSPI_Transmit(&qspi_bus->QSPI_Handler, (rt_uint8_t *)sndb, 5000) == HAL_OK)
{
result = length;
}
else
{
LOG_E("QSPI send data failed(%d)!", qspi_bus->QSPI_Handler.ErrorCode);
qspi_bus->QSPI_Handler.State = HAL_QSPI_STATE_READY;
result = -RT_ERROR;
goto __exit;
}
}
else
{
result = 1;
}
}
else if (rcvb)/* recv data */
{
qspi_send_cmd(qspi_bus, qspi_message);
#ifdef BSP_QSPI_USING_DMA
if (HAL_QSPI_Receive_DMA(&qspi_bus->QSPI_Handler, rcvb) == HAL_OK)
#else
if (HAL_QSPI_Receive(&qspi_bus->QSPI_Handler, rcvb, 5000) == HAL_OK)
#endif
{
result = length;
#ifdef BSP_QSPI_USING_DMA
while (qspi_bus->QSPI_Handler.RxXferCount != 0);
#endif
}
else
{
LOG_E("QSPI recv data failed(%d)!", qspi_bus->QSPI_Handler.ErrorCode);
qspi_bus->QSPI_Handler.State = HAL_QSPI_STATE_READY;
result = -RT_ERROR;
goto __exit;
}
}
__exit:
#ifdef BSP_QSPI_USING_SOFTCS
if (message->cs_release && (device->cs_pin != PIN_NONE))
{
rt_pin_write(device->cs_pin, PIN_HIGH);
}
#endif
return result;
}
源码下载
…\bsp\stm32\stm32h750-fk750m1-vbt6\project.uvproj
RT-Thread FANKE STM32 FK750M1-VBT6开发板BSP说明 源码下载