Commit b050ba12 authored by Andreas Werner's avatar Andreas Werner
Browse files

RISC-V: SMode: add SBI Debug Putc support, add new syscalls putc(3) getchar(4)

parent 54bce5c2
......@@ -106,3 +106,8 @@ config ARCH_SBI
bool "SBI Timer"
default y
depends on ARCH_SBI
config ARCH_SBI_UART
bool "SBI UART"
default y
depends on ARCH_SBI
depends on UART
/* SPDX-License-Identifier: MIT */
/*
* Author: Andreas Werner <kernel@andy89.org>
* Date: 2021
*/
#ifndef SBI_UART_H_
#define SBI_UART_H_
HAL_DEFINE_GLOBAL_ARRAY(uart);
#define SBI_UART_ID HAL_GET_ID(uart, sbi, sbi_data0)
#endif
obj-y += sbicalls.o
obj-$(CONFIG_ARCH_SBI_TIMER) += sbi_timer.o
obj-$(CONFIG_ARCH_SBI_UART) += sbi_uart.o
/* SPDX-License-Identifier: MIT */
/*
* Author: Andreas Werner <kernel@andy89.org>
* Date: 2021
*/
#include <FreeRTOS.h>
#include <uart.h>
#define UART_PRV
#include <uart_prv.h>
#include <sbi.h>
struct uart {
struct uart_generic gen;
};
UART_INIT(sbi, port, baudrate) {
int32_t ret;
struct uart *uart = (struct uart *) UART_GET_DEV(port);
if (uart == NULL) {
return NULL;
}
ret = uart_generic_init(uart);
if (ret < 0) {
return NULL;
}
/*
* Already Init
*/
if (ret > 0) {
return uart;
}
if (baudrate == 0) {
return NULL;
}
return uart;
sbi_uart_init_error0:
return NULL;
}
UART_DEINIT(sbi, uart) {
uart->gen.init = false;
return 0;
}
UART_GETC(sbi, uart, waittime) {
char c;
int lret;
uart_lock(uart, waittime, 255);
if (ulInIsr) {
c = sbi_console_getchar();
} else {
register uintptr_t a0 asm ("a0") = 0;
__asm volatile( "li a7, 4; ecall" : "+r" (a0) : : "a7");
c = a0;
}
uart_unlock(uart, 255);
return c;
}
UART_PUTC(sbi, uart, c, waittime) {
int lret;
uart_lock(uart, waittime, -1);
if (ulInIsr) {
sbi_console_putchar(c);
} else {
register uintptr_t a0 asm ("a0") = (uintptr_t)(c);
__asm volatile( "li a7, 3; ecall" : : "r" (a0) : "a7");
}
uart_unlock(uart, -1);
return 0;
}
UART_GETC_ISR(sbi, uart) {
char c;
if (ulInIsr) {
c = sbi_console_getchar();
} else {
register uintptr_t a0 asm ("a0") = (uintptr_t)(c);
__asm volatile( "li a7, 4; ecall" : "+r" (a0) : : "a7");
c = a0;
}
return c;
}
UART_PUTC_ISR(sbi, uart, c) {
if (ulInIsr) {
sbi_console_putchar(c);
} else {
register uintptr_t a0 asm ("a0") = (uintptr_t)(c);
__asm volatile( "li a7, 3; ecall" : : "r" (a0) : "a7");
}
return 0;
}
#ifndef CONFIG_UART_GENERIC_STRING
UART_PUTS(sbi, uart, s, waittime) {
int32_t ret;
uart_lock(uart, waittime, -1);
while(*s != '\0') {
if (*s == '\n') {
ret = uart_putc(uart, '\r', waittime);
if (ret < 0) {
goto nxp_uart_puts_error0;
}
}
ret = uart_putc(uart, *s, waittime);
if (ret < 0) {
goto nxp_uart_puts_error0;
}
s++;
}
uart_unlock(uart, -1);
return 0;
nxp_uart_puts_error0:
uart_unlock(uart, -1);
return ret;
}
UART_PUTS_ISR(sbi, uart, s) {
int32_t ret;
while(*s != '\0') {
if (*s == '\n') {
ret = uart_putcISR(uart, '\r');
if (ret < 0) {
goto nxp_uart_putsISR_error0;
}
}
ret = uart_putcISR(uart, *s);
if (ret < 0) {
goto nxp_uart_putsISR_error0;
}
s++;
}
return 0;
nxp_uart_putsISR_error0:
return -1;
}
#endif
#ifndef CONFIG_UART_GENERIC_BYTE
UART_READ(sbi, uart, data, length, waittime) {
int i;
uart_lock(uart, waittime, -1);
for (i = 0; i < length; i++) {
data[i] = uart_getc(uart, waittime);
if (data[i] == 255) {
goto nxp_uart_read_error0;
}
}
uart_unlock(uart, -1);
return 0;
nxp_uart_read_error0:
uart_unlock(uart, -1);
return -1;
}
UART_WRITE(sbi, uart, data, length, waittime) {
int i;
int32_t ret;
uart_lock(uart, waittime, -1);
for (i = 0; i < length; i++) {
ret = uart_putc(uart, data[i], waittime);
if (ret < 0) {
goto nxp_uart_read_error0;
}
}
uart_unlock(uart, -1);
return 0;
nxp_uart_read_error0:
uart_unlock(uart, -1);
return -1;
}
UART_READ_ISR(sbi, uart, data, length) {
int i;
for (i = 0; i < length; i++) {
data[i] = uart_getcISR(uart);
if (data[i] == 255) {
goto nxp_uart_read_error0;
}
}
return 0;
nxp_uart_read_error0:
return -1;
}
UART_WRITE_ISR(sbi, uart, data, length) {
int i;
int32_t ret;
for (i = 0; i < length; i++) {
ret = uart_putcISR(uart, data[i]);
if (ret < 0) {
goto nxp_uart_read_error0;
}
}
return 0;
nxp_uart_read_error0:
return -1;
}
#endif
UART_OPS(sbi);
struct uart sbi_data0 = {
UART_INIT_DEV(sbi)
HAL_NAME("SBI Debug UART")
};
UART_ADDDEV(sbi, sbi_data0);
......@@ -81,6 +81,7 @@ uint64_t ullNextTime = 0ULL;
const uint64_t *pullNextTime = &ullNextTime;
size_t uxTimerIncrementsForOneTick; /* Assumes increment won't go over 32-bits. */
uint32_t ulHartId;
uint32_t ulInIsr = 1;
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
stack checking. A problem in the ISR stack will trigger an assert, not call the
......
......@@ -69,6 +69,7 @@ at the top of this file. */
.extern uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
.extern xISRStackTop
.extern portasmHANDLE_INTERRUPT
.extern ulInIsr
.align 8
.func
......@@ -108,9 +109,15 @@ freertos_risc_v_trap_handler:
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
/* set ulInIsr */
la t0, ulInIsr
li t1, 1
sw t1, 0(t0)
load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */
store_x sp, 0( t0 ) /* Write sp to first TCB member. */
mv s0, a0 /* save user a0 */
csrr a0, scause
csrr a1, sepc
/* a7 sys call */
......@@ -136,6 +143,10 @@ test_if_environment_call:
beq a7, t0, handle_enableInterrupt
li t0, 2
beq a7, t0, handle_disableInterrupt
li t0, 3
beq a7, t0, handle_putchar
li t0, 4
beq a7, t0, handle_getchar
j as_yet_unhandled
handle_enableInterrupt:
......@@ -161,6 +172,19 @@ handle_yield:
jal vTaskSwitchContext
j processed_source
handle_putchar:
mv a0, s0
li a6, 0 /* FID putchar */
li a7, 1 /* EXT putchar */
ecall
j processed_source
handle_getchar:
li a6, 0 /* FID getchar */
li a7, 2 /* EXT getchar */
ecall
j processed_source
is_exception:
csrr t0, scause /* For viewing in the debugger only. */
csrr t1, sepc /* For viewing in the debugger only */
......@@ -172,6 +196,10 @@ as_yet_unhandled:
j as_yet_unhandled
processed_source:
/* clear ulInIsr */
la t0, ulInIsr
sw zero, 0(t0)
load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */
load_x sp, 0( t1 ) /* Read sp from first TCB member. */
......@@ -232,6 +260,10 @@ xPortStartFirstTask:
csrw mtvec, t0
#endif /* portasmHAS_CLILNT */
/* clear ulInIsr */
la t0, ulInIsr
sw zero, 0(t0)
load_x sp, pxCurrentTCB /* Load pxCurrentTCB. */
load_x sp, 0( sp ) /* Read sp from first TCB member. */
......
......@@ -93,7 +93,7 @@ not need to be guarded with a critical section. */
/* Scheduler utilities. */
extern void vTaskSwitchContext( void );
#define portYIELD() __asm volatile( "mv a7, x0; ecall" );
#define portYIELD() __asm volatile( "mv a7, x0; ecall" : : : "a7");
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
......@@ -106,8 +106,8 @@ extern void vTaskExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __asm volatile( "li a7, 0x2; ecall" )
#define portENABLE_INTERRUPTS() __asm volatile( "li a7, 0x1; ecall" )
#define portDISABLE_INTERRUPTS() __asm volatile( "li a7, 0x2; ecall" : : : "a7")
#define portENABLE_INTERRUPTS() __asm volatile( "li a7, 0x1; ecall" : : : "a7")
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
......@@ -180,6 +180,7 @@ definition is found. */
extern uint32_t ulHartId;
extern uint32_t ulInIsr;
#ifdef __cplusplus
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment