Skip to content

Commit 48534e1

Browse files
TrongNguyenRDucLeRVUNGtranR
authored
Supported new feature Interrupt Stack Management for U2x Port. (#28)
* Add new port layer for CCRH U2x and GHS U2x * Updated U2x port to support U2Cx devices. * Due to internal constraint, we need to postpone the upstream. We will resume once it will be ready. * Update RH850 U2x resource references. * Due to internal constraint, we need to postpone the upstream. We will resume once it will be ready. * Update RH850 U2x resource references. * Updated U2x port to support U2Cx devices. * Due to internal constraint, we need to postpone the upstream. We will resume once it will be ready. * Update RH850 U2x resource references * Update RH850 U2x resource references * updated U2x FreeRTOS port to support Stack Interrupt Management. * updated U2x FreeRTOS port to support Stack Interrupt Management. * 1. Supported new feature Interrupt Stack Management. 2. Improved the usage of FXU/FPU. 3. Improved the content in README.md. --------- Co-authored-by: Duc Dat Le <duc.le.xm@renesas.com> Co-authored-by: vung.tran.zg <vung.tran.zg@renesas.com>
1 parent bc32d25 commit 48534e1

File tree

10 files changed

+591
-438
lines changed

10 files changed

+591
-438
lines changed
120 KB
Loading

CCRH/Image/Assembler.png

37.8 KB
Loading

CCRH/U2x/README.md

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,120 @@ This repository contains the port of FreeRTOS for Renesas RH850/U2x microcontrol
1818

1919
## Link to Test Project
2020

21-
The test project can be found in [RH850_U2Ax_CCRH](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main/RH850_U2Ax_CCRH) and [RH850_U2Bx_CCRH](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main/RH850_U2Bx_CCRH). These projects contain example tasks and configurations to help you get started with FreeRTOS on the RH850/U2Ax and U2Bx.
21+
The test project can be found in [RH850_U2Ax_CCRH](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main/RH850_U2Ax_CCRH) and [RH850_U2Bx_CCRH](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main/RH850_U2Bx_CCRH). These projects contain example tasks and configurations to help you get started with FreeRTOS on the RH850/U2Ax and RH850/U2Bx.
22+
23+
## Setup for Vector Table
24+
1. Allocate the Stack area in Linker Script:<br />
25+
- In the Linker configuration, create a dedicated Stack (memory region) for the Vector Table of each Processing Element (PE).
26+
27+
For example, in **Section Settings**, add:<br />
28+
| Address | Section |
29+
|------------|---------------------|
30+
| 0x00040000 | .inttable_PE0.const |
31+
| 0x00041000 | .inttable_PE1.const |
32+
| 0x00042000 | .inttable_PE2.const |
33+
34+
![Allocate a Stack for Vector Table](../Image/Allocate_Stack_For_Vector_Table.png)
35+
36+
2. Declare the Vector Table in the source code:<br />
37+
- In the application source code, define the Vector Table.<br />
38+
- Map this Vector Table to the Stack region that was created in the Linker Script.
39+
40+
For example, in **main.c** file, add:<br />
41+
<pre>
42+
/***********************************************************************************************************************
43+
* Vector Table Configuration
44+
**********************************************************************************************************************/
45+
/* Interrupt vector table for PE0. Mapping into the memory section ".inttable_PE0". */
46+
#pragma section const ".inttable_PE0"
47+
const int_vector_t g_vector_table_PE0[ RTOS_VECTOR_TABLE_MAX_ENTRIES ] =
48+
{
49+
#if ( configNUMBER_OF_CORES > 1 )
50+
[ 1 ] = vPortIPIHander, /* Internal processor interrupt 1 */
51+
#endif /* End of #if (configNUMBER_OF_CORES > 1) */
52+
53+
[ 360 ] = vPortTickISR, /* INTOSTM0TINT (OSTM0 interrupt) */
54+
[ 621 ] = r_Config_UART0_interrupt_send, /* EIC621: INTRLIN30UR0 (RLIN30 transmit interrupt) */
55+
};
56+
57+
#if ( configNUMBER_OF_CORES > 1 )
58+
/* Interrupt vector table for PE1. Mapping into the memory section ".inttable_PE1". */
59+
#pragma section const ".inttable_PE1"
60+
const int_vector_t g_vector_table_PE1[ RTOS_VECTOR_TABLE_MAX_ENTRIES ] =
61+
{
62+
[ 1 ] = vPortIPIHander, /* Internal processor interrupt 1 */
63+
};
64+
65+
/* Interrupt vector table for PE2. Mapping into the memory section ".inttable_PE2". */
66+
#pragma section const ".inttable_PE2"
67+
const int_vector_t g_vector_table_PE2[ RTOS_VECTOR_TABLE_MAX_ENTRIES ] =
68+
{
69+
[ 1 ] = vPortIPIHander, /* Internal processor interrupt 1 */
70+
};
71+
#endif /* End of #if (configNUMBER_OF_CORES > 1) */
72+
73+
#pragma section default
74+
</pre>
75+
76+
3. Assign the Vector Table into the INTBP register in Startup:<br />
77+
- In System Startup, assign the Vector Table address into the INTBP register so that the Processor knows where to fetch Interrupt Vectors.
78+
79+
For example, in **Startup** file, add:<br />
80+
<pre>
81+
$ifdef PE1_USED
82+
__PE1:
83+
; Initialization of the interrupt base pointer.
84+
.extern _g_vector_table_PE1
85+
mov #_g_vector_table_PE1, r10
86+
ldsr r10, 4, 1 ; INTBP
87+
88+
mov #_PE1_stacktop, sp ; Set sp register.
89+
mov #__sex_entry_PE1, r10 ; First set EBASE register address.
90+
jr32 __DONE
91+
$endif
92+
93+
$ifdef PE2_USED
94+
__PE2:
95+
; Initialization of the interrupt base pointer.
96+
.extern _g_vector_table_PE2
97+
mov #_g_vector_table_PE2, r10
98+
ldsr r10, 4, 1 ; INTBP
99+
100+
mov #_PE2_stacktop, sp ; Set sp register.
101+
mov #__sex_entry_PE2, r10 ; First set EBASE register address.
102+
jr32 __DONE
103+
$endif
104+
</pre>
105+
106+
4. Interrupt Vector Configuration:<br />
107+
- Interrupt handling must be configured using the Direct Vector method, e.g. by configuring EBASE or EICn registers.
108+
109+
## FPU and FXU Units Usage
110+
- The `FXU Unit` is available only on RH850 U2Bx devices.<br />
111+
To ensure correct operation, any task requiring FXU must run on an FXU-enabled core. In SMP systems, the core assignment shall be fixed using CPU affinity via the `vTaskCoreAffinitySet()` function.
112+
113+
- By default, the FPU and FXU operations are enabled, which may introduce redundant code and impact performance.<br />
114+
If they are not required by the application, FPU and FXU related code can be disabled by defining the macros `configDISABLE_FPU` and `configDISABLE_FXU` respectively.<br />
115+
Additionally, `-DconfigDISABLE_FPU` and `-DconfigDISABLE_FXU` should be added to the compiler option.
116+
117+
For example, in **Property** of CC-RH (Build Tool):<br />
118+
![Assembler Section](../Image/Assembler.png)
22119

23120
## Note
24-
1. The minimal stack size (configMINIMAL_STACK_SIZE) must be included the reserved memory for nested interrupt. This formula can be referred: `(task_context_size) * (2 + configMAX_INT_NESTING) + Stack_depth_of_taskcode`
25-
In which, `task_context_size` is calculated as `36*4bytes = 144bytes` (when FPU enabled) or `34*4bytes = 136` (when FPU disabled), configMAX_INT_NESTING is `02` as default (Note that a value of `0` is not allowed).
121+
1. Refer this formula to estimate the minimal stack size (configMINIMAL_STACK_SIZE) used: `[(task_context_size) * 2] + stack_required_for_taskcode`.<br />
122+
In which, `task_context_size` is calculated as `36 * 4 bytes = 144 bytes`.
123+
26124
2. Users need to create a memory section named `mev_address` in `CRAM` for Exclusive Control functionality. Users should initialize the `mev_address` section in the startup file.
27125

28-
Example:
29-
```
30-
; .mev_address section in CRAM is used for Sync flags
31-
mov #__s.mev_address.bss, r20
32-
st.w r0, 0[r20]
33-
```
34-
3. The `FXU unit` is only available on `core 0`. Users must ensure that FXU operations are restricted to `core 0` by using the `vTaskCoreAffinitySet` function provided by FreeRTOS SMP.
35-
4. FXU can be enabled by specific compiler option `-DconfigENABLE_FXU`. FPU can be enabled by specific compiler option `-DconfigENABLE_FPU`
36-
5. The macros `configENABLE_FXU` and `configENABLE_FPU` must be defined in `FreeRTOSConfig.h`.
37-
6. This port supports U2Ax and U2Bx devices. The user must configure `configDEVICE_NAME` with the value `U2Bx_DEVICES` or `U2Ax_DEVICES` to specify which device is being used.
38-
7. The User can configure the interrupt priority of the OSTM Timer using `configTIMER_INT_PRIORITY`, with 16 levels available (0 being the highest priority and 15 the lowest).
39-
8. This port also supports the configuration of contiguous CPU cores in FreeRTOS, allowing the user to set task affinity for execution on specific cores or subsets of cores.
126+
For example:<br />
127+
<pre>
128+
; .mev_address section in CRAM is used for Sync flags
129+
mov #__s.mev_address.bss, r20
130+
st.w r0, 0[r20]</pre>
131+
132+
3. This port supports both U2Ax and U2Bx devices. The User must configure `configDEVICE_NAME` with the value `U2Bx_DEVICES` or `U2Ax_DEVICES` to specify which device is being used.
40133

134+
4. This port also supports the configuration of contiguous CPU cores in FreeRTOS SMP, allowing the User to set task affinity for execution on specific cores or subsets of cores.
41135

42136
## Other Relevant Information
43137

@@ -52,4 +146,4 @@ Example:
52146
- If you encounter any issues or have questions about this port, please open an issue in this repository or contact the maintainer.
53147

54148
- **Contributing:**
55-
- Contributions to improve this port are welcome. Please fork the repository, make your changes, and submit a pull request.
149+
- Contributions to improve this port are welcome. Please fork the repository, make your changes, and submit a pull request.

CCRH/U2x/port.c

Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#define portFXSR_REGISTER_SEL ( 10 )
4747

4848
/* PSW.EBV and PSW.CUx bits are kept as current status */
49-
#define portINITIAL_PSW_MASK ( 0x00078000 )
49+
#define portINITIAL_PSW_MASK ( 0x00038000 )
5050
#define portCURRENT_PSW_VALUE ( portSTSR( portPSW_REGISTER_ID, portREGISTER_SEL_0 ) )
5151
#define portCURRENT_SR_ZERO_VALUE ( ( StackType_t ) 0x00000000 )
5252
#define portCURRENT_FPSR_VALUE ( portSTSR( portFPSR_REGISTER_ID, portREGISTER_SEL_0 ) )
@@ -141,8 +141,8 @@
141141

142142
/* Macros indicatings status of scheduler request */
143143
#define PORT_SCHEDULER_NOREQUEST 0UL
144-
#define PORT_SCHEDULER_TASKSWITCH 1UL /* Do not modify */
145-
#define PORT_SCHEDULER_STARTFIRSTTASK 2UL /* Do not modify */
144+
#define PORT_SCHEDULER_TASKSWITCH 1UL /* Do not modify */
145+
#define PORT_SCHEDULER_STARTFIRSTTASK 2UL /* Do not modify */
146146

147147
#ifndef configSETUP_TICK_INTERRUPT
148148

@@ -151,19 +151,6 @@
151151
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
152152
#endif /* configSETUP_TICK_INTERRUPT */
153153

154-
#if ( !defined( configMAX_INT_NESTING ) || ( configMAX_INT_NESTING == 0 ) )
155-
156-
/* Set the default value for depth of nested interrupt. In theory, the
157-
* microcontroller have mechanism to limit number of nested level of interrupt
158-
* by priority (maximum 16 levels). However, the large stack memory should be
159-
* prepared for each task to save resource in interrupt handler. Therefore, it
160-
* is necessary to limit depth of nesting interrupt to optimize memory usage.
161-
* In addition, the execution time of interrupt handler should be very short
162-
* (typically not exceed 20us), this constraint does not impact to system.
163-
*/
164-
#define configMAX_INT_NESTING 2UL
165-
#endif
166-
167154
/*
168155
* Used to catch tasks that attempt to return from their implementing function.
169156
*/
@@ -191,7 +178,11 @@ volatile BaseType_t xPortScheduleStatus[ configNUMBER_OF_CORES ] = { 0 };
191178
* It is necessary to control maximum stack depth.
192179
*/
193180
volatile UBaseType_t uxInterruptNesting[ configNUMBER_OF_CORES ] = { 0 };
194-
volatile const UBaseType_t uxPortMaxInterruptDepth = configMAX_INT_NESTING;
181+
182+
#ifndef configPORT_ISR_STACK_TOPS
183+
#error "Define configPORT_ISR_STACK_TOPS in FreeRTOSConfig.h"
184+
#endif
185+
const UBaseType_t uxInterruptStack[ configNUMBER_OF_CORES ] = configPORT_ISR_STACK_TOPS;
195186

196187
/* Count number of nested locks by same cores. The lock is completely released
197188
* only if this count is decreased to 0, the lock is separated for task and isr */
@@ -224,8 +215,10 @@ void vPortTickISR( void );
224215
* cores. The core will wait until lock will be available, whilst the core which
225216
* already had lock can acquire lock without waiting. This function could be
226217
* call from task and interrupt context, the critical section is called as in ISR */
227-
void vPortRecursiveLockAcquire( BaseType_t xCoreID, BaseType_t xFromIsr );
228-
void vPortRecursiveLockRelease( BaseType_t xCoreID, BaseType_t xFromIsr );
218+
void vPortRecursiveLockAcquire( BaseType_t xCoreID,
219+
BaseType_t xFromIsr );
220+
void vPortRecursiveLockRelease( BaseType_t xCoreID,
221+
BaseType_t xFromIsr );
229222

230223
#endif /* (configNUMBER_OF_CORES > 1) */
231224

@@ -269,7 +262,7 @@ void vPortClearInterruptMask( portLONG uxSavedInterruptStatus )
269262
BaseType_t xPortGET_CORE_ID( void )
270263
{
271264
#if ( configNUMBER_OF_CORES > 1 )
272-
return( portSTSR( 0, 2 ) ); /* Get PEID value */
265+
return portSTSR( 0, 2 ); /* Get PEID value */
273266
#else
274267

275268
/* In single core, xPortGET_CORE_ID is used in this port only. The dummy
@@ -381,46 +374,32 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
381374
pxTopOfStack--;
382375
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R30; /* R30 (EP) */
383376
pxTopOfStack--;
384-
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R1; /* R1 */
377+
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R1; /* R1 */
385378
pxTopOfStack--;
386-
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R2; /* R2 */
379+
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R2; /* R2 */
387380

388381
pxTopOfStack--;
389382

383+
/* if FPU is enabled, initialize the FPU registers in Stack */
384+
#ifndef configDISABLE_FPU
385+
{
386+
*pxTopOfStack = ( StackType_t ) ( portCURRENT_FPSR_VALUE & portINITIAL_FPSR_MASK ); /* FPSR */
387+
pxTopOfStack--;
388+
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* FPEPC */
389+
pxTopOfStack--;
390+
}
391+
#endif /* End of #ifndef configDISABLE_FPU */
392+
390393
/* Keep System pre-configuration (HV, CUx, EBV) as current setting in PSW register */
391394
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* EIPSW */
392395
pxTopOfStack--;
393-
*pxTopOfStack = ( StackType_t ) pxCode; /* EIPC */
396+
*pxTopOfStack = ( StackType_t ) pxCode; /* EIPC */
394397
pxTopOfStack--;
395-
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* EIIC */
398+
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* EIIC */
396399
pxTopOfStack--;
397400
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* CTPSW */
398401
pxTopOfStack--;
399-
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* CTPC */
400-
401-
/* if FPU is enabled, initialize the FPU registers in Stack */
402-
#if ( configENABLE_FPU == 1 )
403-
pxTopOfStack--;
404-
*pxTopOfStack = ( StackType_t ) ( portCURRENT_FPSR_VALUE & portINITIAL_FPSR_MASK ); /* FPSR */
405-
pxTopOfStack--;
406-
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* FPEPC */
407-
#endif /* (configENABLE_FPU == 1) */
408-
409-
/* if FXU is enabled, initialize the FXU registers in Stack */
410-
#if ( configENABLE_FXU == 1 )
411-
/* FXU Unit is available in PE0 only */
412-
if( 0 == xPortGET_CORE_ID() )
413-
{
414-
pxTopOfStack--;
415-
*pxTopOfStack = ( StackType_t ) ( portCURRENT_FXSR_VALUE & portINITIAL_FXSR_MASK ); /* FXSR */
416-
pxTopOfStack--;
417-
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* FXXP */
418-
}
419-
else
420-
{
421-
/* Do nothing */
422-
}
423-
#endif /* (configENABLE_FXU == 1) */
402+
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* CTPC */
424403

425404
return pxTopOfStack;
426405
}
@@ -494,9 +473,7 @@ static void prvTaskExitError( void )
494473
* should instead call vTaskDelete( NULL ).
495474
*
496475
* Artificially force an assert() to be triggered if configASSERT() is
497-
* defined, then stop here so application writers can catch the error. */
498-
499-
/* This statement will always fail, triggering the assert */
476+
* defined, then stop here so application writers can catch the error. *//* This statement will always fail, triggering the assert */
500477
configASSERT( pdFALSE );
501478

502479
/*
@@ -621,11 +598,12 @@ static void prvSetupTimerInterrupt( void )
621598

622599
/* Interrupt configuration for OSTM Timer*/
623600
pulOSTMIntReg = ( volatile uint32_t * ) portOSTM_EIC_ADDR;
624-
*pulOSTMIntReg = ( portINT_TABLE_VECTOR | configTIMER_INT_PRIORITY );
601+
*pulOSTMIntReg = ( portINT_DIRECT_VECTOR | configTIMER_INT_PRIORITY );
625602

626603
/* Set OSTM0 control setting */
627-
*( ( volatile uint32_t * ) portOSTMCTL_ADDR ) = ( portOSTM_INTERRUPT_ENABLE | portOSTM_MODE_INTERVAL_TIMER | portOSTM_START_INTERRUPT_DISABLE );
628-
*( ( volatile uint32_t * ) portOSTMCMP_ADDR ) = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) ) - 1;
604+
*( ( volatile uint32_t * ) portOSTMCTL_ADDR ) =
605+
( portOSTM_INTERRUPT_ENABLE | portOSTM_MODE_INTERVAL_TIMER | portOSTM_START_INTERRUPT_DISABLE );
606+
*( ( volatile uint32_t * ) portOSTMCMP_ADDR ) = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1 );
629607

