RISC-V: add float-point and C906 MTIMER support

This commit is contained in:
Paul Pan 2023-01-31 22:07:39 +08:00
parent def7d2df2b
commit c9bf3486c6
4 changed files with 239 additions and 11 deletions

View File

@ -0,0 +1,205 @@
/*
* FreeRTOS Kernel V10.4.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/*
* The FreeRTOS kernel's RISC-V port is split between the the code that is
* common across all currently supported RISC-V chips (implementations of the
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
*
* + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that
* is common to all currently supported RISC-V chips. There is only one
* portASM.S file because the same file is built for all RISC-V target chips.
*
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
* as there are multiple RISC-V chip implementations.
*
* !!!NOTE!!!
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
* compiler's!) include path. For example, if the chip in use includes a core
* local interrupter (CLINT) and does not include any chip specific register
* extensions then add the path below to the assembler's include path:
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
*
*/
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
#define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHANDLE_INTERRUPT Default_IRQHandler
#define portasmHAS_SIFIVE_CLINT 1
#define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 32 /* Must be even number on 32-bit cores. */
.macro portasmSAVE_ADDITIONAL_REGISTERS
/* save float registers */
addi sp, sp, -(portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE)
#if __riscv_flen == 64
fsd f31, 32 * portWORD_SIZE( sp )
fsd f30, 31 * portWORD_SIZE( sp )
fsd f29, 30 * portWORD_SIZE( sp )
fsd f28, 29 * portWORD_SIZE( sp )
fsd f27, 28 * portWORD_SIZE( sp )
fsd f26, 27 * portWORD_SIZE( sp )
fsd f25, 26 * portWORD_SIZE( sp )
fsd f24, 25 * portWORD_SIZE( sp )
fsd f23, 24 * portWORD_SIZE( sp )
fsd f22, 23 * portWORD_SIZE( sp )
fsd f21, 22 * portWORD_SIZE( sp )
fsd f20, 21 * portWORD_SIZE( sp )
fsd f19, 20 * portWORD_SIZE( sp )
fsd f18, 19 * portWORD_SIZE( sp )
fsd f17, 18 * portWORD_SIZE( sp )
fsd f16, 17 * portWORD_SIZE( sp )
fsd f15, 16 * portWORD_SIZE( sp )
fsd f14, 15 * portWORD_SIZE( sp )
fsd f13, 14 * portWORD_SIZE( sp )
fsd f12, 13 * portWORD_SIZE( sp )
fsd f11, 12 * portWORD_SIZE( sp )
fsd f10, 11 * portWORD_SIZE( sp )
fsd f9, 10 * portWORD_SIZE( sp )
fsd f8, 9 * portWORD_SIZE( sp )
fsd f7, 8 * portWORD_SIZE( sp )
fsd f6, 7 * portWORD_SIZE( sp )
fsd f5, 6 * portWORD_SIZE( sp )
fsd f4, 5 * portWORD_SIZE( sp )
fsd f3, 4 * portWORD_SIZE( sp )
fsd f2, 3 * portWORD_SIZE( sp )
fsd f1, 2 * portWORD_SIZE( sp )
fsd f0, 1 * portWORD_SIZE( sp )
#elif __riscv_flen == 32
fsw f31, 32 * portWORD_SIZE( sp )
fsw f30, 31 * portWORD_SIZE( sp )
fsw f29, 30 * portWORD_SIZE( sp )
fsw f28, 29 * portWORD_SIZE( sp )
fsw f27, 28 * portWORD_SIZE( sp )
fsw f26, 27 * portWORD_SIZE( sp )
fsw f25, 26 * portWORD_SIZE( sp )
fsw f24, 25 * portWORD_SIZE( sp )
fsw f23, 24 * portWORD_SIZE( sp )
fsw f22, 23 * portWORD_SIZE( sp )
fsw f21, 22 * portWORD_SIZE( sp )
fsw f20, 21 * portWORD_SIZE( sp )
fsw f19, 20 * portWORD_SIZE( sp )
fsw f18, 19 * portWORD_SIZE( sp )
fsw f17, 18 * portWORD_SIZE( sp )
fsw f16, 17 * portWORD_SIZE( sp )
fsw f15, 16 * portWORD_SIZE( sp )
fsw f14, 15 * portWORD_SIZE( sp )
fsw f13, 14 * portWORD_SIZE( sp )
fsw f12, 13 * portWORD_SIZE( sp )
fsw f11, 12 * portWORD_SIZE( sp )
fsw f10, 11 * portWORD_SIZE( sp )
fsw f9, 10 * portWORD_SIZE( sp )
fsw f8, 9 * portWORD_SIZE( sp )
fsw f7, 8 * portWORD_SIZE( sp )
fsw f6, 7 * portWORD_SIZE( sp )
fsw f5, 6 * portWORD_SIZE( sp )
fsw f4, 5 * portWORD_SIZE( sp )
fsw f3, 4 * portWORD_SIZE( sp )
fsw f2, 3 * portWORD_SIZE( sp )
fsw f1, 2 * portWORD_SIZE( sp )
fsw f0, 1 * portWORD_SIZE( sp )
#endif
.endm
.macro portasmRESTORE_ADDITIONAL_REGISTERS
/* load float registers */
#if __riscv_flen == 64
fld f31, 32 * portWORD_SIZE( sp )
fld f30, 31 * portWORD_SIZE( sp )
fld f29, 30 * portWORD_SIZE( sp )
fld f28, 29 * portWORD_SIZE( sp )
fld f27, 28 * portWORD_SIZE( sp )
fld f26, 27 * portWORD_SIZE( sp )
fld f25, 26 * portWORD_SIZE( sp )
fld f24, 25 * portWORD_SIZE( sp )
fld f23, 24 * portWORD_SIZE( sp )
fld f22, 23 * portWORD_SIZE( sp )
fld f21, 22 * portWORD_SIZE( sp )
fld f20, 21 * portWORD_SIZE( sp )
fld f19, 20 * portWORD_SIZE( sp )
fld f18, 19 * portWORD_SIZE( sp )
fld f17, 18 * portWORD_SIZE( sp )
fld f16, 17 * portWORD_SIZE( sp )
fld f15, 16 * portWORD_SIZE( sp )
fld f14, 15 * portWORD_SIZE( sp )
fld f13, 14 * portWORD_SIZE( sp )
fld f12, 13 * portWORD_SIZE( sp )
fld f11, 12 * portWORD_SIZE( sp )
fld f10, 11 * portWORD_SIZE( sp )
fld f9, 10 * portWORD_SIZE( sp )
fld f8, 9 * portWORD_SIZE( sp )
fld f7, 8 * portWORD_SIZE( sp )
fld f6, 7 * portWORD_SIZE( sp )
fld f5, 6 * portWORD_SIZE( sp )
fld f4, 5 * portWORD_SIZE( sp )
fld f3, 4 * portWORD_SIZE( sp )
fld f2, 3 * portWORD_SIZE( sp )
fld f1, 2 * portWORD_SIZE( sp )
fld f0, 1 * portWORD_SIZE( sp )
#elif __riscv_flen == 32
flw f31, 32 * portWORD_SIZE( sp )
flw f30, 31 * portWORD_SIZE( sp )
flw f29, 30 * portWORD_SIZE( sp )
flw f28, 29 * portWORD_SIZE( sp )
flw f27, 28 * portWORD_SIZE( sp )
flw f26, 27 * portWORD_SIZE( sp )
flw f25, 26 * portWORD_SIZE( sp )
flw f24, 25 * portWORD_SIZE( sp )
flw f23, 24 * portWORD_SIZE( sp )
flw f22, 23 * portWORD_SIZE( sp )
flw f21, 22 * portWORD_SIZE( sp )
flw f20, 21 * portWORD_SIZE( sp )
flw f19, 20 * portWORD_SIZE( sp )
flw f18, 19 * portWORD_SIZE( sp )
flw f17, 18 * portWORD_SIZE( sp )
flw f16, 17 * portWORD_SIZE( sp )
flw f15, 16 * portWORD_SIZE( sp )
flw f14, 15 * portWORD_SIZE( sp )
flw f13, 14 * portWORD_SIZE( sp )
flw f12, 13 * portWORD_SIZE( sp )
flw f11, 12 * portWORD_SIZE( sp )
flw f10, 11 * portWORD_SIZE( sp )
flw f9, 10 * portWORD_SIZE( sp )
flw f8, 9 * portWORD_SIZE( sp )
flw f7, 8 * portWORD_SIZE( sp )
flw f6, 7 * portWORD_SIZE( sp )
flw f5, 6 * portWORD_SIZE( sp )
flw f4, 5 * portWORD_SIZE( sp )
flw f3, 4 * portWORD_SIZE( sp )
flw f2, 3 * portWORD_SIZE( sp )
flw f1, 2 * portWORD_SIZE( sp )
flw f0, 1 * portWORD_SIZE( sp )
#endif
addi sp, sp, (portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE)
.endm
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */

