RT-Thread STM32F103 正点原子战舰V3开发板BSP说明
RT-Thread STM32F103 正点原子战舰V3开发板BSP说明
简介
本文档为 正点原子战舰V3 开发板的 BSP (板级支持包) 说明。
主要内容如下:
- 开发板资源介绍
- BSP 快速上手
- 进阶使用方法
通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。
开发板介绍
STM32F103战舰V3,资源丰富,接口多,功能强大,性价比高,资料全,外观炫酷,布局人性化,配件丰富,配件的接口丰富,是学习嵌入式的好开发板
开发板外观如下图所示:
该开发板常用 板载资源 如下:
- MCU:STM32F103ZET6,主频 72MHz,512KB FLASH ,64KB RAM
- 外部 RAM:无
- 外部 FLASH:W25Q128(SPI2,128MB)、EEPROM(24c02)
- 常用外设
- LED:2个,DS0(黄色,PB5),DS1(红色,PE5)
- 按键:4个,K0(兼具唤醒功能,PA0),K1(PE4), K2 (PE3) , K3 (PE2)
- 常用接口:USB 转串口、SD 卡接口、以太网接口、LCD 接口、USB SLAVE等
- 调试接口,板载的 ST-LINK SWD 下载
开发板更多详细信息请参考正点原子战舰V3开发板介绍
外设支持
本 BSP 目前对外设的支持情况如下:
板载外设 | 支持情况 | 备注 |
---|---|---|
USB 转串口 | 支持 | UART1 |
SPI Flash | 支持 | W25Q128 128M FLASH SPI2 |
以太网 | 支持 | DM9000 |
SD卡 | 支持 | |
RS485 | 支持 | USART2 |
片上外设 | 支持情况 | 备注 |
GPIO | 支持 | PA0, PA1… PG15 —> PIN: 0, 1…111 |
UART | 支持 | UART1/2/3 |
SPI | 支持 | SPI1/2 |
I2C | 支持 | 软件 I2C |
ADC | 支持 | |
RTC | 支持 | 支持外部晶振和内部低速时钟 |
PWM | 支持 | TIM3 CH1 TIM3 CH2 |
CAN | 支持 | |
IWG | 支持 | |
扩展模块 | 支持情况 | 备注 |
esp8266 | 支持 | USART3 |
使用说明
使用说明分为如下两个章节:
-
快速上手
本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。
-
进阶使用
本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。
快速上手
本 BSP 为开发者提供 MDK4、MDK5 和 IAR 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。
硬件连接
使用数据线连接开发板到 PC,打开电源开关。
编译下载
双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。
工程默认配置使用 ST-Link 仿真器下载程序,在通过 ST-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板
运行结果
下载程序成功之后,系统会自动运行,两个 LED 闪烁 。
连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息:
\ | /
- RT - Thread Operating System
/ | \ 4.0.1 build Mar 10 2019
2006 - 2019 Copyright by rt-thread team
msh >
进阶使用
此 BSP 默认只开启了 GPIO 和 串口1 的功能,如果需使用 SD 卡、Flash 等更多高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下:
-
在 bsp 下打开 env 工具。
-
输入
menuconfig
命令配置工程,配置好之后保存退出。 -
输入
pkgs --update
命令更新软件包。 -
输入
scons --target=mdk4/mdk5/iar
命令重新生成工程。
本章节更多详细的介绍请参考 STM32 系列 BSP 外设驱动使用教程。
注意事项
- 此开发板外部高速晶振是 12MHz ;
- 建议使用USB转TTL连接到PC机 ;
- 正点原子开发板 在使用终端工具如:PuTTy、XShell 时,会出现系统不能启动的问题,推荐使用串口调试助手如:sscom
示例代码
…\components\drivers\ipc\waitqueue.c
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon
* to blocked thread.
* 2022-01-24 THEWON let rt_wqueue_wait return thread->error when using signal
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
*/
#include <stdint.h>
#include <rthw.h>
#include <rtdevice.h>
/**
* @brief This function will insert a node to the wait queue.
*
* @param queue is a pointer to the wait queue.
*
* @param node is a pointer to the node to be inserted.
*/
void rt_wqueue_add(rt_wqueue_t *queue, struct rt_wqueue_node *node)
{
rt_base_t level;
level = rt_spin_lock_irqsave(&(queue->spinlock));
node->wqueue = queue;
rt_list_insert_before(&(queue->waiting_list), &(node->list));
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
}
/**
* @brief This function will remove a node from the wait queue.
*
* @param node is a pointer to the node to be removed.
*/
void rt_wqueue_remove(struct rt_wqueue_node *node)
{
rt_base_t level;
RT_ASSERT(node->wqueue != RT_NULL);
level = rt_spin_lock_irqsave(&(node->wqueue->spinlock));
rt_list_remove(&(node->list));
rt_spin_unlock_irqrestore(&(node->wqueue->spinlock), level);
}
/**
* @brief This function is the default wakeup function, but it doesn't do anything in actual.
* It always return 0, user should define their own wakeup function.
*
* @param wait is a pointer to the wait queue.
*
* @param key is the wakeup condition.
*
* @return always return 0.
*/
int __wqueue_default_wake(struct rt_wqueue_node *wait, void *key)
{
return 0;
}
/**
* @brief This function will wake up a pending thread on the specified waiting queue that meets the conditions.
*
* @param queue is a pointer to the wait queue.
*
* @param key is the wakeup conditions, but it is not effective now, because
* default wakeup function always return 0.
* If user wants to use it, user should define their own wakeup function.
*/
void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key)
{
rt_base_t level;
int need_schedule = 0;
rt_list_t *queue_list;
struct rt_list_node *node;
struct rt_wqueue_node *entry;
queue_list = &(queue->waiting_list);
level = rt_spin_lock_irqsave(&(queue->spinlock));
/* set wakeup flag in the queue */
queue->flag = RT_WQ_FLAG_WAKEUP;
if (!(rt_list_isempty(queue_list)))
{
for (node = queue_list->next; node != queue_list; node = node->next)
{
entry = rt_list_entry(node, struct rt_wqueue_node, list);
if (entry->wakeup(entry, key) == 0)
{
rt_thread_resume(entry->polling_thread);
need_schedule = 1;
rt_list_remove(&(entry->list));
break;
}
}
}
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
if (need_schedule)
rt_schedule();
}
/**
* @brief This function will join a thread to the specified waiting queue, the thread will holds a wait or
* timeout return on the specified wait queue.
*
* @param queue is a pointer to the wait queue.
*
* @param condition is parameters compatible with POSIX standard interface (currently meaningless, just pass in 0).
*
* @param msec is the timeout value, unit is millisecond.
*
* @return Return 0 if the thread is woken up.
*/
static int _rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec, int suspend_flag)
{
int tick;
rt_thread_t tid = rt_thread_self();
rt_timer_t tmr = &(tid->thread_timer);
struct rt_wqueue_node __wait;
rt_base_t level;
rt_err_t ret;
/* current context checking */
RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE);
tick = rt_tick_from_millisecond(msec);
if ((condition) || (tick == 0))
return 0;
__wait.polling_thread = rt_thread_self();
__wait.key = 0;
__wait.wakeup = __wqueue_default_wake;
__wait.wqueue = queue;
rt_list_init(&__wait.list);
level = rt_spin_lock_irqsave(&(queue->spinlock));
/* reset thread error */
tid->error = RT_EOK;
if (queue->flag == RT_WQ_FLAG_WAKEUP)
{
/* already wakeup */
goto __exit_wakeup;
}
ret = rt_thread_suspend_with_flag(tid, suspend_flag);
if (ret != RT_EOK)
{
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* suspend failed */
return -RT_EINTR;
}
rt_list_insert_before(&(queue->waiting_list), &(__wait.list));
/* start timer */
if (tick != RT_WAITING_FOREVER)
{
rt_timer_control(tmr,
RT_TIMER_CTRL_SET_TIME,
&tick);
rt_timer_start(tmr);
}
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_schedule();
level = rt_spin_lock_irqsave(&(queue->spinlock));
__exit_wakeup:
queue->flag = RT_WQ_FLAG_CLEAN;
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_wqueue_remove(&__wait);
return tid->error;
}
int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
{
return _rt_wqueue_wait(queue, condition, msec, RT_UNINTERRUPTIBLE);
}
int rt_wqueue_wait_killable(rt_wqueue_t *queue, int condition, int msec)
{
return _rt_wqueue_wait(queue, condition, msec, RT_KILLABLE);
}
int rt_wqueue_wait_interruptible(rt_wqueue_t *queue, int condition, int msec)
{
return _rt_wqueue_wait(queue, condition, msec, RT_INTERRUPTIBLE);
}
源码下载
…\bsp\stm32\stm32f103-atk-warshipv3\project.uvproj
RT-Thread STM32F103 正点原子战舰V3开发板 源码下载