当前位置: 首页 > news >正文

基于AT32的RT-Thread移植

准备源码,配置工程

仅供有移植RTOS基础的人参考借鉴。

添加源码

直接用CubeMX生成的RT-Thread_Nano源码,复制到自己的AT32工程内里。

AT32大多芯片是M4架构,注意替换libcpu中的文件。注意:AT32F437ZGT7是M4架构

把RTT源码添加进keil工程

开启SysTick中断。

添加头文件路径

屏蔽那几个中断

SVC_Handler、PendSV_Handler(void)、SysTick_Handler(void)、HardFault_Handler(void),因为这些函数RT-Thread已经帮我们实现好了。

修改部分.c/.h

根据板子重新实现特定函数

修改board.c中的rt_hw_board_init。如果需要使用RT-Thread的shell命令行调试工具,还需要修改uart_init(void)、rt_hw_console_output、rt_hw_console_getchar这几个函数。

多数情况下还需要在串口中断函数中手动清除下接收完成标志位。

rt_hw_board_init:

这个作用主要就是初始化时钟,关键是要开启SysTick中断。

/*** This function will initial your board.*/
void rt_hw_board_init(void)
{/* * 1: OS Tick Configuration* Enable the hardware timer and call the rt_os_tick_callback function* periodically with the frequency RT_TICK_PER_SECOND. *//* 添加的代码部分begin */system_clock_config();  // 已正确配置HCLK=288MHzSysTick_Config(288000-1);/* * 设置SysTick中断优先级:* AT32使用4位优先级(0~15),值越大优先级越低* 设为15(最低),避免影响高优先级外设中断*/NVIC_SetPriority(SysTick_IRQn, 15);/* 添加的代码部分end *//* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INITrt_components_board_init();
#endif#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

rt_hw_console_output

void rt_hw_console_output(const char *str)
{rt_size_t i = 0;rt_size_t size = rt_strlen(str);char a = '\r';  // 换行前添加回车for (i = 0; i < size; i++){// 遇到换行符时先发送回车if (*(str + i) == '\n'){// 等待发送缓冲区为空while (usart_flag_get(CONSOLE_USART, USART_TDBE_FLAG) == RESET);usart_data_transmit(CONSOLE_USART, a);}// 发送当前字符while (usart_flag_get(CONSOLE_USART, USART_TDBE_FLAG) == RESET);usart_data_transmit(CONSOLE_USART, *(str + i));}// 等待最后一个字符发送完成while (usart_flag_get(CONSOLE_USART, USART_TDC_FLAG) == RESET);
}

USART1_IRQHandler和rt_hw_console_getchar

// 接收缓存:-1表示无数据
static volatile int usart_rx_buf = -1;
// 接收完成标志
static volatile rt_bool_t usart_rx_ready = RT_FALSE;/*** USART中断处理函数:接收数据并缓存*/
void USART1_IRQHandler(void)
{rt_interrupt_enter();// 处理接收缓冲区非空中断(AT32标志位为USART_RDBF_FLAG)if (usart_flag_get(CONSOLE_USART, USART_RDBF_FLAG) == SET){// 读取接收数据并缓存usart_rx_buf = (int)(usart_data_receive(CONSOLE_USART) & 0xFF);usart_rx_ready = RT_TRUE;// 清除标志位(AT32需要手动清除)usart_flag_clear(CONSOLE_USART, USART_RDBF_FLAG);}rt_interrupt_leave();
}char rt_hw_console_getchar(void)
{int ch = -1;// 等待中断接收数据while (usart_rx_ready != RT_TRUE){rt_thread_mdelay(1);  // 短延时等待,降低CPU占用}// 读取缓存数据并重置标志ch = usart_rx_buf;usart_rx_ready = RT_FALSE;usart_rx_buf = -1;return ch;
}

board.c。仅供参考

/** Copyright (c) 2006-2019, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2021-05-24                  the first version*/#include <rthw.h>
#include <rtthread.h>//#include "main.h"
#include "at32f435_437.h"
#include "at32f435_437_clock.h"
#include "usart.h"#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
/** Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP* the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes*/
#define RT_HEAP_SIZE (15*1024)
static rt_uint8_t rt_heap[RT_HEAP_SIZE];RT_WEAK void *rt_heap_begin_get(void)
{return rt_heap;
}RT_WEAK void *rt_heap_end_get(void)
{return rt_heap + RT_HEAP_SIZE;
}
#endifvoid SysTick_Handler(void)
{rt_interrupt_enter();rt_tick_increase();rt_interrupt_leave();
}#ifdef RT_USING_FINSH
#include <finsh.h>
static void reboot(uint8_t argc, char **argv)
{rt_hw_cpu_reset();
}
MSH_CMD_EXPORT(reboot, Reboot System);
#endif /* RT_USING_FINSH *//*** This function will initial your board.*/
void rt_hw_board_init(void)
{/* * 1: OS Tick Configuration* Enable the hardware timer and call the rt_os_tick_callback function* periodically with the frequency RT_TICK_PER_SECOND. *//* 添加的代码部分begin */system_clock_config();  // 已正确配置HCLK=288MHzSysTick_Config(288000-1);/* * 设置SysTick中断优先级:* AT32使用4位优先级(0~15),值越大优先级越低* 设为15(最低),避免影响高优先级外设中断*/NVIC_SetPriority(SysTick_IRQn, 15);/* 添加的代码部分end *//* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INITrt_components_board_init();
#endif#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}// 定义控制台使用的USART端口(根据实际硬件调整)
#define CONSOLE_USART         USART1
#ifdef RT_USING_CONSOLE//static UART_HandleTypeDef UartHandle;
static int uart_init(void)
{/* TODO: Please modify the UART port number according to your needs */usart_config();return 0;
}
INIT_BOARD_EXPORT(uart_init);void rt_hw_console_output(const char *str)
{rt_size_t i = 0;rt_size_t size = rt_strlen(str);char a = '\r';  // 换行前添加回车for (i = 0; i < size; i++){// 遇到换行符时先发送回车if (*(str + i) == '\n'){// 等待发送缓冲区为空while (usart_flag_get(CONSOLE_USART, USART_TDBE_FLAG) == RESET);usart_data_transmit(CONSOLE_USART, a);}// 发送当前字符while (usart_flag_get(CONSOLE_USART, USART_TDBE_FLAG) == RESET);usart_data_transmit(CONSOLE_USART, *(str + i));}// 等待最后一个字符发送完成while (usart_flag_get(CONSOLE_USART, USART_TDC_FLAG) == RESET);
}
#endif#ifdef RT_USING_FINSH// 接收缓存:-1表示无数据
static volatile int usart_rx_buf = -1;
// 接收完成标志
static volatile rt_bool_t usart_rx_ready = RT_FALSE;/*** USART中断处理函数:接收数据并缓存*/
void USART1_IRQHandler(void)
{rt_interrupt_enter();// 处理接收缓冲区非空中断(AT32标志位为USART_RDBF_FLAG)if (usart_flag_get(CONSOLE_USART, USART_RDBF_FLAG) == SET){// 读取接收数据并缓存usart_rx_buf = (int)(usart_data_receive(CONSOLE_USART) & 0xFF);usart_rx_ready = RT_TRUE;// 清除标志位(AT32需要手动清除)usart_flag_clear(CONSOLE_USART, USART_RDBF_FLAG);}rt_interrupt_leave();
}char rt_hw_console_getchar(void)
{int ch = -1;// 等待中断接收数据while (usart_rx_ready != RT_TRUE){rt_thread_mdelay(1);  // 短延时等待,降低CPU占用}// 读取缓存数据并重置标志ch = usart_rx_buf;usart_rx_ready = RT_FALSE;usart_rx_buf = -1;return ch;
}
#endif

main.c测试代码

#include "at32f435_437_clock.h"
#include "./BSP/led.h"
#include "./BSP/key.h"
#include "./BSP/beep.h"
#include "Delay.h"
#include "./BSP/usart.h"#include <rthw.h>
#include "rtthread.h"
#include <stdio.h>/* 定义线程控制块 */
static rt_thread_t led1_thread = RT_NULL;static void led1_thread_entry(void *parameter)
{while (1){rt_thread_delay(500); /* 延时500个tick */gpio_bits_set(LED2_GPIO,LED2_PIN);rt_thread_delay(500); /* 延时500个tick */gpio_bits_reset(LED2_GPIO,LED2_PIN); }
}int main(void)
{/* 初始化系统时钟 */system_clock_config();/* 初始化引脚定义 */led_init();key_init(); beep_init();usart_config();/* 间隔1s发送一次AT32_TEST */
//    printf("AT32_USART测试\r\n");// 在main函数中添加
//    rt_kprintf("SystemCoreClock: %d Hz\n", SystemCoreClock);  // 应输出288000000
//    rt_kprintf("SysTick时钟: %d Hz\n", (SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk) ? SystemCoreClock : (SystemCoreClock/8));
//    led1_thread =                           /* 线程控制块指针 */rt_thread_create("led1",            /* 线程名字 */led1_thread_entry, /* 线程入口函数 */RT_NULL,           /* 线程入口函数参数 */128,               /* 线程栈大小 */20,                /* 线程的优先级 */20);               /* 线程时间片 *//* 启动线程,开启调度 */rt_thread_startup(led1_thread);while(1){rt_thread_delay(1000);}
}

可能遇到的问题以及可尝试

卡死在空闲线程。

1. 可能调度器未开启,原因是SysTick中断未正常运行。

shell命令行无反应

1. 串口中断函数的接收标志位是否有清除,如果不清除会一直卡在串口中断函数。

http://www.dtcms.com/a/462839.html

相关文章:

  • 物流公司排名网站建设乐云seo
  • 组合两个表 与 从不订购的客户
  • 常熟企业网站建设2018做网站的软件
  • 嵌入式字符串解析自我批斗练习
  • PID控制器的不同的传递函数与参数形式
  • 网站建设与企业发展平面设计兼职接单
  • 网站 模板 下载青岛学网站建设的学校
  • vue啊哈哈哈哈哈哈哈哈
  • 广州网站设计实力乐云seo国外做美食的网站
  • Git安装与配置:操作步骤+Gitee绑定
  • 深圳网站建设补助网站非法篡改
  • C语言字符串安全查找 :strchr_s、strrchr_s、strstr_s
  • 微观世界的“尺子”,数码显微测量仪的原理与多元应用
  • jsp网站开发实例视频网站自助建设平台百度
  • 海思 / ASR / 展锐芯片实测:2025 随身 WiFi 选购核心参数与场景适配方案
  • 条件语句练习题
  • JLINKKeil调试 软硬件版本驱动对齐
  • wordpress 模板层次结构信息图百度网站关键词优化在哪里做
  • 天津做网站外包公司有哪些网站打开的速度特别慢的原因
  • ElasticSearch与Kibana 入门指南(7.x版本)
  • LLM 与强化学习的新范式:Agentic RL 研究综述
  • wordpress 标签打不开外贸网站推广seo
  • 深圳租赁住房和建设局网站网站设计定位
  • 公司网站建设会议纪要全球速卖通企业类型
  • 一、十天速通Java面试(第三天)
  • 网站怎么seo关键词排名优化推广石家庄专业信息门户网站定制
  • 十堰为企业做网站的单位wordpress建m域名网站
  • anaconda安装及使用
  • 惠来做网站专门做门的网站
  • 合肥专业网站排名推广wordpress显示近几篇微博