Freertos學習:在Posix環境仿真FreeRTOS


--- title: rtos-freertos-在Posix環境仿真FreeRTOS date: 2020-06-11 16:22:34 categories: tags: - freertos - posix - linux - config ---

章節概述:

介紹如何在POSIX(Linux)環境完成FreeRTOS仿真。

下載源碼

成果地址:https://gitee.com/schips/FreeRTOS-on-Linux.git

參考文檔:《Posix/Linux Simulator for FreeRTOS》、《在Linux下實現FreeRTOS的簡單模擬器

1、進入官網上的例程,點擊FreeRTOS contributed port下載,解壓。

2、進入源碼下載地址,下載自己喜歡的版本

解壓以后,現在我們有下面的2個目錄:

FreeRTOSv10.3.1 
Posix_GCC_Simulator

3、新建2個目錄:kerneluser;分別用來放置FreeRTOS的內核、與用戶這塊的程序。

4、將FreeRTOSv10.3.1\FreeRTOS\Source下的文件拷貝到kernel

  • .h:拷貝所有
  • .c:拷貝croutine.clist.c queue.c以及tasks.c

5、將Posix_GCC_Simulator\FreeRTOS_Posix\FreeRTOS_Kernel\下的portable拷貝到kernel

6、將Posix_GCC_Simulator\FreeRTOS_Posix下的FreeRTOSConfig.h拷貝到user

7、在user目錄下創建main.c,並在其中預留一個空的main函數。

#include <stdio.h>

int main(int ac, char *av[])
{
    return 0;
}

編譯腳本

參考官方示例的makefile,在根目錄下創建Makefile文件,同樣在子目錄下也包含兩個subdir.mk用來編譯需要的對應的.o

Makefile

位於頂級目錄

RM := rm -rf

PROJ_ROOT  :=.
USERDIR    :=user
KERINELDIR :=kernel

BUILD_TMP  :=$(PROJ_ROOT)/tmp
TARGET_INC := -I$(PROJ_ROOT)/$(USERDIR) \
              -I$(PROJ_ROOT)/$(KERINELDIR)/include \
              -I$(PROJ_ROOT)/$(KERINELDIR)/portable/GCC/Posix 

-include $(PROJ_ROOT)/$(USERDIR)/user.mk
-include $(PROJ_ROOT)/$(KERINELDIR)/kernel.mk

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif

all:simulator_linux.bin

simulator_linux.bin: $(OBJS)
    @echo 'Building target: $@'
    gcc -pthread -lrt -o"simulator_linux.bin" $(OBJS) $(LIBS)
    @echo 'Finished building target: $@'
    @echo ' '

clean:
    -$(RM) $(OBJS)$(C_DEPS)$(EXECUTABLES) simulator_linux.bin
    -@echo ' '

.PHONY: all clean dependents
.SECONDARY:

kernel.mk

C_SRCS += \
$(PROJ_ROOT)/$(KERINELDIR)/croutine.c \
$(PROJ_ROOT)/$(KERINELDIR)/list.c \
$(PROJ_ROOT)/$(KERINELDIR)/queue.c \
$(PROJ_ROOT)/$(KERINELDIR)/tasks.c \
$(PROJ_ROOT)/$(KERINELDIR)/portable/GCC/Posix/port.c \
$(PROJ_ROOT)/$(KERINELDIR)/portable/MemMang/heap_3.c 

OBJS += \
$(BUILD_TMP)/croutine.o \
$(BUILD_TMP)/list.o \
$(BUILD_TMP)/queue.o \
$(BUILD_TMP)/tasks.o \
$(BUILD_TMP)/port.o \
$(BUILD_TMP)/heap_3.o 

C_DEPS += \
$(BUILD_TMP)/croutine.d \
$(BUILD_TMP)/list.d \
$(BUILD_TMP)/queue.d \
$(BUILD_TMP)/tasks.d \
$(BUILD_TMP)/port.d \
$(BUILD_TMP)/heap_3.d 

$(BUILD_TMP)/%.o: $(PROJ_ROOT)/$(KERINELDIR)/%.c
	@echo 'Building file: $<'
	gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
	@echo 'Finished building: $<'
	@echo ' '

