3回答

1收藏

GD32F190R8小红板+ Colibri RTOS下的 LED闪亮控制(含环境搭建)

GD32 GD32 4777 人阅读 | 3 人回复 | 2016-06-15

本帖最后由 wolfgang2015 于 2016-6-15 20:36 编辑

项目所含内容
1、通过KEIL和GD官方开发库,搭建标准开发模板;
2、在小红板硬件建立Colibri RTOS系统;
3、通过线程控制的LED心跳时钟;
4、通过实时响应按键并控制修改另外一个LED闪亮频率。

首先感谢爱板网、GD32官方、Trochili RTOS系统共同举办这次活动,能对GD32、TrochiliRTOS有了进一步的认识和了解。

一、资料软件的准备:
1、ARM嵌入式系统开发利器KEIL软件
在KEIL官方网站(http://www.keil.com/)下载需要用的ARM开发工具,这里需要用邮件注册一下就能下载了。

2、GD32F190R8小红板的资料
    通过本次GD32活动页面 (https://www.cirmall.com/gd32f190mcu/?ziliao)下载所有能用到的工具及软件包,这里的资料分类如下:
  《MCU选型及培训资料》有助于了解GD全系列,并为F190作好应用定位;
  《MCU数据手册及固件库》是所芯片数据手册、用户手册以及Keil发所需的固件;
  《MCU应用软件》是MCU编程所需的各种上位软件
  《MCU开发板资料》是针对开发板驱动、原理图及引脚分布相关资料,并包含了Trochili V0.12的RTOS实时系统的相关资料的内容;
这里能用到的必要资料内如下:
a、芯片资料相关内容:
GD32F190xxDatasheet Rev1.0.pdf


GD32F1x0_User_Manual_CN_v2.0_20160115.pdf


GD32F1x0_User_Manual_EN_v2.0_20160115.pdf


GD32F1x0_Firmware_Library_V2.0.0.rar


b、开发板相关资料内容:
Keil.GD32F1x0_DFP.2.0.0.rar


GD32Colibri-F190R8-原理图.pdf


GD32Colibri-F190R8-管脚分配与开发板布局.xlsx


GD32_Colibri_F190R8_TROCHILI_V0.12_PRV4代码.rar


第01章嵌入式内核基础.pdf


*3、资料中ColibriF190主板芯片资源总览
a、芯片资源总览:




从GD32F190R8的芯片功能看,GD32F190R8的功能十分丰富,有通常的GPIOA、B、C、D、F之外,还有Usart、CAN、IIC、IIS、SPI、Timer1、2、3、14~17等功能,还有对模拟电路的红外发送、ADC、DAC、比较器、放大等功能,还有可通过HDMI接口控制的功能,可谓全能小强。唯一美中不足的就是不支持USB,不过功能已经很丰富了,有待对各功能模块进一步探索。
b、主板资源总缆:


主板外侧引脚定义如上图, 引脚能兼容Arduino定义

主板内侧引脚定义,是ColibriF190主板个性的引脚定义
   从上两主板图可看出F190板子是将所有功能引出的全功能板。主板是通过USB集线器芯片分别连接到CH340G和GD32F103芯片上,实现了一个USB既能实现CMSIS-DAP对F190主芯片的调试下载,又能通过Ch340连接到主芯片的F190的UsartRX/TX接口进行信息通信。美中不足的地方还是有:是虽然提供GD-LINK(CMSIS-DAP)和引出功能引脚,但不能方便的将F190与电源切断,无法利用GD-LINK来对其他GD32芯片进行调试。


二、GD32F190R8在KEIL开发环境中的搭建
1、KEIL中引入GD32开发包


  第一步:在Keil面板中,选择“Pack Installer”功能,这是会弹出一个新的窗口“Pack Installer”,

  第二步:在File--〉Import 功能中,选择在第一章节中下载并解压的Pack文件(在Keil.GD32F1x0_DFP.2.0.0.rar压缩文件中)并导入。
导入之后,就能导入一个叫GigaDevice的节点,打开后能看见GD32F130、150、170、190系列的芯片,其中就有R8的芯片型号。

2、KEIL中建立GD32F190R8的工程
a、第一步:空工程的建立





选择Project--〉“New uVision Project...”,在弹出窗口中,选择好目录,并输入项目名称“GD32F190R8_Clock”

  在Select Device for Target 窗口中,选择“GigaDevice”--〉“GD32F1x0Series”--〉“GD32F190”--〉“GD32F190R8”,点击OK继续。


  在“Manage Run-TimeEnvironment”窗口中直接点OK,跳过选择。
  这时就建立了一个空的,名为GD32F190项目

b、第二步:项目文件目录规划及文件引入
代码按目录做好分类:



Board:存放BSP的相关目录和代码
DOC:存放一些说明文档
Firmware:是直接取自 “GD32F1x0_Firmware_Library_V2.0.0.rar\GD32F1x0_Firmware_Library_V2.0.0\Firmware”的目录
Trochili:是直接取自
“GD32_Colibri_F190R8_TROCHILI_V0.12_PRV4代码.rar\trochili_v0.12_preview4\trochili”目录下的inc和src目录。
User:是应用代码存放的目录
Readme.txt:文件用于存放对应用代码的说明和注意事项



然后利用"FileExtensions,Books and Environment"将文件项目文件引入工程项目。

在ManageProject Items 中,在Project Targets中输入项目目标名称“GD32F190R8_Clock”,在Groups中分别输入分类名:
a、Startup(用于存放启动的.S文件);
b、CMSIS(用于存放使用CMSIS访问控制ARM M3芯片的接口文件);
c、GD32F1x0_Library(用于存放GD32F190基类固件库文件)
d、BSP(用于存放ColibriF190板级支撑包的文件)
e、Trochili(用于存放 TrochiliRTOS相关的代码)
f、User(用于存放应用的代码,这里是存放LED项目的代码)
g、Demo(项目开发过程中的一些测试、演示代码)

a至c是通用的建立步骤,d至g是选用的,这里为方便评估GD芯片、ColibriF190主板、以及Trochili RTOS ,把a至g的分类都做好。

工程管理集、代码目录都做好归类后,将Firmware中的代码引入工程:

同样是在"FileExtensions,Books and Environment"功能中,选择对应的“Groups”点击Add Files,把目录中的代码引入到项目中:
Startup 中加入以下文件:
    .\Firmware\CMSIS\ARM\startup_gd32f1x0.s
CMSIS中加入以下文件:
    .\Firmware\CMSIS\system_gd32f1x0.c
GD32F1x0_Library中加入以下文件:
    .\ Firmware\Peripherals\src\*.c
User 添加的文件主要参考“GD32F1x0_Firmware_Library_V2.0.0.rar\GD32F1x0_Firmware_Library_V2.0.0\Template”目录下的 Systick.c、Systick.h、gd32F1x0_it.c、gd32F1x0_it.h、gd32f1x0_conf.h、main.c 6个文件。
   将这6个文件存放在.\User目录中

  值得注意的是,如果要用Trochili系统的同学Systick.c、Systick.h、gd32F1x0_it.c、gd32F1x0_it.h 这四个文件不要引入工程,这会跟Trochili系统设置冲突。



c、第三步:编译环境配置



需要配置目标代码的编译环境,点击“Options for Target...”按钮



在Optionsfor Target 窗口的 “C/C++”标签栏中,Preprocessor Symbols的Define配置中输入:“USE_STDPERIPH_DRIVER,GD32F170_190”
在IncludePath 配置中把对应的文件路径设置如下:


1)、Keil工具下的CMSIS引用包,这里选用的include Paths为:“X:Keil_5\ARM\Pack\ARM\CMSIS\4.5.0\CMSIS\Include”。具体的目录为Keil文件中的CMSIS目录,可以在ARM Pack中更新最新的CMSIS版本。
2)、Firmware在include Paths增加:
  .\Firmware
  .\Firmware\CMSIS
  .\Firmware\Peripherals
  .\Firmware\Peripherals\inc
