3392|4

36

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

HC32F4A0-FreeRTOS移植 [复制链接]

 

        本篇在上篇的基础上,进行实时操作系统移植,所使用到的系统是FreeRTOS v10.3.0,系统源码与测试代码都将以附件形式在文末分享。

        由于我一直使用v10.3.0版本的系统,因此就不在git上下载最新的系统了,这个版本的系统我已经在多个产品上使用过了,稳定性与可靠性都不错。本篇只说系统如何使用。

首先添加源码文件到工程,如下图。除FreeRTOSConfig.h文件外,其余文件都是官方文件,不要自己更改其中的内容。FreeRTOSConfig.h这个文件是非常重要的,是用于剪裁FreeRTOS这个系统的,比如是否使用信号量、是否使用软件定时器等。

        其次,还有一个重要文件为port.c,这个文件根据内核或编译平台的不同,要选择不同的文件,我们这里使用ARM_CM4F文件夹下的port.c,如图所示。

 

        在添加完相关文件后,我们需要添加头文件路径,如下图。

        由于HC32F4A0的svc中断和pendsv中断本身没有函数写好,都需要我们自己去实现,而FreeRTOS是需要接管这两个函数的,所以我们就不需要创建也不需要删除相关内容。但是,我们需要实现Systick_Handler函数,因为之前我们使用过精确定时,所以,我们将这个函数放在delay.c中,像ST或GD单片机,一般都放在stm(gd)32f4xx_it.c中。Systick_Handler函数实现如下。在delay.c中,还需要包含相关FreeRTOS的头文件,我们新建了一个os_inclusdes.h的头文件,包含了所有操作系统相关的头文件,其内容有#include "FreeRTOS.h"、#include "task.h"、#include "queue.h"、#include "timers.h"、#include "semphr.h"。

/**************************************************************
  * [url=home.php?mod=space&uid=32621]@name[/url] SysTick_Handler
  * [url=home.php?mod=space&uid=159083]@brief[/url] * @param   None
  * @retval
  * [url=home.php?mod=space&uid=1315547]@author[/url] Zachary
  * [url=home.php?mod=space&uid=34591]@data[/url] 2023-02-13
 **************************************************************/
extern void xPortSysTickHandler( void );
void SysTick_Handler( void )
{
	uint32_t ulReturn;
    if ( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED )	/* ---任务调度已开启--- */
    {	
		ulReturn = taskENTER_CRITICAL_FROM_ISR();
        xPortSysTickHandler();
		taskEXIT_CRITICAL_FROM_ISR( ulReturn );
	}
}

        接着我们编写多任务函数,我们一共创建3个任务来测试操作系统是否一直成功,分别是static void xTaskStart( void *pvParameters )开始任务、static void xTask1( void *pvParameters )任务1和static void xTask2( void *pvParameters )任务2。

        首先,需要创建任务句柄,任务句柄每个任务都是唯一的,任务的创建、挂起、删除等操作,都需要任务句柄。有了任务句柄,就可以使用xTaskCreate函数创建任务了。下面是我们在main.c中创建的任务。任务创建函数的说明均以注释的形式,进行说明。开始任务中创建了任务1与任务2,开始任务本身优先级为最低0,任务内容为控制LED1每500ms闪烁一次;任务1优先级为1,任务内容是控制LCD液晶屏刷屏;任务2优先级最高,任务内容是控制LED2每250ms闪烁一次。

static TaskHandle_t xTaskHandleStart = NULL;        /* ---任务句柄--- */
static TaskHandle_t xTaskHandleTask1 = NULL;
static TaskHandle_t xTaskHandleTask2 = NULL;

static void xTaskStart( void *pvParameters );       /* ---任务函数--- */
static void xTask1( void *pvParameters );
static void xTask2( void *pvParameters );

/**************************************************************
  * @Name    StartTaskCreate
  * @brief   创建开始任务
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
void StartTaskCreate( void )
{
    xTaskCreate( xTaskStart,            /* ---任务函数--- */
                 "xTaskStart",          /* ---任务名称--- */
                 1024,                  /* ---任务堆栈--- */
                 NULL,                  /* ---传入参数--- */
                 0,                     /* ---任务优先级--- */
                 &xTaskHandleStart );   /* ---任务句柄--- */
}

