FreeRTOS Ported to RH850

FreeRTOS Ported to RH850

Hello, everyone. I have ported FreeRTOS to RH850. It seems works fine with some basic tests.

Have Fun! :wink:

2 Likes

Thanks. Is this related to this? Porting freeRTOS on Renesas RH850 : Task completed

1 Like

Emm…yes. They are similar but different. At least the task stack layout is different. :joy:

Nice … I will check it… …!!

Happy May Day! I updated this port. Some new features have been added.

  1. support interrupt nesting
  2. use a separate ISR stack for interrupts
  3. reduce stack usage of nested interrupts
  4. IAR and CCRH are added
1 Like

Hello mikisama,

Can your program run with Renesas CS+ RH850 Simulator (or other simulator)?

Best regards,
NoMaY

Hello mikisama,

I have one more question.

Can your port be used with Renesas CS+ RH850 Code Generator easily?

Best regards,
NoMaY

I use IAR. The ELF generated by IAR and CCRH can be debugged with IAR. The ELF generated by GCC can be debugged by IAR, but it doesn’t be fully compatible with IAR.

You can build the project with CCRH and create a debug-only project with CS+.


2
3

I don’t know how to simulate the interrupt and peripheral in CS+ and IAR :joy:.

Renesas Code Generator for RH850 doesn’t support my chip. :joy:

Hi @mikisama , in the example code I see you’re setting RINT=1, meaning only one level of user interrupt priority is supported.
I’m wondering what work is required, and how much effort that work is, to support using FreeRTOS with multiple levels of user interrupt priority enabled?

Hi, @JonWingfield
Sorry for the later reply. I didn’t notice the forum email.

For RH850, there are two interrupt acknowledgments according to the settings:

  1. Direct vector method
  2. Table reference method

RINT only works for the Direct vector method.

When we use the Direct vector method and RINT=0

  • interrupts with priority 0 will jump to 0x0100 (highest priority)
  • interrupts with priority 1 will jump to 0x0110
    .
    .
    .
  • interrupts with priority 15 will jump to 0x01F0 (lowest priority)

When we use the Direct vector method and RINT=1

  • all interrupts no matter which priority it is, will jump to 0x0100

So when RINT=1, it means that there is only one interrupt entry address, not only one priority level.

You can read the software manual 4.5 Exception Handler Address for more details. RH850G3KH User’s Manual: Software (renesas.com)

Thanks for the response, really appreciate the work you did here.
I understand the interrupt mechanism, was more wondering if you’ve tried setting RINT=0 and using the vISRWrapper function you wrote as the handler for multiple interrupt vectors.
I’ve spent time reviewing your implementation and the documentation on nested interrupts and don’t see any obvious issues with this approach.

Hi, @JonWingfield.

You are right.

I just modified vector.s and main.c as shown below.
It also works fine.

diff --git a/sample/IAR/vector.s b/sample/IAR/vector.s
index 1fb89fc..9789154 100644
--- a/sample/IAR/vector.s
+++ b/sample/IAR/vector.s
@@ -77,63 +77,63 @@ __eiint0:   /* 0x0100 */

     ALIGN 4
 __eiint1:   /* 0x0110 */
-    jr __eiint1
+    jr _vISRWrapper

     ALIGN 4
 __eiint2:   /* 0x0120 */
-    jr __eiint2
+    jr _vISRWrapper

     ALIGN 4
 __eiint3:   /* 0x0130 */
-    jr __eiint3
+    jr _vISRWrapper

     ALIGN 4
 __eiint4:   /* 0x0140 */
-    jr __eiint4
+    jr _vISRWrapper

     ALIGN 4
 __eiint5:   /* 0x0150 */
-    jr __eiint5
+    jr _vISRWrapper

     ALIGN 4
 __eiint6:   /* 0x0160 */
-    jr __eiint6
+    jr _vISRWrapper

     ALIGN 4
 __eiint7:   /* 0x0170 */
-    jr __eiint7
+    jr _vISRWrapper
 
     ALIGN 4
 __eiint8:   /* 0x0180 */
-    jr __eiint8
+    jr _vISRWrapper

     ALIGN 4
 __eiint9:   /* 0x0190 */
-    jr __eiint9
+    jr _vISRWrapper

     ALIGN 4
 __eiint10:  /* 0x01a0 */