3)、用户文件在include Paths增加;
“.\User”



  在Debug标签页中选择“CMSIS-DAP Debugger”后,能通过KEIL调试开发板了。

  至此,已经可以通过在User目录中增加相关功能函数实现对F190芯片引脚的初始化及相关操作来实现一些基本功能的程序开发。但这不是这实战的目标,在日常开发中需要建立更规范工程格式,就得把相关操作及初始化使用BSP的方式实现,便于项目和代码的迭代管理。

3、在KEIL中建立BSP
a、第一步建立文件存放目录
在.\Board目录下增加一个叫ColibrilF190的子目录:

b、第二步将Colibril主板各功能控制代码添加到BSP组内;
功能控制代码都存放在.\Board\ColibrilF190目录中



根据项目功能,这里添加了用于控制板在功能的BSP文件:
ColibriF190_BSP: 是板载支撑包的公共文件;
ColibriF190_BSP_LED:实现LED的控制功能;
ColibriF190_BSP_KEY:实现KEY的控制功能;
ColibriF190_BSP_Usart:实现Usart的控制功能。


c、第三步将BSP的目录路径添加到includePaths中:



    .\board
    .\board\ColibrilF190

    这里可以通过Main函数来调用相应的功能,来对模块进行测试;功能模块具备条是通过后,就需要引入调试机制将各个功能模块有机的组合在一起,一起步入RTOS到工程中。

