忘備録-備忘録

技術的な備忘録

RX210でFreeRTOSを動かす その2

2015-10-09 08:29:46 | RX210
秋月電子通商で販売しているAE-RX210ボードでリアルタイムOSのFreeRTOSを動かしてみました。 環境はe2 studio上でRXCです。
今回はOS部分をきれいに分離し新しプロジェクトに組み込み安くしました。ファイルとフォルダの構成を次に示します。
[src]
 +---- iodefine.h       <-- ウイザードで自動作成
 +---- typedefine.h      <-- ウイザードで自動作成
 +---- dbsct.c         <-- ウイザードで自動作成
 +---- main.c         <-- ウイザードで自動作成
 |
 +-----[FreeRTOS]
       +------ croutine.h        
       +------ deprecated_definitions.h 
       +------ event_groups.h      
       +------ FreeRTOS.h        
       +------ list.h          
       +------ mpu_wrappers.h      
       +------ portable.h        
       +------ projdefs.h        
       +------ queue.h          
       +------ semphr.h         
       +------ StackMacros.h      
       +------ task.h          
       +------ timers.h         
       +------ croutine.c        
       +------ event_groups.c      
       +------ list.c          
       +------ queue.c          
       +------ tasks.c          
       +------ timers.c         
       |
       +------ [portable]
             +------ FreeRTOSConfig.h
             +------ portmacro.h
             +------ stacksct.h      <-- 移動
             +------ vect.h        <-- 移動
             +------ ApplicationHook.c  <-- 新規作成
             +------ heap_2.c
             +------ hwsetup.c       <-- 変更
             +------ interrupt_handlers.c <-- 移動
             +------ port.c
             +------ reset_program.c
             +------ vector_table.c


画面上ではこのようになります。

変更・新規作成したファイルを次に示します。
ApplicationHook.c(新規作成)
/*
* タスク切り替え用のタイマのスタートと各種フック関数
*
* サンプルではmain関数と同じファイルに記述してあったがこのファイルに移動させた
*/

/* Hardware specific includes. */
#include "../../iodefine.h"

/* Kernel includes. */
#include "../FreeRTOS.h"
#include "../task.h"
#include "../queue.h"

/* This variable is not used by this simple Blinky example.  It is defined
purely to allow the project to link as it is used by the full build
configuration. */
volatile unsigned long ulHighFrequencyTickCount = 0UL;

/*-----------------------------------------------------------*/


/* A callback function named vApplicationSetupTimerInterrupt() must be defined
to configure a tick interrupt source, and configTICK_VECTOR set in
FreeRTOSConfig.h to install the tick interrupt handler in the correct position
in the vector table.  This example uses a compare match timer.  It can be
into any FreeRTOS project, provided the same compare match timer is available. */
void vApplicationSetupTimerInterrupt( void )
{
     /* Enable compare match timer 0. */
     SYSTEM.PRCR.WORD = 0x0A502;
     MSTP( CMT0 ) = 0;
     SYSTEM.PRCR.WORD = 0x0A500;

     /* Interrupt on compare match. */
     CMT0.CMCR.BIT.CMIE = 1;
     CMT0.CMCR.BIT.CKS = 0;                         // CLK = PCLK/8

     /* Set the compare match value. */
     CMT0.CMCOR = ( unsigned short ) ( ( ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ) -1 ) / 8 );

     /* Divide the PCLK by 8. */
     CMT0.CMCR.BIT.CKS = 0;

     /* Enable the interrupt... */
     _IEN( _CMT0_CMI0 ) = 1;
     ICU.IER[IER_CMT0_CMI0].BIT.IEN_CMT0_CMI0 = 1;     //Enable CMIE
     /* ...and set its priority to the application defined kernel priority. */
     _IPR( _CMT0_CMI0 ) = configKERNEL_INTERRUPT_PRIORITY;
     ICU.IPR[IPR_CMT0_CMI0].BYTE = configKERNEL_INTERRUPT_PRIORITY;          // Set interrupt priority level
     /* Start the timer. */
     CMT.CMSTR0.BIT.STR0 = 1;
}
/*-----------------------------------------------------------*/



/* If configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h, then this
function will be called if pvPortMalloc() returns NULL because it has exhausted
the available FreeRTOS heap space.  See http://www.freertos.org/a00111.html. */
void vApplicationMallocFailedHook( void )
{
     for( ;; );
}
/*-----------------------------------------------------------*/

/* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 in
FreeRTOSConfig.h, then this function will be called if a task overflows its
stack space.  See
http://www.freertos.org/Stacks-and-stack-overflow-checking.html. */
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
     for( ;; );
}
/*-----------------------------------------------------------*/

/* If configUSE_IDLE_HOOK is set to 1 in FreeRTOSConfig.h, then this function
will be called on each iteration of the idle task.  See
http://www.freertos.org/a00016.html */
void vApplicationIdleHook( void )
{
     /* If this is being executed then the kernel has been started.  Start the high
     frequency timer test as described at the top of this file.  This is only
     included in the optimised build configuration - otherwise it takes up too much
     CPU time and can disrupt other tests. */
}
/*-----------------------------------------------------------*/


reset_program.c
/***************************************************************/
/*                                                             */
/*      PROJECT NAME :  FreeRTOS02                             */
/*      FILE         :  reset_program.c                        */
/*      DESCRIPTION  :  Reset program                          */
/*      CPU SERIES   :  RX200                                  */
/*      CPU TYPE     :  RX210                                  */
/*                                                             */
/*      This file is generated by e2 studio.                   */
/*                                                             */
/***************************************************************/                               
                                                                          
                                                                          
                                                                          
                                                                         