/**************************************************************
  * @Name    xTaskStart
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTaskStart( void *pvParameters )
{
    xTaskCreate( xTask1,                    /* ---任务函数--- */
                 "xTask1",                  /* ---任务名称--- */
                 512,                       /* ---任务堆栈--- */
                 NULL,                      /* ---传入参数--- */
                 1,                         /* ---任务优先级--- */
                 &xTaskHandleTask1 );       /* ---任务句柄--- */
    
    xTaskCreate( xTask2,                    /* ---任务函数--- */
                 "xTask2",                  /* ---任务名称--- */
                 512,                       /* ---任务堆栈--- */
                 NULL,                      /* ---传入参数--- */
                 2,                         /* ---任务优先级--- */
                 &xTaskHandleTask2 );       /* ---任务句柄--- */
    for( ;; )
    {
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN6, TCA9539_PIN_SET );
        vTaskDelay( 500 );
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN6, TCA9539_PIN_RESET );
        vTaskDelay( 500 );
    }
}
/**************************************************************
  * @Name    xTask1
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTask1( void *pvParameters )
{
    for( ;; )
    {
        LCD_Clear( RED );
        vTaskDelay( 200 );
        LCD_Clear( GREEN );
        vTaskDelay( 200 );
        LCD_Clear( BLACK );
        vTaskDelay( 200 );
        LCD_Clear( BLUE );
        vTaskDelay( 200 );
        LCD_Clear( YELLOW );
        vTaskDelay( 200 );
        LCD_Clear( MAGENTA );
        vTaskDelay( 200 );
        LCD_Draw_Circle( 200, 200, 100, BLACK );
        LCD_ShowString( 300, 300, lcddev.width, lcddev.height, 24, ( uint8_t * )"hello world", BLACK, MAGENTA );
        vTaskDelay( 1000 );
    }
}

/**************************************************************
  * @Name    xTask2
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTask2( void *pvParameters )
{
    for( ;; )
    {
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_SET );
        vTaskDelay( 250 );
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_RESET );
        vTaskDelay( 250 );
    }
}

下面是main.c中的内容:

/**
  ************************************* Copyright ******************************
  *
  *                 (C) Copyright 2022,Zachary ,HPU, China.
  *                            All Rights Reserved
  *
  * FileName   : main.c
  * Version    : v1.0
  * Author     : Zachary
  * Date       : 2023-02-13
  * Description: This is a template project of HC32F4A0
											---Zachary,in Zhejiang Hanpu.
  ******************************************************************************
 */

/* Includes --------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "os_includes.h"
#include "bsp_Gpio.h"
#include "bsp_TCA9539.h"
#include "bsp_NT35510.h"
#include "bsp_XPT2046.h"
#include "bsp_AT24Cxx.h"
/* --- Typedef -----------------------------------------------------------*/
/* --- Define ------------------------------------------------------------*/
/* --- Macro -------------------------------------------------------------*/
/* --- Variables ---------------------------------------------------------*/
stc_clock_freq_t sysclk;
uint8_t Reg = 0x20;
uint8_t ReadBuf[8];
uint8_t WriteBuf[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char DispBuf1[50], DispBuf2[50];

static TaskHandle_t xTaskHandleStart = NULL;
static TaskHandle_t xTaskHandleTask1 = NULL;
static TaskHandle_t xTaskHandleTask2 = NULL;
/* --- Functions ---------------------------------------------------------*/
static void SysInit( void );
static void bsp_SetSysClk( void );
static void LCD_Test( void );
static void xTaskStart( void *pvParameters );
static void xTask1( void *pvParameters );
static void xTask2( void *pvParameters );
/*------------------------------------------------------------------------*/

/**************************************************************
  * @Name    Load_Drow_Dialog
  * @brief   
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
void Load_Drow_Dialog( void )
{
    LCD_Clear( WHITE );//清屏
    LCD_ShowString( lcddev.width - 24, 0, lcddev.width, lcddev.height, 16, ( uint8_t * )"RST", BLACK, WHITE ); //显示清屏区域
}

/**************************************************************
  * @Name    rtp_test
  * @brief   电阻触摸屏测试函数
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
void rtp_test( void )
{
    Load_Drow_Dialog();
    while( 1 )
    {
        tp_dev.scan( 0 );
        if( tp_dev.sta & TP_PRES_DOWN )			//触摸屏被按下
        {
            if( tp_dev.x[0] < lcddev.width && tp_dev.y[0] < lcddev.height )
            {
                if( tp_dev.x[0] > ( lcddev.width - 24 ) && tp_dev.y[0] < 16 )
                    Load_Drow_Dialog();//清除
                else 
                    TP_Draw_Big_Point( tp_dev.x[0], tp_dev.y[0], RED );		//画图
            }
        }
        else
            delay_ms( 1 );	//没有按键按下的时候
    }
}

/**************************************************************
  * @Name    xTask1
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTask1( void *pvParameters )
{
    for( ;; )
    {
        LCD_Clear( RED );
        vTaskDelay( 200 );
        LCD_Clear( GREEN );
        vTaskDelay( 200 );
        LCD_Clear( BLACK );
        vTaskDelay( 200 );
        LCD_Clear( BLUE );
        vTaskDelay( 200 );
        LCD_Clear( YELLOW );
        vTaskDelay( 200 );
        LCD_Clear( MAGENTA );
        vTaskDelay( 200 );
        LCD_Draw_Circle( 200, 200, 100, BLACK );
        LCD_ShowString( 300, 300, lcddev.width, lcddev.height, 24, ( uint8_t * )"hello world", BLACK, MAGENTA );
        vTaskDelay( 1000 );
    }
}

/**************************************************************
  * @Name    xTask2
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTask2( void *pvParameters )
{
    for( ;; )
    {
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_SET );
        vTaskDelay( 250 );
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_RESET );
        vTaskDelay( 250 );
    }
}

/**************************************************************
  * @Name    xTaskStart
  * @brief   
  * @param   pvParameters: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
static void xTaskStart( void *pvParameters )
{
    xTaskCreate( xTask1,                    /* ---任务函数--- */
                 "xTask1",                  /* ---任务名称--- */
                 512,                       /* ---任务堆栈--- */
                 NULL,                      /* ---传入参数--- */
                 1,                         /* ---任务优先级--- */
                 &xTaskHandleTask1 );       /* ---任务句柄--- */
    
    xTaskCreate( xTask2,                    /* ---任务函数--- */
                 "xTask2",                  /* ---任务名称--- */
                 512,                       /* ---任务堆栈--- */
                 NULL,                      /* ---传入参数--- */
                 2,                         /* ---任务优先级--- */
                 &xTaskHandleTask2 );       /* ---任务句柄--- */
    for( ;; )
    {
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN6, TCA9539_PIN_SET );
        vTaskDelay( 500 );
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN6, TCA9539_PIN_RESET );
        vTaskDelay( 500 );
    }
}
/**************************************************************
  * @Name    StartTaskCreate
  * @brief   创建开始任务
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-23
 **************************************************************/