View File

@ -50,6 +50,10 @@
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
#endif
#ifndef configCPU_THEAD_C906
#warning configCPU_THEAD_C906 must be defined in FreeRTOSConfig.h. If the target chip is T-Head C906 then set configCPU_THEAD_C906 to 1. Otherwise set configCPU_THEAD_C906 to 0.
#endif
/* Let the user override the pre-loading of the initial RA. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
@ -123,18 +127,20 @@ size_t xTaskReturnAddress = ( size_t ) portTASK_RETURN_ADDRESS;
/*-----------------------------------------------------------*/
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
#if( configMTIME_BASE_ADDRESS != 0 || configCPU_THEAD_C906 != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
void vPortSetupTimerInterrupt( void )
{
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte type so high 32-bit word is 4 bytes up. */
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
volatile uint32_t ulHartId;
volatile uint32_t ulHartId;
__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
#if ( configCPU_THEAD_C906 != 0 )
{
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte type so high 32-bit word is 4 bytes up. */
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
do
{
ulCurrentTimeHigh = *pulTimeHigh;
@ -144,6 +150,14 @@ size_t xTaskReturnAddress = ( size_t ) portTASK_RETURN_ADDRESS;
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
}
#else
{
// C906 Manual
__asm volatile("csrr %0, 0xc01" : "=r"(ullNextTime));
}
#endif
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
*pullMachineTimerCompareRegister = ullNextTime;
@ -151,7 +165,7 @@ size_t xTaskReturnAddress = ( size_t ) portTASK_RETURN_ADDRESS;
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
#endif /* ( configMTIME_BASE_ADDRESS != 0 || configCPU_THEAD_C906 != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
@ -178,14 +192,14 @@ extern void xPortStartFirstTask( void );
* configure whichever clock is to be used to generate the tick interrupt. */
vPortSetupTimerInterrupt();
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
#if( ( configMTIME_BASE_ADDRESS != 0 || configCPU_THEAD_C906 != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
{
/* Enable mtime and external interrupts. 1<<7 for timer interrupt,
* 1<<11 for external interrupt. _RB_ What happens here when mtime is
* not present as with pulpino? */
__asm volatile( "csrs mie, %0" :: "r"(0x880) );
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
#endif /* ( configMTIME_BASE_ADDRESS != 0 || configCPU_THEAD_C906 != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
xPortStartFirstTask();

View File

@ -180,8 +180,8 @@ extern size_t xCriticalNesting;
* from the CLINT address. */
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS ) || !defined( configCPU_THEAD_C906 )
#error configMTIME_BASE_ADDRESS, configMTIMECMP_BASE_ADDRESS and configCPU_THEAD_C906 must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
#endif
#ifdef __cplusplus

View File

@ -21,3 +21,12 @@
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
*
*/
My Addition Notes:
+ chip_specific_extensions/Thead_common
- modified from portable/ThirdParty/Community-Supported-Ports/GCC/RISC-V/chip_specific_extensions/THEAD_RV32
-
+ port.c
- modify configMTIME_BASE_ADDRESS related logic
+ C906 has MTIMER but count is in CSR