Recent

Author Topic: RISCV32 Embedded -> Adding Microcontroller  (Read 557 times)

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
RISCV32 Embedded -> Adding Microcontroller
« on: May 26, 2022, 11:24:51 am »
Hello,

currently I try to use fpc on a risc-v 32bit microcontroller, namely the CH32V307 from WCH. Therefor I ported the c header file to pascal and modified the fpc source as described in the wiki:
https://wiki.freepascal.org/TARGET_Embedded#Adding_new_microcontrollers

A very basic program is working now, but there are issues, point 1 is the most important.

1. Interrupts
Functions/procedures are returned with the assembler command "JALR" and fpc also uses this command for interrupts, but there it should be the "MRET" command instead. Could that be implemented? I'm not sure if this a special case for this microcontroller. The command is mentioned in the risc-v specification in "Volume II: Privileged Architecture". It seems interrupts automatically change the mode from user to machine mode which has to do with memory protection, and MRET switches the mode back.
For testing I added the "MRET" in inline assembler at the end of the interrupt handler and it works. But then the stackframe and pushed registers have to be cleaned up manually in inline assembler as well, and that of course is not suitable in 'productive code'.

2. Inline Assembler
The inline assembler seems not to support any pseudo instructions like LA, LI, CSRW which makes a 'translation' of startup code that is written in assembler a bit difficult. Also it seems not all register name aliases are working, e.g. the alias "zero" for X0. And in the used register list in the end of an asm section aliases that were accepted in code didn't work.
asm lui t0, 0x06 end['x5']; // t0 is alias of x5

3. Stack pointer address
The stack address is defined in the linker script providing a symbol. The linker script is generated in the file compiler/systems/t_embed.pas with the following line:
 Add('_stack_top = 0x' + IntToHex(srambase+sramsize-1,4) + ';');
As far as I understand the microcontroller only allows 32bit alligned memory access, so I had to change it to
 Add('_stack_top = 0x' + IntToHex(srambase+sramsize-4,4) + ';');
Now I'm not sure what is the best way to fulfill this without breaking existing code. In t_embed.pas it could be distinguished between each controller, but that would perspectively blow up the file. The offset could also be adjusted in the controllers startup code, where the stack pointer is initialized. But then it would differ from the original startup code making future porting of other devices more difficult. Or it could be changed to -4 for all devices, perhaps it doesn't break any compatibility, but just wastes 3 byte for devices that would support byte allignment? Or is the -1 even wrong, as a a 32bit access (riscv32) to (srambase+sramsize-1) would result in an access including the 3 bytes outside of the defined SRAM region?

Thanks!
Regards~

PascalDragon

  • Hero Member
  • *****
  • Posts: 4113
  • Compiler Developer
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #1 on: May 26, 2022, 04:40:43 pm »
Please report bugs for each of these issues and maybe an additional one for officially adding the CH32V307 (if you want), that references the other three as requirements.

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #2 on: May 26, 2022, 07:22:56 pm »
OK, I will file the bug reports.

and maybe an additional one for officially adding the CH32V307 (if you want), that references the other three as requirements.

Yes, I wanted to wait until I got it working so far.
What is the proper way of providing the changes? Just the modified files, or together with the version of the unmodified ones? I don't really know the git workflow.

Laksen

  • Hero Member
  • *****
  • Posts: 697
    • J-Software
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #3 on: May 26, 2022, 09:05:15 pm »
The part about interrupts should be pretty easy to do with a modification to the compiler. We did something similar for interrupt handling on ARM by using the interrupt; procedure directive

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #4 on: May 27, 2022, 12:14:55 pm »
I created the bug reports:
https://gitlab.com/freepascal.org/fpc/source/-/issues/39737
https://gitlab.com/freepascal.org/fpc/source/-/issues/39738
https://gitlab.com/freepascal.org/fpc/source/-/issues/39739

The part about interrupts should be pretty easy to do with a modification to the compiler. We did something similar for interrupt handling on ARM by using the interrupt; procedure directive
In my understanding other riscv32 microcontrollers don't have a user mode (but do have interrupts), so also don't need/support MRET. This maybe should be considered.
« Last Edit: May 27, 2022, 12:21:55 pm by kupferstecher »

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #5 on: May 27, 2022, 12:34:15 pm »
An other thing, the device has a hardware stack for interrupts.
If enabled, the registers don't need to be pushed/popped by code. Is there any way to tell the compiler not to save registers in a certain procedure (interrupt handler)?

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #6 on: May 30, 2022, 12:37:34 pm »
One more question (5):

When I build the cross-compiler, the according makefile for riscv32-embedded is not created/updated.

-> Is this a bug or intended behaviour or am I doing something wrong?

The build output is as follows:

Code: Text  [Select][+][-]
  1.  Required packages for embedded-riscv32:
  2.  Required dirs for riscv32-embedded: compiler rtl utils packages installer
  3.    Subdir: compiler/Makefile.fpc
  4.    Subdir: rtl/Makefile.fpc
  5.    Subdir: utils/Makefile.fpc
  6.    Subdir: packages/Makefile.fpc
  7.    Subdir: installer/Makefile.fpc

but the makefile with the device file is in the directory \rtl\embedded, which is not part of the list. I had to translate it 'manually' with
Code: Text  [Select][+][-]
  1. fpcmake.exe -w -Tall

This is the command I use for building the cross compiler:
Code: Text  [Select][+][-]
  1. %MAKE_PATH%\make.exe clean crossall crossinstall FPC=%PPCBIN% OS_TARGET=embedded CPU_TARGET=riscv32 SUBARCH=rv32imac INSTALL_PREFIX=%INSTALL_PATH% CROSSBINDIR=%GNU_BIN_PATH% CROSSOPT="-O3 -XX -CX" BINUTILSPREFIX=riscv-embedded-

PascalDragon

  • Hero Member
  • *****
  • Posts: 4113
  • Compiler Developer
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #7 on: May 30, 2022, 01:15:59 pm »
When I build the cross-compiler, the according makefile for riscv32-embedded is not created/updated.

The makefiles are only updated manually when something in a Makefile.fpc or in the general template used by fpcmake changed.

kupferstecher

  • Hero Member
  • *****
  • Posts: 517
Re: RISCV32 Embedded -> Adding Microcontroller
« Reply #8 on: May 30, 2022, 01:37:56 pm »
OK, I added that in the wiki.
Thanks!

 

TinyPortal © 2005-2018