void StartTaskCreate( void )
{
    xTaskCreate( xTaskStart,            /* ---任务函数--- */
                 "xTaskStart",          /* ---任务名称--- */
                 1024,                  /* ---任务堆栈--- */
                 NULL,                  /* ---传入参数--- */
                 0,                     /* ---任务优先级--- */
                 &xTaskHandleStart );   /* ---任务句柄--- */
}
/**************************************************************
  * @Name    main
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-22
 **************************************************************/
int32_t main( void )
{
    SysInit();
//    sprintf( DispBuf1, "WirteBuf:%d,%d,%d,%d,%d,%d,%d,%d", WriteBuf[0], WriteBuf[1], \
//    WriteBuf[2], WriteBuf[3], WriteBuf[4], WriteBuf[5], WriteBuf[6], WriteBuf[7] );
//    LCD_ShowString( 10, 500, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf1, WHITE, BLACK );

//    AT24Cxx_I2C_Write( AT24Cxx_Addr, &Reg, 0x01, WriteBuf, 0x08 );
//    delay_ms( 10 );
//    AT24Cxx_I2C_Read( AT24Cxx_Addr, &Reg, 0x01, ReadBuf, 0x08 );

//    sprintf( DispBuf2, "ReadBuf:%d,%d,%d,%d,%d,%d,%d,%d", ReadBuf[0], ReadBuf[1], \
//    ReadBuf[2], ReadBuf[3], ReadBuf[4], ReadBuf[5], ReadBuf[6], ReadBuf[7] );
//    LCD_ShowString( 10, 550, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf2, WHITE, BLACK );
//    delay_ms( 1000 );
//    rtp_test();
    StartTaskCreate();
    vTaskStartScheduler();
    while( 1 )
    {
//        LED10_TOGGLE();
//        LED11_TOGGLE();
//        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_SET );
//        delay_ms( 500 );
//        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_RESET );
//        delay_ms( 500 );
    }
}

/**************************************************************
  * @Name    SysInit
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-02-13
 **************************************************************/