-    jr __eiint10
+    jr _vISRWrapper

     ALIGN 4
 __eiint11:  /* 0x01b0 */
-    jr __eiint11
+    jr _vISRWrapper

     ALIGN 4
 __eiint12:  /* 0x01c0 */
-    jr __eiint12
+    jr _vISRWrapper

     ALIGN 4
 __eiint13:  /* 0x01d0 */
-    jr __eiint13
+    jr _vISRWrapper

     ALIGN 4
 __eiint14:  /* 0x01e0 */
-    jr __eiint14
+    jr _vISRWrapper

     ALIGN 4
 __eiint15:  /* 0x01f0 */
-    jr __eiint15
+    jr _vISRWrapper

 /*-----------------------------------------------------------*/
     END
diff --git a/sample/main.c b/sample/main.c
index c6ba6dc..2931a1e 100644
--- a/sample/main.c
+++ b/sample/main.c
@@ -75,9 +75,9 @@ void prvSetupHardware(void)
      * all EI level interrupts will jump to 0x0100
      */
 #if defined(__GNUC__) || defined(__ICCRH850__)
-    asm("ldsr %[ebase], 3, 1" ::[ebase] "r"(0x0001));
+    asm("ldsr %[ebase], 3, 1" ::[ebase] "r"(0x0000));
 #elif defined(__CCRH__)
-    __ldsr_rh(3, 1, 0x0001);
+    __ldsr_rh(3, 1, 0x0000);
 #endif
 }

It’s just that I prefer using one interrupt entry address. :smiley:

Awesome. Thanks for the confirmation. I would prefer the simplicity of it as well but ability to nest interrupts has turned out to be a requirement for my project :slight_smile:
Thanks!

Hi mikisama,
Thank you for sharing!
Recently I was trying the RTOS on the RH850/F1L, and it seems that it is ok.
For the assembly code,
I would like to know what’s the purpose of variable __stack, because I have commented “mov hilo(__stack), sp” in file portasm.s, it seems that system is normal.
BTW, my IDE is GreenHills v7.xx
Thanks!

Hi, @Bowen_Gu

Unlike cortex-m, rh850 do not support a separate hardware interrupt stack.
To reduce task stack load by interrupts,we can use the Main Stack as ISR stack.

Otherwise, you must ensure that each task stack is large enough to hold interrupt context.

Hi @mikisama ,
Thank you for your reply and sorry to bother you. I’m trying to run freeRTOS in the table reference method mode.
At present, it seems to be running normally,I haven’t done more tests.
I would like to ask whether interrupt nesting is a factor to be considered, or if there are other factors.
Appreciate your suggestion in advance!

emm, consider what? stability? :joy:

hi @mikisama ,
I’m a beginner and don’t know much about RH850 assembly code.
In direct vector mode, I can understand that interrupt nesting should be added。
In the table reference method mode, the interrupt nesting is necessary?
Thanks

Hi, @Bowen_Gu

  • Interrupt nesting can reduce the latency of high priority interrupts while potentially increasing the latency of low priority interrupts.
  • If your application does have really emergency ISR that need to be handled firstly, enabling interrupt nesting can be helpful for this.
  • Both direct vector mode and table reference mode can enable interrupt nesting as needed.

For RH850 to use the table reference mode, each ISR requires a pair of wrapper code (context save and context restore) written in assembly. I think it is annoying and I hate assembly code, so I choose direct vector mode which only need one pair of wrapper code written in assembly.

code snippets for RH850 table reference mode

/* foo.c */
void tauj0i0_isr_handler(void)
{
}

void ostm_isr_handler(void)
{
}
_tauj0i0_isr:
    contex_save
    jarl _tauj0i0_isr_handler, lp
    contex_restore
    eiret

_ostm0_isr:
    contex_save
    jarl _ostm_isr_handler, lp
    contex_restore
    eiret

code snippets for RH850 direct mode

void tauj0i0_isr_handler(void)
{
}

void ostm_isr_handler()
{
}

void isr_handler(long eiic)
{
    switch(eiic)
    {
    case 0x1048:
        tauj0i0_isr_handler();
        break;
    case 0x104c:
        ostm_isr_handler();
        break;
    }
}
_isr_wrapper:
    contex_save
    jarl _isr_handler, lp
    contex_restore
    eiret