630608
/* Enable OSTM0 operation */
631609
*( ( volatile uint32_t * ) portOSTMTS_ADDR ) = portOSTM_COUNTER_START;
@@ -647,11 +625,13 @@ static void prvSetupTimerInterrupt( void )
647625
* before and after function call. */
648626
push r20
649627
mov # __s.mev_address.bss, r20
628+
650629
/* r6 is xBitPosition */
651630
Lock: set1 r6, [ r20 ]
652631
bz Lock_success
653632
snooze
654633
br Lock
634+
655635
Lock_success:
656636
pop r20
657637
}
@@ -663,13 +643,15 @@ Lock: set1 r6, [ r20 ]
663643
{
664644
push r20
665645
mov # __s.mev_address.bss, r20
646+
666647
/* r6 is xBitPosition */
667648
clr1 r6, [ r20 ]
668649
pop r20
669650
}
670651

671652
/*-----------------------------------------------------------*/
672-
void vPortRecursiveLockAcquire( BaseType_t xCoreID, BaseType_t xFromIsr )
653+
void vPortRecursiveLockAcquire( BaseType_t xCoreID,
654+
BaseType_t xFromIsr )
673655
{
674656
BaseType_t xSavedInterruptStatus;
675657
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );
@@ -685,7 +667,8 @@ Lock: set1 r6, [ r20 ]
685667
portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
686668
}
687669

688-
void vPortRecursiveLockRelease( BaseType_t xCoreID, BaseType_t xFromIsr )
670+
void vPortRecursiveLockRelease( BaseType_t xCoreID,
671+
BaseType_t xFromIsr )
689672
{
690673
BaseType_t xSavedInterruptStatus;
691674
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );

0 commit comments

Comments
 (0)