static void SysInit( void )
{
    bsp_SetSysClk();
    CLK_GetClockFreq( &sysclk );	/* ---检查时钟是否正确--- */
    delay_init( 240 );				/* ---系统滴答定时器初始化--- */
    bsp_Gpio_Init();				/* ---初始化Gpio--- */
    bsp_TCA9539_Init();
//    TCA9539_ConfigPin( TCA9539_IO_PORT1, TCA9539_IO_PIN5, TCA9539_DIR_OUT );
    TCA9539_ConfigPin( TCA9539_IO_PORT1, TCA9539_IO_PIN6, TCA9539_DIR_OUT );
    TCA9539_ConfigPin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_DIR_OUT );
    bsp_NT35510_Init();
//    LCD_Test();
    bsp_XPT2046_Init();

}

/**************************************************************
  * @Name    LCD_Test
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-04
 **************************************************************/
static void LCD_Test( void )
{
    LCD_Clear( RED );
    delay_ms( 500 );
    LCD_Clear( GREEN );
    delay_ms( 500 );
    LCD_Clear( BLACK );
    delay_ms( 500 );
    LCD_Clear( BLUE );
    delay_ms( 500 );
    LCD_Clear( YELLOW );
    delay_ms( 500 );
    LCD_Clear( MAGENTA );
    delay_ms( 500 );
    LCD_Draw_Circle( 200, 200, 100, BLACK );
    LCD_ShowString( 300, 300, lcddev.width, lcddev.height, 24, ( uint8_t * )"hello world", BLACK, MAGENTA );
}

/**************************************************************
  * @Name    SetSysClk
  * @brief	 参考自官方工程
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-02-13
 **************************************************************/
static void bsp_SetSysClk( void )
{
    stc_clock_xtal_init_t stcXtalInit;
    stc_clock_pll_init_t stcPLLHInit;

    LL_PERIPH_WE( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                  LL_PERIPH_EFM | LL_PERIPH_SRAM );		/* ---解保护相关外设--- */

    /* PCLK0, HCLK  Max 240MHz */
    /* PCLK1, PCLK4 Max 120MHz */
    /* PCLK2, PCLK3 Max 60MHz  */
    /* EX BUS Max 120MHz */
    CLK_SetClockDiv( CLK_BUS_CLK_ALL, \
                     ( CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
                       CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
                       CLK_HCLK_DIV1 ) );				/* ---外设总线分频--- */

    CLK_XtalStructInit( &stcXtalInit );
    /* Config Xtal and enable Xtal */
    stcXtalInit.u8Mode   = CLK_XTAL_MD_OSC;			/* ---选择外部晶振--- */
    stcXtalInit.u8Drv    = CLK_XTAL_DRV_ULOW;		/* ---晶振驱动能力 有源晶振驱动能力强--- */
    stcXtalInit.u8State  = CLK_XTAL_ON;
    stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS;	/* ---晶振稳定等待周期--- */
    CLK_XtalInit( &stcXtalInit );

    CLK_PLLStructInit( &stcPLLHInit );				/* ---锁相环寄存器初始化--- */
    /* VCO = (8/1)*120 = 960MHz*/
    stcPLLHInit.u8PLLState = CLK_PLL_ON;
    stcPLLHInit.PLLCFGR = 0UL;
    stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
    CLK_PLLInit( &stcPLLHInit );

    /* Highspeed SRAM set to 0 Read/Write wait cycle */
    SRAM_SetWaitCycle( SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0 );

    /* SRAM1_2_3_4_backup set to 1 Read/Write wait cycle */
    SRAM_SetWaitCycle( ( SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB ), SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1 );

    /* 0-wait @ 40MHz */
    EFM_SetWaitCycle( EFM_WAIT_CYCLE5 );

    /* 4 cycles for 200 ~ 250MHz */
    GPIO_SetReadWaitCycle( GPIO_RD_WAIT4 );

    CLK_SetSysClockSrc( CLK_SYSCLK_SRC_PLL );

    LL_PERIPH_WP( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                  LL_PERIPH_EFM | LL_PERIPH_SRAM );		/* ---保护相关外设--- */
}

视频展示:

633b71556d384ccc70ddc300ca837c3c

 

FreeRTOS源码与测试工程代码:

FreeRTOSv10.3.0.7z (143.74 KB, 下载次数: 57)
HC32F4A0_FreeRTOS.7z (1.12 MB, 下载次数: 110)

最新回复

非常感谢 大老   详情 回复 发表于 2024-3-22 09:11

赞赏

1

查看全部赞赏

点赞(5) 关注(1)
 
 

回复
举报

210

帖子

3

TA的资源

一粒金砂(高级)

沙发
 

不错啊,值得学习、收藏的帖子,一直想找机会学习RTOS呢。谢谢楼主分享!

 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

板凳
 

谢谢分享!

个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 

很好

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 

非常感谢 大老

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表