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 进行配置,步骤如下:

  1. 在 bsp 下打开 env 工具。
  2. 输入 menuconfig 命令配置工程,配置好之后保存退出。
  3. 输入 pkgs --update 命令更新软件包。
  4. 输入 scons --target=mdk4/mdk5/iar 命令重新生成工程。

本章节更多详细的介绍请参考 STM32 系列 BSP 外设驱动使用教程

注意事项

  • 目前仅测试 V1.1 版本硬件,较老的 V1.0 暂未测试

  • 默认仅开启 LCD 功能,此时生成的固件大小约为 110k 左右,如果开启其他功能固件超过 128k ,可以通过如下方式:

    1. H750 实际上可以使用片内 2M ram,但是 128k 后 ST 不保证可用性,此时可以:
      1. 在 keil 中芯片选为 H743 ,此时会出现 2MB Flash 的下载算法,选择此下载算法下载程序
      2. bsp\stm32\stm32h750-weact-ministm32h7xx 目录下会提供一份 h750 的 keil 内部 ram 的下载算法,可以采用下载算法
    2. 通过 bootloader 从片外 qspi flash 启动
  • 调试串口为串口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说明 源码下载


维护人:

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

华为奋斗者精神

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

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

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

打赏作者

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

抵扣说明:

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

余额充值