本帖最后由 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小红板的资料 《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延时增加
|