$(BUILD_TMP)/%.o: $(PROJ_ROOT)/$(KERINELDIR)/portable/GCC/Posix/%.c
	@echo 'Building file: $<'
	gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
	@echo 'Finished building: $<'
	@echo ' '

$(BUILD_TMP)/%.o: $(PROJ_ROOT)/$(KERINELDIR)/portable/MemMang/%.c
	@echo 'Building file: $<'
	gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
	@echo 'Finished building: $<'
	@echo ' '

user.mk

C_SRCS += \
$(PROJ_ROOT)/$(USERDIR)/main.c 

OBJS += \
$(BUILD_TMP)/main.o 

C_DEPS += \
$(BUILD_TMP)/main.d 

# Each subdirectory must supply rules for building sources it contributes
$(BUILD_TMP)/%.o: $(PROJ_ROOT)/$(USERDIR)/%.c
    @echo 'Building file: $<'
    gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
    @echo 'Finished building: $<'
@echo ' '

編譯與改動

portmacro.h

由於v6.0與現在的版本差異較大,所以需要在 kernel/portable/GCC/Posix/portmacro.h進行適配。

添加:

#define portPOINTER_SIZE_TYPE unsigned long

添加:

/*--------------------------v10.3---------------------------------*/
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned long UBaseType_t;

#define portTICK_PERIOD_MS                                ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#if( configUSE_16_BIT_TICKS == 1 )
        typedef unsigned portSHORT TickType_t;
        #define portMAX_DELAY ( TickType_t ) 0xffff
#else
        typedef unsigned portLONG TickType_t;
        #define portMAX_DELAY ( TickType_t ) 0xffffffff
#endif
/*----------------------------------------------------------------*/

屏蔽掉:

/*
#if( configUSE_16_BIT_TICKS == 1 )
	typedef unsigned portSHORT portTickType;
	#define portMAX_DELAY ( portTickType ) 0xffff
#else
	typedef unsigned portLONG portTickType;
	#define portMAX_DELAY ( portTickType ) 0xffffffff
#endif
*/

屏蔽掉:

//#define portTICK_RATE_MS				( ( portTickType ) 1000 / configTICK_RATE_HZ )

main.c

新的

#include <stdio.h>
#include <stdlib.h>

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

static void vTask1( void *pvParameters );
static void vTask2( void *pvParameters );

int main()
{
    static xQueueHandle xTestQueue;
    xTestQueue = xQueueCreate( 10, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
    xTaskCreate( vTask1, "vTask1", configMINIMAL_STACK_SIZE, ( void * ) &xTestQueue, tskIDLE_PRIORITY, NULL );
    xTaskCreate( vTask2, "vTask2", configMINIMAL_STACK_SIZE, ( void * ) &xTestQueue, tskIDLE_PRIORITY, NULL );

    vTaskStartScheduler();
    return 1;
}

static void vTask1( void *pvParameters )
{
unsigned short usValue = 0, usLoop;
xQueueHandle *pxQueue;
const unsigned short usNumToProduce = 3;
short sError = pdFALSE;

    pxQueue = ( xQueueHandle * ) pvParameters;

    for( ;; )
    {       
        for( usLoop = 0; usLoop < usNumToProduce; ++usLoop )
        {
            /* Send an incrementing number on the queue without blocking. */
            printf("Task1 will send: %d\r\n", usValue);
            if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( portTickType ) 0 ) != pdPASS )
            {
                sError = pdTRUE;
            }
            else
            {
                ++usValue;
            }
        }
        vTaskDelay( 2000 );
    }
}
static void vTask2( void *pvParameters )
{
unsigned short usData = 0;
xQueueHandle *pxQueue;

    pxQueue = ( xQueueHandle * ) pvParameters;

    for( ;; )
    {       
        while( uxQueueMessagesWaiting( *pxQueue ) )
        {
            if( xQueueReceive( *pxQueue, &usData, ( portTickType ) 0 ) == pdPASS )
            {
                printf("Task2 received:%d\r\n", usData);
            }
        }
        vTaskDelay( 5000 );
    }
}

/********************************************************/
/* This is a stub function for FreeRTOS_Kernel */
void vMainQueueSendPassed( void )
{
    return;
}

/* This is a stub function for FreeRTOS_Kernel */
void vApplicationIdleHook( void )
{
    return;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM