从新唐 官网下载的:BSP
Nano100B_Series_BSP_CMSIS_V3.02.000.zip
从freertos 网站下载的:
FreeRTOSV8.2.3.zip
参考文档:
FreeRTOS在Nano100上的移植.pptx
参考例程:
[Nano100B]FREERTOS.zip
1 解压 Nano100B_Series_BSP_CMSIS_V3.02.000.zip
进入如下目录,
打开keil工程
E:\freertos\nano100\Nano100B Series BSP_CMSIS_V3.02.000\SampleCode\StdDriver\UART_TxRx_Function\KEIL
双击:UART_TxRx_Function.uvproj
UART0:
在此项目的基础上,添加 Freertos的支持。
注意实际上使用如下模板工程,效果更好
E:\freertos\nano100\Nano100B Series BSP_CMSIS_V3.02.000\SampleCode\Template\Keil\
2 解压FreeRTOSV8.2.3.zip
建立 目录 E:\freertos\nano100\Nano100B Series BSP_CMSIS_V3.02.000\
在此目录下,解压FreeRTOSV8.2.3.zip
得到,如下目录结构
E:\freertos\nano100\Nano100B Series BSP_CMSIS_V3.02.000\ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source
3 添加文件FreeRTOS到UART_TxRx_Function
添加分组:Freertos
添加文件:
E:\freertos\nano100\Nano100B Series BSP_CMSIS_V3.02.000\ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source
list.c
queue.c
tasks.c
timers.c
ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source\portable\RVDS\ARM_CM0
port.c
ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source\portable\MemMang
heap_2.c
最后的效果图:
4 添加 include路径到 keil 工程
……..\ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source\include
……..\ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Source\portable\RVDS\ARM_CM0
……..\ThirdParty\FreeRTOSV8.2.3\FreeRTOS\Demo\Common\include
….\UART_TxRx_Function
5 添加 FreeRTOSConfig.h文件
添加FreeRTOSConfig.h文件到目录
Nano100B Series BSP_CMSIS_V3.02.000\SampleCode\StdDriver\UART_TxRx_Function\ 下面:
内容为:
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
/* Ensure stdint is only used by the compiler, and not the assembler. */
#ifdef __ICCARM__
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#ifdef __ARMCC_VERSION
#include "nano100series.h"
#endif
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 50 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_QUEUE_SETS 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
6 编译错误
会出现如下错误:
.\obj\UART.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o).
.\obj\UART.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o).
.\obj\UART.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_2.o).
Not enough information to produce a FEEDBACK file.
Not enough information to list image symbols.
Finished: 2 information, 0 warning and 3 error messages.
".\obj\UART.axf" - 3 Error(s), 0 Warning(s).
7 修改main.c文件
添加如下函数:
vApplicationTickHook
void vApplicationTickHook(void)
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
}
vApplicationIdleHook
void vApplicationIdleHook(void)
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
}
vApplicationMallocFailedHook
void vApplicationMallocFailedHook(void)
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
taskDISABLE_INTERRUPTS();
for(;;);
}
添加如下头文件:
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
8 编译成功
9 修改main.c
添加如下函数:
#define THREAD_TEST_STACK_SIZE configMINIMAL_STACK_SIZE
#define THREAD_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
void Thread_Task1( void *pvParameters );
void Thread_Task2( void *pvParameters );
void vStartThreadTasks( void )
{
xTaskCreate( Thread_Task1, (const char * ) "Th_Task1", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );
xTaskCreate( Thread_Task2, (const char * ) "Th_Task2", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );
}
void Thread_Task1( void *pvParameters )
{
portTickType xLastTime1;
/* Get current system TickCount. */
xLastTime1 = xTaskGetTickCount();
for( ;; )
{
/* Run a time every 400 milliseconds. */
vTaskDelayUntil( &xLastTime1, 400 );
printf("Task1 called-\n");
}
}
void Thread_Task2( void *pvParameters )
{
portTickType xLastTime2;
/* Get current system TickCount. */
xLastTime2 = xTaskGetTickCount();
for( ;; )
{
/* Run a time every 800 milliseconds. */
vTaskDelayUntil( &xLastTime2, 800 );
printf("Task2 called--\n");
}
}
修改main函数:
int main(void)
{
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Init UART0 for printf */
UART0_Init();
/* Init UART1 for test */
UART1_Init();
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
printf("\n\nCPU @ %dHz\n", SystemCoreClock);
printf("+---------------------+\n");
printf("| UART function test |\n");
printf("+---------------------+\n");
vStartThreadTasks();
vTaskStartScheduler();
while(1);
}
整体的main.c文件:
#include <stdio.h>
#include "Nano100Series.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "uart.h"
#define RXBUFSIZE 1024
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t g_u8SendData[12] = {0};
uint8_t g_u8RecData[RXBUFSIZE] = {0};
volatile uint32_t g_u32comRbytes = 0;
volatile uint32_t g_u32comRhead = 0;
volatile uint32_t g_u32comRtail = 0;
volatile int32_t g_bWait = TRUE;
volatile int32_t g_i32pointer = 0;
/*---------------------------------------------------------------------------------------------------------*/
/* Define functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void);
void UART1_TEST_HANDLE(void);
void UART_FunctionTest(void);
void vApplicationTickHook(void)
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
}
void vApplicationIdleHook(void)
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
}
void vApplicationMallocFailedHook(void)
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
taskDISABLE_INTERRUPTS();
for(;;);
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable External XTAL (4~24 MHz) */
CLK->PWRCTL |= (0x1 << CLK_PWRCTL_HXT_EN_Pos); // HXT Enabled
/* Waiting for 12MHz clock ready */
CLK_WaitClockReady( CLK_CLKSTATUS_HXT_STB_Msk);
/* Switch HCLK clock source to XTAL */
CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLK_S_Msk;
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_HXT;
/* Enable IP clock */
CLK->APBCLK |= CLK_APBCLK_UART0_EN; // UART0 Clock Enable
CLK->APBCLK |= CLK_APBCLK_UART1_EN; // UART1 Clock Enable
/* Select IP clock source */
CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
CLK->CLKSEL1 |= (0x0 << CLK_CLKSEL1_UART_S_Pos);// Clock source from external 12 MHz or 32 KHz crystal clock
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set PB multi-function pins for UART0 RXD and TXD */
SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB0_MFP_UART0_RX | SYS_PB_L_MFP_PB1_MFP_UART0_TX);
/* Set PB multi-function pins for UART1 RXD, TXD, RTS, CTS */
SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB4_MFP_Msk | SYS_PB_L_MFP_PB5_MFP_Msk |
SYS_PB_L_MFP_PB6_MFP_Msk | SYS_PB_L_MFP_PB7_MFP_Msk);
SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB4_MFP_UART1_RX | SYS_PB_L_MFP_PB5_MFP_UART1_TX |
SYS_PB_L_MFP_PB6_MFP_UART1_RTS | SYS_PB_L_MFP_PB7_MFP_UART1_CTS);
/* Lock protected registers */
SYS_LockReg();
}
void UART0_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
UART_Open(UART0, 115200);
}
#define THREAD_TEST_STACK_SIZE configMINIMAL_STACK_SIZE
#define THREAD_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
void Thread_Task1( void *pvParameters );
void Thread_Task2( void *pvParameters );
void vStartThreadTasks( void )
{
xTaskCreate( Thread_Task1, (const char * ) "Th_Task1", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );
xTaskCreate( Thread_Task2, (const char * ) "Th_Task2", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );
}
void Thread_Task1( void *pvParameters )
{
portTickType xLastTime1;
/* Get current system TickCount. */
xLastTime1 = xTaskGetTickCount();
for( ;; )
{
/* Run a time every 400 milliseconds. */
vTaskDelayUntil( &xLastTime1, 400 );
printf("Task1 called-\n");
}
}
void Thread_Task2( void *pvParameters )
{
portTickType xLastTime2;
/* Get current system TickCount. */
xLastTime2 = xTaskGetTickCount();
for( ;; )
{
/* Run a time every 800 milliseconds. */
vTaskDelayUntil( &xLastTime2, 800 );
printf("Task2 called--\n");
}
}
int main(void)
{
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Init UART0 for printf */
UART0_Init();
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
printf("\n\nCPU @ %dHz\n", SystemCoreClock);
printf("+---------------------+\n");
printf("| UART function test |\n");
printf("+---------------------+\n");
vStartThreadTasks();
vTaskStartScheduler();
while(1);
}
运行log为:
CPU @ 12000000Hz
+---------------------+
| UART function test |
+---------------------+
Task1 called-
Task2 called--
Task1 called-
Task1 called-
Task2 called--
Task1 called-
10 nuc140的移植freertos,并且LED闪烁
和上面的类似:
使用的是 NUC100_120BSP_v3.00.002.zip
和
FreeRTOSV8.2.3.zip
在如下工程的基础上修改,
E:\Nu_LB_Nuc140\NUC100_120BSP_v3.00.002_freertos\NUC100_120BSPv3.00.002\SampleCode\Template
修改后的工程为:
资源下载地址:
https://download.youkuaiyun.com/download/wowocpp/10622226
对应的板子为Nu_LB_Nuc140
对应的LED为:
对应的UART为:
12 需要删除掉的东西
FreeRTOSV8.2.3\FreeRTOS\Demo\ 中的 其他平台的东西
保留 Common 目录
这个大小就变得小了