4、在KEIL中引入TROCHILIRTOS
a、第一步将Trochili目录中源文件引入到项目中:




b、第二步将Trochili的目录路径添加到include Paths中:
Trochili在includePaths增加:


  .\Trochili
  .\Trochili\inc
  .\Trochili\inc\cpu
  .\Trochili\inc\ipc
  .\Trochili\inc\lib
  .\Trochili\inc\mem

  这里项目所需的基础工作都引入到了工程中,可以在此基础上开发基于ColibriF190、Trochili RTOS的开发相关应用了。
备注:TROCHILI的控制原理及操作可以通过“GD32_Colibri_F190R8_TROCHILI_V0.12_PRV4代码.rar”的例程来熟悉,这就就不多讲了,另外《嵌入式实时操作系统原理与最佳实践》这本书是跟“TROCHILI RTOS”有关的,可以作为TROCHILI 上手的参考。

三、GD32F190R8RTOS LED闪亮功能设计
1、LED控制功能设计与实现
a、功能规划
主板上的LED与F190引脚的电路连接如下,若要控制LED就需要对对应的引脚做初始化:
   LED4--PB10
   LED5--PB8
   LED6--PB9
b、功能初始化
void Led_Config(void){
         GPIO_InitPara    GPIO_InitStructure;
         /*    Enable the LED Clock */
         RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB,ENABLE);
         /*    Configure the LED pin */
         GPIO_InitStructure.GPIO_Pin    = GPIO_PIN_8 | GPIO_PIN_9|GPIO_PIN_10;
         GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT;
         GPIO_InitStructure.GPIO_OType    = GPIO_OTYPE_PP;
         GPIO_InitStructure.GPIO_PuPd    = GPIO_PUPD_NOPULL;
         GPIO_InitStructure.GPIO_Speed    = GPIO_SPEED_50MHZ;
         GPIO_Init(GPIOB,&GPIO_InitStructure);
}

c、功能维护和使用
   此功能主要存放在" ColibriF190_BSP_LED"中,便于维护和使用;
   这里初始化主要进行GPIO的时钟设置,并设置引脚的初始化参数。初始化完成后,利用固件中的GPIO_SetBits()/ GPIO_ResetBits()函数进行操作了,本文略过。

2、KEY控制功能设计与实现
a、功能规划
   B2--PA0
   B3--PB7
   B4--PB6
b、功能初始化
void Key_Config(void){
         GPIO_InitPara    GPIO_InitStructure;
         EXTI_InitPara    EXTI_InitStructure;
         NVIC_InitPara    NVIC_InitStructure;
         /* Enable the KEY Clock */
        RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);  
        /* Enable the KEY Clock */
        RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);
        /* Configure KEY pin */
       GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6;
       GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN;
       GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_NOPULL;
       GPIO_Init(GPIOB, &GPIO_InitStructure);
       GPIO_InitStructure.GPIO_Pin = GPIO_PIN_7;
       GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN;
       GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_NOPULL;
       GPIO_Init(GPIOB, &GPIO_InitStructure);
       /* Enable SYSCFG clock */
      RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_CFG, ENABLE);
      /* Connect EXTI Line6/7 to PB6/7 pin */
     SYSCFG_EXTILine_Config(EXTI_SOURCE_GPIOB, EXTI_SOURCE_PIN6);
     SYSCFG_EXTILine_Config(EXTI_SOURCE_GPIOB, EXTI_SOURCE_PIN7);     
     /* Configure EXTI Line6/7 and its    interrupt to the lowest priority*/
     EXTI_InitStructure.EXTI_LINE = EXTI_LINE6;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
     EXTI_InitStructure.EXTI_LINEEnable = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
     EXTI_ClearIntBitState(EXTI_LINE6);
     /* Configure EXTI Line6/7 and its    interrupt to the lowest priority*/
     EXTI_InitStructure.EXTI_LINE = EXTI_LINE7;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
     EXTI_InitStructure.EXTI_LINEEnable = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
     EXTI_ClearIntBitState(EXTI_LINE7);
     /* 1 bits for pre-emption priority and    3 bits for subpriority */
    NVIC_PRIGroup_Enable(NVIC_PRIGROUP_1);
    /* Enable and set EXTI4_15 Interrupt to    the highest priority */
    NVIC_InitStructure.NVIC_IRQ = EXTI4_15_IRQn;
    NVIC_InitStructure.NVIC_IRQPreemptPriority = 0;
    NVIC_InitStructure.NVIC_IRQSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
    NVIC_Init(&NVIC_InitStructure);        
}