/*********************************************************************
*
* Device     : RX/RX200
*
* File Name  : resetprg.c
*
* Abstract   : Reset Program.
*
* History    : 1.00  (2010-12-17)
*            : 1.10  (2011-02-21)
*            : 1.11  (2011-06-20)
*            : 1.20  (2014-09-18)
*            : 1.21  (2014-10-22)
*
* NOTE       : THIS IS A TYPICAL EXAMPLE.
*
* Copyright (C) 2010 (2011-2014) Renesas Electronics Corporation. and
* Renesas Solutions Corp. All rights reserved.
*
*********************************************************************/

#include     <machine.h>
#include     <_h_c_lib.h>
//#include     <stddef.h>                         // Remove the comment when you use errno
//#include      <stdlib.h>                         // Remove the comment when you use rand()
#include     "../../typedefine.h"          // Define Types
#include "stacksct.h"          // Stack Sizes (Interrupt and User)

extern void HardwareSetup( void );

#ifdef __cplusplus
extern "C" {
#endif
void PowerON_Reset_PC(void);
void main(void);
#ifdef __cplusplus
}
#endif

//#ifdef __cplusplus                    // Use SIM I/O
//extern "C" {
//#endif
//extern void _INIT_IOLIB(void);
//extern void _CLOSEALL(void);
//#ifdef __cplusplus
//}
//#endif

#define PSW_init  0x00010000     // PSW bit pattern
#define FPSW_init 0x00000000     // FPSW bit base pattern

//extern void srand(_UINT);          // Remove the comment when you use rand()
//extern _SBYTE *_s1ptr;                    // Remove the comment when you use strtok()
         
//#ifdef __cplusplus                    // Use Hardware Setup
//extern "C" {
//#endif
//extern void HardwareSetup(void);
//#ifdef __cplusplus
//}
//#endif
    
//#ifdef __cplusplus               // Remove the comment when you use global class object
//extern "C" {                         // Sections C$INIT and C$END will be generated
//#endif
//extern void _CALL_INIT(void);
//extern void _CALL_END(void);
//#ifdef __cplusplus
//}
//#endif

#pragma section ResetPRG          // output PowerON_Reset to PResetPRG section

#pragma entry PowerON_Reset_PC

void PowerON_Reset_PC(void)
{
#ifdef __RXV2
     set_extb(__sectop("EXCEPTVECT"));
#endif
     set_intb(__sectop("C$VECT"));

#ifdef __FPU
#ifdef __ROZ                         // Initialize FPSW
#define _ROUND 0x00000001               // Let FPSW RMbits=01 (round to zero)
#else
#define _ROUND 0x00000000               // Let FPSW RMbits=00 (round to nearest)
#endif
#ifdef __DOFF
#define _DENOM 0x00000100               // Let FPSW DNbit=1 (denormal as zero)
#else
#define _DENOM 0x00000000               // Let FPSW DNbit=0 (denormal as is)
#endif
     set_fpsw(FPSW_init | _ROUND | _DENOM);
#endif

     _INITSCT();

//     _INIT_IOLIB();                         // Use SIM I/O

//     errno=0;                              // Remove the comment when you use errno
//     srand((_UINT)1);                         // Remove the comment when you use rand()
//     _s1ptr=NULL;                         // Remove the comment when you use strtok()


     HardwareSetup();                    // Use Hardware Setup
    nop();

//     _CALL_INIT();                         // Remove the comment when you use global class object

     set_psw(PSW_init);                    // Set Ubit & Ibit for PSW
//     chg_pmusr();                         // Remove the comment when you need to change PSW PMbit (SuperVisor->User)

     main();

//     _CLOSEALL();                         // Use SIM I/O
    
//     _CALL_END();                         // Remove the comment when you use global class object

     brk();
}


main.c
/* Hardware specific includes. */
#include "iodefine.h"

/* Kernel includes. */
#include "FreeRTOS/FreeRTOS.h"
#include "FreeRTOS/task.h"
#include "FreeRTOS/queue.h"



void vTask1(void *pvParameters)
{
     while(1) {
          PORTC.PODR.BIT.B1 = ~PORTC.PODR.BIT.B1;
          vTaskDelay(100/portTICK_PERIOD_MS);
     }
}

void vTask2(void *pvParameters)
{
     while(1) {
          PORTC.PODR.BIT.B2 = ~PORTC.PODR.BIT.B2;
          vTaskDelay(200/portTICK_PERIOD_MS);
     }
}

void vTask3(void *pvParameters)
{
     while(1) {
          PORTC.PODR.BIT.B3 = ~PORTC.PODR.BIT.B3;
          vTaskDelay(300/portTICK_PERIOD_MS);
     }
}

void main(void)
{

     /* Turn all LEDs off. */
     PORTC.PDR.BYTE = 0xFF;     //ポートC出力
     PORTC.PODR.BYTE = 0xFF;     //初期値


     xTaskCreate(vTask1,"Task1",100,NULL,1,NULL);
     xTaskCreate(vTask2,"Task2",100,NULL,1,NULL);
     xTaskCreate(vTask3,"Task3",100,NULL,1,NULL);


     /* Create the queue. */
     vTaskStartScheduler();

     /* If all is well the next line of code will not be reached as the scheduler
     will be     running.  If the next line is reached then it is likely that there was
     insufficient heap available for the idle task to be created. */
     for( ;; );
}