c、功能维护和使用
  此功能主要存放在" ColibriF190_BSP_KEY"中,便于维护和使用;
  Key的初始化有以下内容:
  1)初始化GPIO时钟、配置GPIO引脚参数;
  2)配置系统时钟,将GPIO与外部中断功能关联,配置外部中断功能参数;
  3)外部中断与中断控制器优先级组别关联,配置中断控制器优先级功能参数。
  这里对KEY的主要是进行按键的扫描,在扫描函数中,用EXTI_GetIntBitState()来识别第几口发生的中断,配置对应的按键值,便于应用识别。操控方式略。

3、USART控制功能设计与实现
a、功能规划
   USART2_RX(1)--PA3
   USART2_TX(1)--PA2
b、功能初始化
void Usart_Config (void){
        /* Configure the GPIO ports */
       GPIO_InitPara     GPIO_InitStructure;
       USART_InitPara     USART_InitStructure;
       /* Enable GPIO clock */
       RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOA, ENABLE);
       /* Enable USART APB clock */
       RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_USART2, ENABLE);
       /* Connect PXx to USARTx_Tx */
       GPIO_PinAFConfig(GPIOA, GPIO_PINSOURCE2, GPIO_AF_1);
       /* Connect PXx to USARTx_Rx */
      GPIO_PinAFConfig(GPIOA, GPIO_PINSOURCE3, GPIO_AF_1);
      /* Configure USART Rx/Tx as alternate    function push-pull */
     GPIO_InitStructure.GPIO_Pin     = GPIO_PIN_2 | GPIO_PIN_3;
     GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_AF;
     GPIO_InitStructure.GPIO_Speed   = GPIO_SPEED_50MHZ;
     GPIO_InitStructure.GPIO_OType   = GPIO_OTYPE_PP;
     GPIO_InitStructure.GPIO_PuPd    = GPIO_PUPD_NOPULL;
     GPIO_Init(GPIOA    , &GPIO_InitStructure);
     USART_DeInit( USART2 );
     USART_InitStructure.USART_BRR                 = 115200;
     USART_InitStructure.USART_WL                  = USART_WL_8B;
     USART_InitStructure.USART_STBits              = USART_STBITS_1;
     USART_InitStructure.USART_Parity              = USART_PARITY_RESET;
     USART_InitStructure.USART_HardwareFlowControl    = USART_HARDWAREFLOWCONTROL_NONE;
     USART_InitStructure.USART_RxorTx              = USART_RXORTX_RX |    USART_RXORTX_TX;
     USART_Init(USART2,    &USART_InitStructure);
     /* USART enable */
    USART_Enable(USART2, ENABLE);
}

c、功能维护和使用
  此功能主要存放在" ColibriF190_BSP_USART"中,便于维护和使用;
  Usart的初始化有以下内容:
  1)初始化GPIO时钟、配置GPIO引脚复用功能参数,选择GPIO的AF1;
  2)配置GPIO引脚与USART功能的参数,并初始化;
  3)配置USART功能的电气特性参数,初始化并打开USART。
  使用Usart的功能主要有Read()和Write()实现对USART的读写通信联系。操控方式略。

4、基于RTOS、SGD32F190、LED的系统线程的设计与实现
a、针对LED、KEY、USART等测试应用线程规划
   1)LED4 心跳线程,LED4随定线程定时器值闪亮或熄灭,作为系统心跳指示;
   2)LED5 闪亮频率可变线程,但该线程可以随按键改变延时值,以达到改变闪亮和熄灭频率的目的;
   3)USART收发线程,通过USART与电脑串口的通信;

b、Trochili RTOS应用线程配置与实现
  使用Trochili RTOS 按照上边的配置步骤配置好后,需要做以下工作:
1)引入“trochili.h"”;
2)设置线程的栈大小、线程优先级、线程时间片大小;
3)线程实体;
4)用户应用实体 AppSetupEntry();
5)Main函数实体;

//引入trochili.h
#include "trochili.h"
......
//设置线程栈大小、优先级、时间片
#define THREAD_LED_STACK_BYTES   (128)
#define THREAD_LED_PRIORITY      (5)
#define THREAD_LED_SLICE         (1)
   
static TWord    ThreadLedFlashStack[THREAD_LED_STACK_BYTES/4];
.....
//线程实体
   
static void ThreadLedFlashEntry(TArgument    data){
     ..
}
....
//用户应用实体
static void AppSetupEntry(void){
}
....
int main(void){
       //注册内核并启动内核
       TclStartKernel(&AppSetupEntry,
                   &CpuSetupEntry,
                   &Colibri_Config,
                   &Colibri_Usart2_WriteStr);
        return 1;
}

Main函数中,除开AppSetupEntry、Colibri_Usart2_WriteStr是用户定义外,Colibri_Config、Colibri_Usart2_WriteStr均为RTOS的系统定义函数。
   注意:“Colibri_Usart2_WriteStr”是串口功能,具体实现在Usart模块中。

c、线程调度策略
1) 用户定时器
LED4 心跳线程,这里可以安排一个RTOS的Timer作为延时控制。LED的主线程就是初始化Timer、启动Timer的线程,启动完毕后,线程处于死循环状态;

static TTimer Led_4Timer;
......
static void    ThreadLedTIMEREntry(TArgument data){
     TError error;
     TState state;
     state = TclInitTimer(&Led_4Timer,
                       TCLP_TIMER_PERIODIC,
                       TCLM_MLS2TICKS(Delay_16),
                       &BlinkLed1,
                       (TArgument)0,
                       &error);
    TCLM_ASSERT((state == eSuccess), "");
    TCLM_ASSERT((error == TCLE_TIMER_NONE), "");
    state = TclStartTimer(&Led_4Timer,    TCLM_MLS2TICKS(Delay_0), &error);
    TCLM_ASSERT((state == eSuccess), "");
    TCLM_ASSERT((error == TCLE_TIMER_NONE), "");
    while (eTrue)
     {
     }
}

2) 受控变频率LED闪亮线程
LED5闪亮频率可变线程,这里安排一个独立的线程,外加一个按键中断相应事件来实现;首先在用户应用实体中增加按键中断应用;然后在中断处理函数中(KEYISR)实现按键修改的岩石变量值,最后LED线程中设置闪亮延时可变量,通过按键修改的值将对LED延时产生影响,达到改变闪亮频率的目的。
   
static void AppSetupEntry(void){
      TState    state;
      TError error;
...
     state = TclSetIrqVector(KEY_IRQ_ID, &ColibriF190_KeyISR,    (TArgument)0, (TThread*)0, &error);
     TCLM_ASSERT((state == eSuccess), "");
     TCLM_ASSERT((error == TCLE_IRQ_NONE), "")
...
}

      
static void    ThreadLedFlashEntry(TArgument data){
     TState    state;
     TError error;
     TThread*    pThread;
     pThread = (TThread*)data;
     while    (eTrue){            
          //LED5    ON
          Led_Control(LED_5,    ON);
          state=TclDelayThread(pThread,    TCLM_MLS2TICKS(delay), &error);
          TCLM_ASSERT((state    == eSuccess), "");
          TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
   
          //LED5    OFF
          Led_Control(LED_5,    OFF);
          state = TclDelayThread(pThread, TCLM_MLS2TICKS(delay), &error);
          TCLM_ASSERT((state == eSuccess), "");
          TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
     }
}

static TBitMask    ColibriF190_KeyISR(TArgument data) {
       uint8_t    key;
       key=Key_Scan();
       switch(key){
              case    KEY_B4:{
                   Key_ADD();
                   break;
              }
   
              case    KEY_B3:{
                   Key_DEC();
                   break;
              }
   
             default:{
                   break;
             }
         }
         return    TCLR_IRQ_DONE;
}
   
四、心得体会
  通过该实战熟悉了GD32开发环境搭建、F190芯片资源配置、RTOS的使用:
1、熟悉了GD32F1x0在Keil开发环境中的标准模板搭建;
2、熟悉了GD32F190的GPIO操作、中断控制、USART资源配置
3、熟悉了TrochiliRTOS系统的相关线程操作及调用;

五、问题
  将RTOS引入应用后,在Trochili0.12的软件包中,只要延时或定时小于10ms(TCLM_MLS2TICKS(9)),线程就无法启动,在使用时尽量避免使用小于10ms(TCLM_MLS2TICKS(9))的延时延时和定时。

效果如下图 按B3延时减少,按B4延时增加





分享到:
回复

使用道具 举报

回答|共 3 个

倒序浏览

沙发

whtt

发表于 2016-6-18 23:10:04 | 只看该作者

超赞,学习了
板凳

trochili

发表于 2016-6-21 15:13:28 | 只看该作者

一灯大师修炼到rtos阶段了。
eeboard大力支持的开源RTOS -- Trochili RTOS
地板

wolfgang2015

发表于 2016-6-21 16:55:00 | 只看该作者

trochili 发表于 2016-6-21 15:13
一灯大师修炼到rtos阶段了。

赫赫,继续修炼BSP
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条