initial commit
This commit is contained in:
6
port/moonlight/README.md
Normal file
6
port/moonlight/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## Generation of register files
|
||||
|
||||
```
|
||||
pip install --extra-index-url https://git.minres.com/api/packages/Tools/pypi/simple peakrdl-mnrs
|
||||
mnrs_gen --firmware -o port/moonlight EthMac.rdl
|
||||
```
|
||||
39
port/moonlight/aclint.h
Normal file
39
port/moonlight/aclint.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _DEVICES_ACLINT_H
|
||||
#define _DEVICES_ACLINT_H
|
||||
|
||||
#include "gen/aclint.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static void set_aclint_mtime(volatile aclint_t* reg, uint64_t value) {
|
||||
set_aclint_mtime_hi(reg, (uint32_t)(value >> 32));
|
||||
set_aclint_mtime_lo(reg, (uint32_t)value);
|
||||
}
|
||||
|
||||
static uint64_t get_aclint_mtime(volatile aclint_t* reg) {
|
||||
#if(__riscv_xlen == 64)
|
||||
// this assume little endianness
|
||||
volatile uint64_t* mtime = (volatile uint64_t*)(uint64_t)(®->MTIME_LO);
|
||||
return *mtime;
|
||||
#else
|
||||
uint32_t mtimeh_val;
|
||||
uint32_t mtimel_val;
|
||||
do {
|
||||
mtimeh_val = get_aclint_mtime_hi(reg);
|
||||
mtimel_val = get_aclint_mtime_lo(reg);
|
||||
} while(mtimeh_val != get_aclint_mtime_hi(reg));
|
||||
return (uint64_t)((((uint64_t)mtimeh_val) << 32) | mtimel_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_aclint_mtimecmp(volatile aclint_t* reg, uint64_t value) {
|
||||
set_aclint_mtimecmp0lo(reg, (uint32_t)0xFFFFFFFF);
|
||||
set_aclint_mtimecmp0hi(reg, (uint32_t)(value >> 32));
|
||||
set_aclint_mtimecmp0lo(reg, (uint32_t)value);
|
||||
}
|
||||
|
||||
static uint64_t get_aclint_mtimecmp(volatile aclint_t* reg) {
|
||||
uint64_t value = ((uint64_t)get_aclint_mtimecmp0hi(reg) << 32) | (uint64_t)get_aclint_mtimecmp0lo(reg);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /* _DEVICES_ACLINT_H */
|
||||
39
port/moonlight/board.c
Normal file
39
port/moonlight/board.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "hwtimer.h"
|
||||
#include "csr.h"
|
||||
#include "platform.h"
|
||||
#include "uart.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// needed by picolibc/port.c
|
||||
int uart_putc(int ch) {
|
||||
int intr_enable = riscv_mintr_get();
|
||||
riscv_mintr_off();
|
||||
uart_write(uart, ch);
|
||||
riscv_mintr_restore(intr_enable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uart_getc(void) {
|
||||
int intr_enable = riscv_mintr_get();
|
||||
riscv_mintr_off();
|
||||
int ch = uart_read(uart);
|
||||
riscv_mintr_restore(intr_enable);
|
||||
return ch;
|
||||
}
|
||||
|
||||
int uart_init(void) {
|
||||
puts("[UART0] : Uart Init Done, this is Test output!");
|
||||
return 0;
|
||||
};
|
||||
|
||||
int board_init(void) {
|
||||
int ret;
|
||||
ret = uart_init();
|
||||
if(ret)
|
||||
return ret;
|
||||
ret = hwtimer_init();
|
||||
if(ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
101
port/moonlight/bootup.c
Normal file
101
port/moonlight/bootup.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Simple C++ startup routine to setup CRT
|
||||
SPDX-License-Identifier: Unlicense
|
||||
|
||||
(https://five-embeddev.com/ | http://www.shincbm.com/)
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C extern
|
||||
#endif
|
||||
|
||||
// Generic C function pointer.
|
||||
typedef void(*function_t)(void) ;
|
||||
// These symbols are defined by the linker script.
|
||||
// See linker.lds
|
||||
EXTERN_C uint8_t __bss_start;
|
||||
EXTERN_C uint8_t __bss_end;
|
||||
EXTERN_C const uint8_t __data_source;
|
||||
EXTERN_C uint8_t __data_start;
|
||||
EXTERN_C uint8_t __data_end;
|
||||
|
||||
EXTERN_C function_t __init_array_start;
|
||||
EXTERN_C function_t __init_array_end;
|
||||
EXTERN_C function_t __fini_array_start;
|
||||
EXTERN_C function_t __fini_array_end;
|
||||
|
||||
// This function will be placed by the linker script according to the section
|
||||
// Raw function 'called' by the CPU with no runtime.
|
||||
EXTERN_C void _start(void) __attribute__ ((naked,section(".text.init")));
|
||||
|
||||
// Entry and exit points as C functions.
|
||||
EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".init")));
|
||||
EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak));
|
||||
|
||||
// Standard entry point, no arguments.
|
||||
extern int main(void);
|
||||
|
||||
// The linker script will place this in the reset entry point.
|
||||
// It will be 'called' with no stack or C runtime configuration.
|
||||
// NOTE - this only supports a single hart.
|
||||
// tp will not be initialized
|
||||
void _start(void) {
|
||||
// Setup SP and GP
|
||||
// The locations are defined in the linker script
|
||||
__asm__ volatile (
|
||||
".option push;"
|
||||
// The 'norelax' option is critical here.
|
||||
// Without 'norelax' the global pointer will
|
||||
// be loaded relative to the global pointer!
|
||||
".option norelax;"
|
||||
"la gp, __global_pointer$;"
|
||||
".option pop;"
|
||||
"la sp, _sp;"
|
||||
"jal zero, _initialize;"
|
||||
: /* output: none %0 */
|
||||
: /* input: none */
|
||||
: /* clobbers: none */);
|
||||
// This point will not be executed, _initialize() will be called with no return.
|
||||
}
|
||||
|
||||
// At this point we have a stack and global poiner, but no access to global variables.
|
||||
void _initialize(void) {
|
||||
// Init memory regions
|
||||
// Clear the .bss section (global variables with no initial values)
|
||||
memset((void*) &__bss_start,
|
||||
0,
|
||||
(&__bss_end - &__bss_start));
|
||||
// Initialize the .data section (global variables with initial values)
|
||||
memcpy((void*)&__data_start,
|
||||
(const void*)&__data_source,
|
||||
(&__data_end - &__data_end));
|
||||
// Call constructors
|
||||
for (const function_t* entry=&__init_array_start;
|
||||
entry < &__init_array_end;
|
||||
++entry) {
|
||||
(*entry)();
|
||||
}
|
||||
int rc = main();
|
||||
// Call destructors
|
||||
for (const function_t* entry=&__fini_array_start;
|
||||
entry < &__fini_array_end;
|
||||
++entry) {
|
||||
(*entry)();
|
||||
}
|
||||
_exit(rc);
|
||||
}
|
||||
|
||||
// This should never be called. Busy loop with the CPU in idle state.
|
||||
void _exit(int exit_code) {
|
||||
(void)exit_code;
|
||||
// Halt
|
||||
while (1) {
|
||||
__asm__ volatile ("wfi");
|
||||
}
|
||||
}
|
||||
79
port/moonlight/exception.c
Normal file
79
port/moonlight/exception.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "riscv-traps.h"
|
||||
#include "riscv-csr.h"
|
||||
|
||||
// Expect this to increment one time per second - inside exception handler, after each return of MTI handler.
|
||||
static volatile uint64_t ecall_count = 0;
|
||||
|
||||
void exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
|
||||
switch(mcause) {
|
||||
case RISCV_EXCP_INSTRUCTION_ADDRESS_MISALIGNED: {
|
||||
puts("[EXCEPTION] : Instruction address misaligned\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_INSTRUCTION_ACCESS_FAULT: {
|
||||
puts("[EXCEPTION] : Instruction access fault\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_ILLEGAL_INSTRUCTION: {
|
||||
puts("[EXCEPTION] : Illegal Instruction\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_BREAKPOINT: {
|
||||
puts("[EXCEPTION] : Breakpoint\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_LOAD_ADDRESS_MISALIGNED: {
|
||||
puts("[EXCEPTION] : Load address misaligned");
|
||||
printf("[EXCEPTION] : PC: 0x%x\n", mepc);
|
||||
printf("[EXCEPTION] : Addr: 0x%x\n", mtval);
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_LOAD_ACCESS_FAULT: {
|
||||
puts("[EXCEPTION] : Load access fault\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_STORE_AMO_ADDRESS_MISALIGNED: {
|
||||
puts("[EXCEPTION] : Store/AMO address misaligned");
|
||||
printf("[EXCEPTION] : PC: 0x%x\n", mepc);
|
||||
printf("[EXCEPTION] : Addr: 0x%x\n", mtval);
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_STORE_AMO_ACCESS_FAULT: {
|
||||
puts("[EXCEPTION] : Store/AMO access fault\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_U_MODE: {
|
||||
puts("[EXCEPTION] : Environment call from U-mode\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_S_MODE: {
|
||||
puts("[EXCEPTION] : Environment call from S-mode\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE: {
|
||||
puts("[EXCEPTION] : Environment call from M-mode\n");
|
||||
ecall_count++;
|
||||
csr_write_mepc(mepc+4);
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_INSTRUCTION_PAGE_FAULT: {
|
||||
puts("[EXCEPTION] : Instruction page fault\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_LOAD_PAGE_FAULT: {
|
||||
puts("[EXCEPTION] : Load page fault\n");
|
||||
break;
|
||||
}
|
||||
case RISCV_EXCP_STORE_AMO_PAGE_FAULT: {
|
||||
puts("[EXCEPTION] : Store/AMO page fault\n");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
printf("[EXCEPTION] : Unknown trap cause: %lu\n", mcause);
|
||||
}
|
||||
}
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
97
port/moonlight/gen/aclint.h
Normal file
97
port/moonlight/gen/aclint.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - 2024 MINRES Technologies GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Generated at 2024-08-02 08:46:07 UTC
|
||||
* by peakrdl_mnrs version 1.2.7
|
||||
*/
|
||||
|
||||
#ifndef _BSP_ACLINT_H
|
||||
#define _BSP_ACLINT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t MSIP[4096];
|
||||
struct {
|
||||
volatile uint32_t LO;
|
||||
volatile uint32_t HI;
|
||||
} MTIMECMP[4095];
|
||||
volatile uint32_t MTIME_LO;
|
||||
volatile uint32_t MTIME_HI;
|
||||
} aclint_t;
|
||||
|
||||
#define ACLINT_MSIP_OFFS 0
|
||||
#define ACLINT_MSIP_MASK 0x1
|
||||
#define ACLINT_MSIP(V) ((V & ACLINT_MSIP0_MASK) << ACLINT_MSIP0_OFFS)
|
||||
|
||||
#define ACLINT_MTIMECMPLO_OFFS 0
|
||||
#define ACLINT_MTIMECMPLO_MASK 0xffffffff
|
||||
#define ACLINT_MTIMECMPLO(V) ((V & ACLINT_MTIMECMP0LO_MASK) << ACLINT_MTIMECMP0LO_OFFS)
|
||||
|
||||
#define ACLINT_MTIMECMPHI_OFFS 0
|
||||
#define ACLINT_MTIMECMPHI_MASK 0xffffffff
|
||||
#define ACLINT_MTIMECMPHI(V) ((V & ACLINT_MTIMECMP0HI_MASK) << ACLINT_MTIMECMP0HI_OFFS)
|
||||
|
||||
#define ACLINT_MTIME_LO_OFFS 0
|
||||
#define ACLINT_MTIME_LO_MASK 0xffffffff
|
||||
#define ACLINT_MTIME_LO(V) ((V & ACLINT_MTIME_LO_MASK) << ACLINT_MTIME_LO_OFFS)
|
||||
|
||||
#define ACLINT_MTIME_HI_OFFS 0
|
||||
#define ACLINT_MTIME_HI_MASK 0xffffffff
|
||||
#define ACLINT_MTIME_HI(V) ((V & ACLINT_MTIME_HI_MASK) << ACLINT_MTIME_HI_OFFS)
|
||||
|
||||
// ACLINT_MSIP0
|
||||
static inline uint32_t get_aclint_msip0(volatile aclint_t* reg) { return reg->MSIP[0]; }
|
||||
static inline void set_aclint_msip0(volatile aclint_t* reg, uint32_t value) { reg->MSIP[0] = value; }
|
||||
static inline uint32_t get_aclint_msip0_msip(volatile aclint_t* reg) { return (reg->MSIP[0] >> 0) & 0x1; }
|
||||
static inline void set_aclint_msip0_msip(volatile aclint_t* reg, uint8_t value) {
|
||||
reg->MSIP[0] = (reg->MSIP[0] & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MSIP
|
||||
static inline uint32_t get_aclint_msip(volatile aclint_t* reg, unsigned idx) { return reg->MSIP[idx]; }
|
||||
static inline void set_aclint_msip(volatile aclint_t* reg, unsigned idx, uint32_t value) { reg->MSIP[idx] = value; }
|
||||
static inline uint32_t get_aclint_msip_msip(volatile aclint_t* reg, unsigned idx) { return (reg->MSIP[idx] >> 0) & 0x1; }
|
||||
static inline void set_aclint_msip_msip(volatile aclint_t* reg, unsigned idx, uint8_t value) {
|
||||
reg->MSIP[idx] = (reg->MSIP[idx] & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIMECMP0LO
|
||||
static inline uint32_t get_aclint_mtimecmp0lo(volatile aclint_t* reg) { return (reg->MTIMECMP[0].LO >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtimecmp0lo(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIMECMP[0].LO = (reg->MTIMECMP[0].LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIMECMPxLO
|
||||
static inline uint32_t get_aclint_mtimecmplo(volatile aclint_t* reg, unsigned idx) { return (reg->MTIMECMP[idx].LO >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtimecmplo(volatile aclint_t* reg, unsigned idx, uint32_t value) {
|
||||
reg->MTIMECMP[idx].LO = (reg->MTIMECMP[idx].LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIMECMP0HI
|
||||
static inline uint32_t get_aclint_mtimecmp0hi(volatile aclint_t* reg) { return (reg->MTIMECMP[0].HI >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtimecmp0hi(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIMECMP[0].HI = (reg->MTIMECMP[0].HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIMECMPxHI
|
||||
static inline uint32_t get_aclint_mtimecmphi(volatile aclint_t* reg, unsigned idx) { return (reg->MTIMECMP[idx].HI >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtimecmphi(volatile aclint_t* reg, unsigned idx, uint32_t value) {
|
||||
reg->MTIMECMP[idx].HI = (reg->MTIMECMP[idx].HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIME_LO
|
||||
static inline uint32_t get_aclint_mtime_lo(volatile aclint_t* reg) { return (reg->MTIME_LO >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtime_lo(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIME_LO = (reg->MTIME_LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// ACLINT_MTIME_HI
|
||||
static inline uint32_t get_aclint_mtime_hi(volatile aclint_t* reg) { return (reg->MTIME_HI >> 0) & 0xffffffff; }
|
||||
static inline void set_aclint_mtime_hi(volatile aclint_t* reg, uint32_t value) {
|
||||
reg->MTIME_HI = (reg->MTIME_HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
#endif /* _BSP_ACLINT_H */
|
||||
477
port/moonlight/gen/ethmac.h
Normal file
477
port/moonlight/gen/ethmac.h
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - 2026 MINRES Technologies GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Generated at 2026-01-26 15:33:03 UTC
|
||||
* by peakrdl_mnrs version 1.3.1
|
||||
*/
|
||||
|
||||
#ifndef _BSP_ETHMAC_H
|
||||
#define _BSP_ETHMAC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t MAC_CTRL;
|
||||
uint8_t fill0[12];
|
||||
volatile uint32_t MAC_TX;
|
||||
volatile uint32_t MAC_TX_AVAILABILITY;
|
||||
uint8_t fill1[8];
|
||||
volatile uint32_t MAC_RX;
|
||||
uint8_t fill2[8];
|
||||
volatile uint32_t MAC_RX_STATS;
|
||||
volatile uint32_t MAC_INTR;
|
||||
uint8_t fill3[12];
|
||||
volatile uint32_t MDIO_DATA;
|
||||
volatile uint32_t MDIO_STATUS;
|
||||
volatile uint32_t MDIO_CONFIG;
|
||||
volatile uint32_t MDIO_INTR;
|
||||
uint8_t fill4[16];
|
||||
volatile uint32_t MDIO_SCLK_CONFIG;
|
||||
volatile uint32_t MDIO_SSGEN_SETUP;
|
||||
volatile uint32_t MDIO_SSGEN_HOLD;
|
||||
volatile uint32_t MDIO_SSGEN_DISABLE;
|
||||
volatile uint32_t MDIO_SSGEN_ACTIVE_HIGH;
|
||||
uint8_t fill5[28];
|
||||
volatile uint32_t MDIO_DIRECT_WRITE;
|
||||
volatile uint32_t MDIO_DIRECT_READ_WRITE;
|
||||
volatile uint32_t MDIO_DIRECT_READ;
|
||||
}ethmac_t;
|
||||
|
||||
#define ETHMAC_MAC_CTRL_TX_FLUSH_OFFS 0
|
||||
#define ETHMAC_MAC_CTRL_TX_FLUSH_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_TX_FLUSH(V) ((V & ETHMAC_MAC_CTRL_TX_FLUSH_MASK) << ETHMAC_MAC_CTRL_TX_FLUSH_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_CTRL_TX_READY_OFFS 1
|
||||
#define ETHMAC_MAC_CTRL_TX_READY_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_TX_READY(V) ((V & ETHMAC_MAC_CTRL_TX_READY_MASK) << ETHMAC_MAC_CTRL_TX_READY_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_CTRL_TX_ALIGNER_ENABLE_OFFS 2
|
||||
#define ETHMAC_MAC_CTRL_TX_ALIGNER_ENABLE_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_TX_ALIGNER_ENABLE(V) ((V & ETHMAC_MAC_CTRL_TX_ALIGNER_ENABLE_MASK) << ETHMAC_MAC_CTRL_TX_ALIGNER_ENABLE_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_CTRL_RX_FLUSH_OFFS 4
|
||||
#define ETHMAC_MAC_CTRL_RX_FLUSH_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_RX_FLUSH(V) ((V & ETHMAC_MAC_CTRL_RX_FLUSH_MASK) << ETHMAC_MAC_CTRL_RX_FLUSH_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_CTRL_RX_PENDING_OFFS 5
|
||||
#define ETHMAC_MAC_CTRL_RX_PENDING_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_RX_PENDING(V) ((V & ETHMAC_MAC_CTRL_RX_PENDING_MASK) << ETHMAC_MAC_CTRL_RX_PENDING_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_CTRL_RX_ALIGNER_ENABLE_OFFS 6
|
||||
#define ETHMAC_MAC_CTRL_RX_ALIGNER_ENABLE_MASK 0x1
|
||||
#define ETHMAC_MAC_CTRL_RX_ALIGNER_ENABLE(V) ((V & ETHMAC_MAC_CTRL_RX_ALIGNER_ENABLE_MASK) << ETHMAC_MAC_CTRL_RX_ALIGNER_ENABLE_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_TX_OFFS 0
|
||||
#define ETHMAC_MAC_TX_MASK 0xffffffff
|
||||
#define ETHMAC_MAC_TX(V) ((V & ETHMAC_MAC_TX_MASK) << ETHMAC_MAC_TX_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_TX_AVAILABILITY_OFFS 0
|
||||
#define ETHMAC_MAC_TX_AVAILABILITY_MASK 0x7ff
|
||||
#define ETHMAC_MAC_TX_AVAILABILITY(V) ((V & ETHMAC_MAC_TX_AVAILABILITY_MASK) << ETHMAC_MAC_TX_AVAILABILITY_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_RX_OFFS 0
|
||||
#define ETHMAC_MAC_RX_MASK 0xffffffff
|
||||
#define ETHMAC_MAC_RX(V) ((V & ETHMAC_MAC_RX_MASK) << ETHMAC_MAC_RX_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_RX_STATS_RX_ERRORS_OFFS 0
|
||||
#define ETHMAC_MAC_RX_STATS_RX_ERRORS_MASK 0xff
|
||||
#define ETHMAC_MAC_RX_STATS_RX_ERRORS(V) ((V & ETHMAC_MAC_RX_STATS_RX_ERRORS_MASK) << ETHMAC_MAC_RX_STATS_RX_ERRORS_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_RX_STATS_RX_DROPS_OFFS 8
|
||||
#define ETHMAC_MAC_RX_STATS_RX_DROPS_MASK 0xff
|
||||
#define ETHMAC_MAC_RX_STATS_RX_DROPS(V) ((V & ETHMAC_MAC_RX_STATS_RX_DROPS_MASK) << ETHMAC_MAC_RX_STATS_RX_DROPS_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_INTR_TX_FREE_INTR_ENABLE_OFFS 0
|
||||
#define ETHMAC_MAC_INTR_TX_FREE_INTR_ENABLE_MASK 0x1
|
||||
#define ETHMAC_MAC_INTR_TX_FREE_INTR_ENABLE(V) ((V & ETHMAC_MAC_INTR_TX_FREE_INTR_ENABLE_MASK) << ETHMAC_MAC_INTR_TX_FREE_INTR_ENABLE_OFFS)
|
||||
|
||||
#define ETHMAC_MAC_INTR_RX_DATA_AVAIL_INTR_ENABLE_OFFS 1
|
||||
#define ETHMAC_MAC_INTR_RX_DATA_AVAIL_INTR_ENABLE_MASK 0x1
|
||||
#define ETHMAC_MAC_INTR_RX_DATA_AVAIL_INTR_ENABLE(V) ((V & ETHMAC_MAC_INTR_RX_DATA_AVAIL_INTR_ENABLE_MASK) << ETHMAC_MAC_INTR_RX_DATA_AVAIL_INTR_ENABLE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DATA_DATA_OFFS 0
|
||||
#define ETHMAC_MDIO_DATA_DATA_MASK 0xff
|
||||
#define ETHMAC_MDIO_DATA_DATA(V) ((V & ETHMAC_MDIO_DATA_DATA_MASK) << ETHMAC_MDIO_DATA_DATA_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DATA_WRITE_OFFS 8
|
||||
#define ETHMAC_MDIO_DATA_WRITE_MASK 0x1
|
||||
#define ETHMAC_MDIO_DATA_WRITE(V) ((V & ETHMAC_MDIO_DATA_WRITE_MASK) << ETHMAC_MDIO_DATA_WRITE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DATA_READ_OFFS 9
|
||||
#define ETHMAC_MDIO_DATA_READ_MASK 0x1
|
||||
#define ETHMAC_MDIO_DATA_READ(V) ((V & ETHMAC_MDIO_DATA_READ_MASK) << ETHMAC_MDIO_DATA_READ_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DATA_SSGEN_OFFS 11
|
||||
#define ETHMAC_MDIO_DATA_SSGEN_MASK 0x1
|
||||
#define ETHMAC_MDIO_DATA_SSGEN(V) ((V & ETHMAC_MDIO_DATA_SSGEN_MASK) << ETHMAC_MDIO_DATA_SSGEN_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DATA_RX_DATA_INVALID_OFFS 31
|
||||
#define ETHMAC_MDIO_DATA_RX_DATA_INVALID_MASK 0x1
|
||||
#define ETHMAC_MDIO_DATA_RX_DATA_INVALID(V) ((V & ETHMAC_MDIO_DATA_RX_DATA_INVALID_MASK) << ETHMAC_MDIO_DATA_RX_DATA_INVALID_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_STATUS_TX_FREE_OFFS 0
|
||||
#define ETHMAC_MDIO_STATUS_TX_FREE_MASK 0x3f
|
||||
#define ETHMAC_MDIO_STATUS_TX_FREE(V) ((V & ETHMAC_MDIO_STATUS_TX_FREE_MASK) << ETHMAC_MDIO_STATUS_TX_FREE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_STATUS_RX_AVAIL_OFFS 16
|
||||
#define ETHMAC_MDIO_STATUS_RX_AVAIL_MASK 0x3f
|
||||
#define ETHMAC_MDIO_STATUS_RX_AVAIL(V) ((V & ETHMAC_MDIO_STATUS_RX_AVAIL_MASK) << ETHMAC_MDIO_STATUS_RX_AVAIL_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_CONFIG_CPOL_OFFS 0
|
||||
#define ETHMAC_MDIO_CONFIG_CPOL_MASK 0x1
|
||||
#define ETHMAC_MDIO_CONFIG_CPOL(V) ((V & ETHMAC_MDIO_CONFIG_CPOL_MASK) << ETHMAC_MDIO_CONFIG_CPOL_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_CONFIG_CPHA_OFFS 1
|
||||
#define ETHMAC_MDIO_CONFIG_CPHA_MASK 0x1
|
||||
#define ETHMAC_MDIO_CONFIG_CPHA(V) ((V & ETHMAC_MDIO_CONFIG_CPHA_MASK) << ETHMAC_MDIO_CONFIG_CPHA_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_CONFIG_MODE_OFFS 4
|
||||
#define ETHMAC_MDIO_CONFIG_MODE_MASK 0x1
|
||||
#define ETHMAC_MDIO_CONFIG_MODE(V) ((V & ETHMAC_MDIO_CONFIG_MODE_MASK) << ETHMAC_MDIO_CONFIG_MODE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_INTR_TX_IE_OFFS 0
|
||||
#define ETHMAC_MDIO_INTR_TX_IE_MASK 0x1
|
||||
#define ETHMAC_MDIO_INTR_TX_IE(V) ((V & ETHMAC_MDIO_INTR_TX_IE_MASK) << ETHMAC_MDIO_INTR_TX_IE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_INTR_RX_IE_OFFS 1
|
||||
#define ETHMAC_MDIO_INTR_RX_IE_MASK 0x1
|
||||
#define ETHMAC_MDIO_INTR_RX_IE(V) ((V & ETHMAC_MDIO_INTR_RX_IE_MASK) << ETHMAC_MDIO_INTR_RX_IE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_INTR_TX_IP_OFFS 8
|
||||
#define ETHMAC_MDIO_INTR_TX_IP_MASK 0x1
|
||||
#define ETHMAC_MDIO_INTR_TX_IP(V) ((V & ETHMAC_MDIO_INTR_TX_IP_MASK) << ETHMAC_MDIO_INTR_TX_IP_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_INTR_RX_IP_OFFS 9
|
||||
#define ETHMAC_MDIO_INTR_RX_IP_MASK 0x1
|
||||
#define ETHMAC_MDIO_INTR_RX_IP(V) ((V & ETHMAC_MDIO_INTR_RX_IP_MASK) << ETHMAC_MDIO_INTR_RX_IP_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_INTR_TX_ACTIVE_OFFS 16
|
||||
#define ETHMAC_MDIO_INTR_TX_ACTIVE_MASK 0x1
|
||||
#define ETHMAC_MDIO_INTR_TX_ACTIVE(V) ((V & ETHMAC_MDIO_INTR_TX_ACTIVE_MASK) << ETHMAC_MDIO_INTR_TX_ACTIVE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_SCLK_CONFIG_OFFS 0
|
||||
#define ETHMAC_MDIO_SCLK_CONFIG_MASK 0xfff
|
||||
#define ETHMAC_MDIO_SCLK_CONFIG(V) ((V & ETHMAC_MDIO_SCLK_CONFIG_MASK) << ETHMAC_MDIO_SCLK_CONFIG_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_SSGEN_SETUP_OFFS 0
|
||||
#define ETHMAC_MDIO_SSGEN_SETUP_MASK 0xfff
|
||||
#define ETHMAC_MDIO_SSGEN_SETUP(V) ((V & ETHMAC_MDIO_SSGEN_SETUP_MASK) << ETHMAC_MDIO_SSGEN_SETUP_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_SSGEN_HOLD_OFFS 0
|
||||
#define ETHMAC_MDIO_SSGEN_HOLD_MASK 0xfff
|
||||
#define ETHMAC_MDIO_SSGEN_HOLD(V) ((V & ETHMAC_MDIO_SSGEN_HOLD_MASK) << ETHMAC_MDIO_SSGEN_HOLD_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_SSGEN_DISABLE_OFFS 0
|
||||
#define ETHMAC_MDIO_SSGEN_DISABLE_MASK 0xfff
|
||||
#define ETHMAC_MDIO_SSGEN_DISABLE(V) ((V & ETHMAC_MDIO_SSGEN_DISABLE_MASK) << ETHMAC_MDIO_SSGEN_DISABLE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_SSGEN_ACTIVE_HIGH_OFFS 0
|
||||
#define ETHMAC_MDIO_SSGEN_ACTIVE_HIGH_MASK 0x1
|
||||
#define ETHMAC_MDIO_SSGEN_ACTIVE_HIGH(V) ((V & ETHMAC_MDIO_SSGEN_ACTIVE_HIGH_MASK) << ETHMAC_MDIO_SSGEN_ACTIVE_HIGH_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DIRECT_WRITE_OFFS 0
|
||||
#define ETHMAC_MDIO_DIRECT_WRITE_MASK 0xff
|
||||
#define ETHMAC_MDIO_DIRECT_WRITE(V) ((V & ETHMAC_MDIO_DIRECT_WRITE_MASK) << ETHMAC_MDIO_DIRECT_WRITE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DIRECT_READ_WRITE_OFFS 0
|
||||
#define ETHMAC_MDIO_DIRECT_READ_WRITE_MASK 0xff
|
||||
#define ETHMAC_MDIO_DIRECT_READ_WRITE(V) ((V & ETHMAC_MDIO_DIRECT_READ_WRITE_MASK) << ETHMAC_MDIO_DIRECT_READ_WRITE_OFFS)
|
||||
|
||||
#define ETHMAC_MDIO_DIRECT_READ_OFFS 0
|
||||
#define ETHMAC_MDIO_DIRECT_READ_MASK 0xff
|
||||
#define ETHMAC_MDIO_DIRECT_READ(V) ((V & ETHMAC_MDIO_DIRECT_READ_MASK) << ETHMAC_MDIO_DIRECT_READ_OFFS)
|
||||
|
||||
//ETHMAC_MAC_CTRL
|
||||
static inline uint32_t get_ethmac_mac_ctrl(volatile ethmac_t* reg){
|
||||
return reg->MAC_CTRL;
|
||||
}
|
||||
static inline void set_ethmac_mac_ctrl(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MAC_CTRL = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_tx_flush(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 0) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_ctrl_tx_flush(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_CTRL = (reg->MAC_CTRL & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_tx_ready(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 1) & 0x1;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_tx_aligner_enable(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 2) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_ctrl_tx_aligner_enable(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_CTRL = (reg->MAC_CTRL & ~(0x1U << 2)) | (value << 2);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_rx_flush(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 4) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_ctrl_rx_flush(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_CTRL = (reg->MAC_CTRL & ~(0x1U << 4)) | (value << 4);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_rx_pending(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 5) & 0x1;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_ctrl_rx_aligner_enable(volatile ethmac_t* reg){
|
||||
return (reg->MAC_CTRL >> 6) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_ctrl_rx_aligner_enable(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_CTRL = (reg->MAC_CTRL & ~(0x1U << 6)) | (value << 6);
|
||||
}
|
||||
|
||||
//ETHMAC_MAC_TX
|
||||
static inline uint32_t get_ethmac_mac_tx(volatile ethmac_t* reg){
|
||||
return (reg->MAC_TX >> 0) & 0xffffffff;
|
||||
}
|
||||
static inline void set_ethmac_mac_tx(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MAC_TX = (reg->MAC_TX & ~(0xffffffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MAC_TX_AVAILABILITY
|
||||
static inline uint32_t get_ethmac_mac_tx_availability(volatile ethmac_t* reg){
|
||||
return reg->MAC_TX_AVAILABILITY;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_tx_availability_words_avail(volatile ethmac_t* reg){
|
||||
return (reg->MAC_TX_AVAILABILITY >> 0) & 0x7ff;
|
||||
}
|
||||
|
||||
//ETHMAC_MAC_RX
|
||||
static inline uint32_t get_ethmac_mac_rx(volatile ethmac_t* reg){
|
||||
return (reg->MAC_RX >> 0) & 0xffffffff;
|
||||
}
|
||||
|
||||
//ETHMAC_MAC_RX_STATS
|
||||
static inline uint32_t get_ethmac_mac_rx_stats(volatile ethmac_t* reg){
|
||||
return reg->MAC_RX_STATS;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_rx_stats_rx_errors(volatile ethmac_t* reg){
|
||||
return (reg->MAC_RX_STATS >> 0) & 0xff;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_rx_stats_rx_drops(volatile ethmac_t* reg){
|
||||
return (reg->MAC_RX_STATS >> 8) & 0xff;
|
||||
}
|
||||
|
||||
//ETHMAC_MAC_INTR
|
||||
static inline uint32_t get_ethmac_mac_intr(volatile ethmac_t* reg){
|
||||
return reg->MAC_INTR;
|
||||
}
|
||||
static inline void set_ethmac_mac_intr(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MAC_INTR = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_intr_tx_free_intr_enable(volatile ethmac_t* reg){
|
||||
return (reg->MAC_INTR >> 0) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_intr_tx_free_intr_enable(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_INTR = (reg->MAC_INTR & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mac_intr_rx_data_avail_intr_enable(volatile ethmac_t* reg){
|
||||
return (reg->MAC_INTR >> 1) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mac_intr_rx_data_avail_intr_enable(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MAC_INTR = (reg->MAC_INTR & ~(0x1U << 1)) | (value << 1);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_DATA
|
||||
static inline uint32_t get_ethmac_mdio_data(volatile ethmac_t* reg){
|
||||
return reg->MDIO_DATA;
|
||||
}
|
||||
static inline void set_ethmac_mdio_data(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_DATA = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_data_data(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DATA >> 0) & 0xff;
|
||||
}
|
||||
static inline void set_ethmac_mdio_data_data(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DATA = (reg->MDIO_DATA & ~(0xffU << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_data_write(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DATA >> 8) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_data_write(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DATA = (reg->MDIO_DATA & ~(0x1U << 8)) | (value << 8);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_data_read(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DATA >> 9) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_data_read(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DATA = (reg->MDIO_DATA & ~(0x1U << 9)) | (value << 9);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_data_ssgen(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DATA >> 11) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_data_ssgen(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DATA = (reg->MDIO_DATA & ~(0x1U << 11)) | (value << 11);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_data_rx_data_invalid(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DATA >> 31) & 0x1;
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_STATUS
|
||||
static inline uint32_t get_ethmac_mdio_status(volatile ethmac_t* reg){
|
||||
return reg->MDIO_STATUS;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_status_tx_free(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_STATUS >> 0) & 0x3f;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_status_rx_avail(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_STATUS >> 16) & 0x3f;
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_CONFIG
|
||||
static inline uint32_t get_ethmac_mdio_config(volatile ethmac_t* reg){
|
||||
return reg->MDIO_CONFIG;
|
||||
}
|
||||
static inline void set_ethmac_mdio_config(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_CONFIG = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_config_cpol(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_CONFIG >> 0) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_config_cpol(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_CONFIG = (reg->MDIO_CONFIG & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_config_cpha(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_CONFIG >> 1) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_config_cpha(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_CONFIG = (reg->MDIO_CONFIG & ~(0x1U << 1)) | (value << 1);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_config_mode(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_CONFIG >> 4) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_config_mode(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_CONFIG = (reg->MDIO_CONFIG & ~(0x1U << 4)) | (value << 4);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_INTR
|
||||
static inline uint32_t get_ethmac_mdio_intr(volatile ethmac_t* reg){
|
||||
return reg->MDIO_INTR;
|
||||
}
|
||||
static inline void set_ethmac_mdio_intr(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_INTR = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_intr_tx_ie(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_INTR >> 0) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_intr_tx_ie(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_INTR = (reg->MDIO_INTR & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_intr_rx_ie(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_INTR >> 1) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_intr_rx_ie(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_INTR = (reg->MDIO_INTR & ~(0x1U << 1)) | (value << 1);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_intr_tx_ip(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_INTR >> 8) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_intr_tx_ip(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_INTR = (reg->MDIO_INTR & ~(0x1U << 8)) | (value << 8);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_intr_rx_ip(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_INTR >> 9) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_intr_rx_ip(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_INTR = (reg->MDIO_INTR & ~(0x1U << 9)) | (value << 9);
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_intr_tx_active(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_INTR >> 16) & 0x1;
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_SCLK_CONFIG
|
||||
static inline uint32_t get_ethmac_mdio_sclk_config(volatile ethmac_t* reg){
|
||||
return reg->MDIO_SCLK_CONFIG;
|
||||
}
|
||||
static inline void set_ethmac_mdio_sclk_config(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_SCLK_CONFIG = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_sclk_config_clk_divider(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_SCLK_CONFIG >> 0) & 0xfff;
|
||||
}
|
||||
static inline void set_ethmac_mdio_sclk_config_clk_divider(volatile ethmac_t* reg, uint16_t value){
|
||||
reg->MDIO_SCLK_CONFIG = (reg->MDIO_SCLK_CONFIG & ~(0xfffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_SSGEN_SETUP
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_setup(volatile ethmac_t* reg){
|
||||
return reg->MDIO_SSGEN_SETUP;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_setup(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_SSGEN_SETUP = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_setup_setup_cycles(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_SSGEN_SETUP >> 0) & 0xfff;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_setup_setup_cycles(volatile ethmac_t* reg, uint16_t value){
|
||||
reg->MDIO_SSGEN_SETUP = (reg->MDIO_SSGEN_SETUP & ~(0xfffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_SSGEN_HOLD
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_hold(volatile ethmac_t* reg){
|
||||
return reg->MDIO_SSGEN_HOLD;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_hold(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_SSGEN_HOLD = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_hold_hold_cycles(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_SSGEN_HOLD >> 0) & 0xfff;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_hold_hold_cycles(volatile ethmac_t* reg, uint16_t value){
|
||||
reg->MDIO_SSGEN_HOLD = (reg->MDIO_SSGEN_HOLD & ~(0xfffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_SSGEN_DISABLE
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_disable(volatile ethmac_t* reg){
|
||||
return reg->MDIO_SSGEN_DISABLE;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_disable(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_SSGEN_DISABLE = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_disable_disable_cycles(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_SSGEN_DISABLE >> 0) & 0xfff;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_disable_disable_cycles(volatile ethmac_t* reg, uint16_t value){
|
||||
reg->MDIO_SSGEN_DISABLE = (reg->MDIO_SSGEN_DISABLE & ~(0xfffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_SSGEN_ACTIVE_HIGH
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_active_high(volatile ethmac_t* reg){
|
||||
return reg->MDIO_SSGEN_ACTIVE_HIGH;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_active_high(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_SSGEN_ACTIVE_HIGH = value;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_ssgen_active_high_spi_cs_active_high(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_SSGEN_ACTIVE_HIGH >> 0) & 0x1;
|
||||
}
|
||||
static inline void set_ethmac_mdio_ssgen_active_high_spi_cs_active_high(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_SSGEN_ACTIVE_HIGH = (reg->MDIO_SSGEN_ACTIVE_HIGH & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_DIRECT_WRITE
|
||||
static inline void set_ethmac_mdio_direct_write(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_DIRECT_WRITE = value;
|
||||
}
|
||||
static inline void set_ethmac_mdio_direct_write_data(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DIRECT_WRITE = (reg->MDIO_DIRECT_WRITE & ~(0xffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_DIRECT_READ_WRITE
|
||||
static inline void set_ethmac_mdio_direct_read_write(volatile ethmac_t* reg, uint32_t value){
|
||||
reg->MDIO_DIRECT_READ_WRITE = value;
|
||||
}
|
||||
static inline void set_ethmac_mdio_direct_read_write_data(volatile ethmac_t* reg, uint8_t value){
|
||||
reg->MDIO_DIRECT_READ_WRITE = (reg->MDIO_DIRECT_READ_WRITE & ~(0xffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
//ETHMAC_MDIO_DIRECT_READ
|
||||
static inline uint32_t get_ethmac_mdio_direct_read(volatile ethmac_t* reg){
|
||||
return reg->MDIO_DIRECT_READ;
|
||||
}
|
||||
static inline uint32_t get_ethmac_mdio_direct_read_data(volatile ethmac_t* reg){
|
||||
return (reg->MDIO_DIRECT_READ >> 0) & 0xff;
|
||||
}
|
||||
|
||||
#endif /* _BSP_ETHMAC_H */
|
||||
176
port/moonlight/gen/uart.h
Normal file
176
port/moonlight/gen/uart.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - 2024 MINRES Technologies GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Generated at 2024-08-02 08:46:07 UTC
|
||||
* by peakrdl_mnrs version 1.2.7
|
||||
*/
|
||||
|
||||
#ifndef _BSP_UART_H
|
||||
#define _BSP_UART_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t RX_TX_REG;
|
||||
volatile uint32_t INT_CTRL_REG;
|
||||
volatile uint32_t CLK_DIVIDER_REG;
|
||||
volatile uint32_t FRAME_CONFIG_REG;
|
||||
volatile uint32_t STATUS_REG;
|
||||
} uart_t;
|
||||
|
||||
#define UART_RX_TX_REG_DATA_OFFS 0
|
||||
#define UART_RX_TX_REG_DATA_MASK 0xff
|
||||
#define UART_RX_TX_REG_DATA(V) ((V & UART_RX_TX_REG_DATA_MASK) << UART_RX_TX_REG_DATA_OFFS)
|
||||
|
||||
#define UART_RX_TX_REG_RX_AVAIL_OFFS 14
|
||||
#define UART_RX_TX_REG_RX_AVAIL_MASK 0x1
|
||||
#define UART_RX_TX_REG_RX_AVAIL(V) ((V & UART_RX_TX_REG_RX_AVAIL_MASK) << UART_RX_TX_REG_RX_AVAIL_OFFS)
|
||||
|
||||
#define UART_RX_TX_REG_TX_FREE_OFFS 15
|
||||
#define UART_RX_TX_REG_TX_FREE_MASK 0x1
|
||||
#define UART_RX_TX_REG_TX_FREE(V) ((V & UART_RX_TX_REG_TX_FREE_MASK) << UART_RX_TX_REG_TX_FREE_OFFS)
|
||||
|
||||
#define UART_RX_TX_REG_TX_EMPTY_OFFS 16
|
||||
#define UART_RX_TX_REG_TX_EMPTY_MASK 0x1
|
||||
#define UART_RX_TX_REG_TX_EMPTY(V) ((V & UART_RX_TX_REG_TX_EMPTY_MASK) << UART_RX_TX_REG_TX_EMPTY_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_ENABLE_OFFS 0
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_ENABLE_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_ENABLE(V) ((V & UART_INT_CTRL_REG_WRITE_INTR_ENABLE_MASK) << UART_INT_CTRL_REG_WRITE_INTR_ENABLE_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_READ_INTR_ENABLE_OFFS 1
|
||||
#define UART_INT_CTRL_REG_READ_INTR_ENABLE_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_READ_INTR_ENABLE(V) ((V & UART_INT_CTRL_REG_READ_INTR_ENABLE_MASK) << UART_INT_CTRL_REG_READ_INTR_ENABLE_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_ENABLE_OFFS 2
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_ENABLE_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_ENABLE(V) ((V & UART_INT_CTRL_REG_BREAK_INTR_ENABLE_MASK) << UART_INT_CTRL_REG_BREAK_INTR_ENABLE_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_PEND_OFFS 8
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_PEND_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_WRITE_INTR_PEND(V) ((V & UART_INT_CTRL_REG_WRITE_INTR_PEND_MASK) << UART_INT_CTRL_REG_WRITE_INTR_PEND_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_READ_INTR_PEND_OFFS 9
|
||||
#define UART_INT_CTRL_REG_READ_INTR_PEND_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_READ_INTR_PEND(V) ((V & UART_INT_CTRL_REG_READ_INTR_PEND_MASK) << UART_INT_CTRL_REG_READ_INTR_PEND_OFFS)
|
||||
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_PEND_OFFS 10
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_PEND_MASK 0x1
|
||||
#define UART_INT_CTRL_REG_BREAK_INTR_PEND(V) ((V & UART_INT_CTRL_REG_BREAK_INTR_PEND_MASK) << UART_INT_CTRL_REG_BREAK_INTR_PEND_OFFS)
|
||||
|
||||
#define UART_CLK_DIVIDER_REG_OFFS 0
|
||||
#define UART_CLK_DIVIDER_REG_MASK 0xfffff
|
||||
#define UART_CLK_DIVIDER_REG(V) ((V & UART_CLK_DIVIDER_REG_MASK) << UART_CLK_DIVIDER_REG_OFFS)
|
||||
|
||||
#define UART_FRAME_CONFIG_REG_DATA_LENGTH_OFFS 0
|
||||
#define UART_FRAME_CONFIG_REG_DATA_LENGTH_MASK 0x7
|
||||
#define UART_FRAME_CONFIG_REG_DATA_LENGTH(V) ((V & UART_FRAME_CONFIG_REG_DATA_LENGTH_MASK) << UART_FRAME_CONFIG_REG_DATA_LENGTH_OFFS)
|
||||
|
||||
#define UART_FRAME_CONFIG_REG_PARITY_OFFS 3
|
||||
#define UART_FRAME_CONFIG_REG_PARITY_MASK 0x3
|
||||
#define UART_FRAME_CONFIG_REG_PARITY(V) ((V & UART_FRAME_CONFIG_REG_PARITY_MASK) << UART_FRAME_CONFIG_REG_PARITY_OFFS)
|
||||
|
||||
#define UART_FRAME_CONFIG_REG_STOP_BIT_OFFS 5
|
||||
#define UART_FRAME_CONFIG_REG_STOP_BIT_MASK 0x1
|
||||
#define UART_FRAME_CONFIG_REG_STOP_BIT(V) ((V & UART_FRAME_CONFIG_REG_STOP_BIT_MASK) << UART_FRAME_CONFIG_REG_STOP_BIT_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_READ_ERROR_OFFS 0
|
||||
#define UART_STATUS_REG_READ_ERROR_MASK 0x1
|
||||
#define UART_STATUS_REG_READ_ERROR(V) ((V & UART_STATUS_REG_READ_ERROR_MASK) << UART_STATUS_REG_READ_ERROR_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_STALL_OFFS 1
|
||||
#define UART_STATUS_REG_STALL_MASK 0x1
|
||||
#define UART_STATUS_REG_STALL(V) ((V & UART_STATUS_REG_STALL_MASK) << UART_STATUS_REG_STALL_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_BREAK_LINE_OFFS 8
|
||||
#define UART_STATUS_REG_BREAK_LINE_MASK 0x1
|
||||
#define UART_STATUS_REG_BREAK_LINE(V) ((V & UART_STATUS_REG_BREAK_LINE_MASK) << UART_STATUS_REG_BREAK_LINE_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_BREAK_DETECTED_OFFS 9
|
||||
#define UART_STATUS_REG_BREAK_DETECTED_MASK 0x1
|
||||
#define UART_STATUS_REG_BREAK_DETECTED(V) ((V & UART_STATUS_REG_BREAK_DETECTED_MASK) << UART_STATUS_REG_BREAK_DETECTED_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_SET_BREAK_OFFS 10
|
||||
#define UART_STATUS_REG_SET_BREAK_MASK 0x1
|
||||
#define UART_STATUS_REG_SET_BREAK(V) ((V & UART_STATUS_REG_SET_BREAK_MASK) << UART_STATUS_REG_SET_BREAK_OFFS)
|
||||
|
||||
#define UART_STATUS_REG_CLEAR_BREAK_OFFS 11
|
||||
#define UART_STATUS_REG_CLEAR_BREAK_MASK 0x1
|
||||
#define UART_STATUS_REG_CLEAR_BREAK(V) ((V & UART_STATUS_REG_CLEAR_BREAK_MASK) << UART_STATUS_REG_CLEAR_BREAK_OFFS)
|
||||
|
||||
// UART_RX_TX_REG
|
||||
static inline uint32_t get_uart_rx_tx_reg(volatile uart_t* reg) { return reg->RX_TX_REG; }
|
||||
static inline void set_uart_rx_tx_reg(volatile uart_t* reg, uint32_t value) { reg->RX_TX_REG = value; }
|
||||
static inline uint32_t get_uart_rx_tx_reg_data(volatile uart_t* reg) { return (reg->RX_TX_REG >> 0) & 0xff; }
|
||||
static inline void set_uart_rx_tx_reg_data(volatile uart_t* reg, uint8_t value) {
|
||||
reg->RX_TX_REG = (reg->RX_TX_REG & ~(0xffU << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_uart_rx_tx_reg_rx_avail(volatile uart_t* reg) { return (reg->RX_TX_REG >> 14) & 0x1; }
|
||||
static inline uint32_t get_uart_rx_tx_reg_tx_free(volatile uart_t* reg) { return (reg->RX_TX_REG >> 15) & 0x1; }
|
||||
static inline uint32_t get_uart_rx_tx_reg_tx_empty(volatile uart_t* reg) { return (reg->RX_TX_REG >> 16) & 0x1; }
|
||||
|
||||
// UART_INT_CTRL_REG
|
||||
static inline uint32_t get_uart_int_ctrl_reg(volatile uart_t* reg) { return reg->INT_CTRL_REG; }
|
||||
static inline void set_uart_int_ctrl_reg(volatile uart_t* reg, uint32_t value) { reg->INT_CTRL_REG = value; }
|
||||
static inline uint32_t get_uart_int_ctrl_reg_write_intr_enable(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 0) & 0x1; }
|
||||
static inline void set_uart_int_ctrl_reg_write_intr_enable(volatile uart_t* reg, uint8_t value) {
|
||||
reg->INT_CTRL_REG = (reg->INT_CTRL_REG & ~(0x1U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_uart_int_ctrl_reg_read_intr_enable(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 1) & 0x1; }
|
||||
static inline void set_uart_int_ctrl_reg_read_intr_enable(volatile uart_t* reg, uint8_t value) {
|
||||
reg->INT_CTRL_REG = (reg->INT_CTRL_REG & ~(0x1U << 1)) | (value << 1);
|
||||
}
|
||||
static inline uint32_t get_uart_int_ctrl_reg_break_intr_enable(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 2) & 0x1; }
|
||||
static inline void set_uart_int_ctrl_reg_break_intr_enable(volatile uart_t* reg, uint8_t value) {
|
||||
reg->INT_CTRL_REG = (reg->INT_CTRL_REG & ~(0x1U << 2)) | (value << 2);
|
||||
}
|
||||
static inline uint32_t get_uart_int_ctrl_reg_write_intr_pend(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 8) & 0x1; }
|
||||
static inline uint32_t get_uart_int_ctrl_reg_read_intr_pend(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 9) & 0x1; }
|
||||
static inline uint32_t get_uart_int_ctrl_reg_break_intr_pend(volatile uart_t* reg) { return (reg->INT_CTRL_REG >> 10) & 0x1; }
|
||||
|
||||
// UART_CLK_DIVIDER_REG
|
||||
static inline uint32_t get_uart_clk_divider_reg(volatile uart_t* reg) { return reg->CLK_DIVIDER_REG; }
|
||||
static inline void set_uart_clk_divider_reg(volatile uart_t* reg, uint32_t value) { reg->CLK_DIVIDER_REG = value; }
|
||||
static inline uint32_t get_uart_clk_divider_reg_clock_divider(volatile uart_t* reg) { return (reg->CLK_DIVIDER_REG >> 0) & 0xfffff; }
|
||||
static inline void set_uart_clk_divider_reg_clock_divider(volatile uart_t* reg, uint32_t value) {
|
||||
reg->CLK_DIVIDER_REG = (reg->CLK_DIVIDER_REG & ~(0xfffffU << 0)) | (value << 0);
|
||||
}
|
||||
|
||||
// UART_FRAME_CONFIG_REG
|
||||
static inline uint32_t get_uart_frame_config_reg(volatile uart_t* reg) { return reg->FRAME_CONFIG_REG; }
|
||||
static inline void set_uart_frame_config_reg(volatile uart_t* reg, uint32_t value) { reg->FRAME_CONFIG_REG = value; }
|
||||
static inline uint32_t get_uart_frame_config_reg_data_length(volatile uart_t* reg) { return (reg->FRAME_CONFIG_REG >> 0) & 0x7; }
|
||||
static inline void set_uart_frame_config_reg_data_length(volatile uart_t* reg, uint8_t value) {
|
||||
reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x7U << 0)) | (value << 0);
|
||||
}
|
||||
static inline uint32_t get_uart_frame_config_reg_parity(volatile uart_t* reg) { return (reg->FRAME_CONFIG_REG >> 3) & 0x3; }
|
||||
static inline void set_uart_frame_config_reg_parity(volatile uart_t* reg, uint8_t value) {
|
||||
reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x3U << 3)) | (value << 3);
|
||||
}
|
||||
static inline uint32_t get_uart_frame_config_reg_stop_bit(volatile uart_t* reg) { return (reg->FRAME_CONFIG_REG >> 5) & 0x1; }
|
||||
static inline void set_uart_frame_config_reg_stop_bit(volatile uart_t* reg, uint8_t value) {
|
||||
reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x1U << 5)) | (value << 5);
|
||||
}
|
||||
|
||||
// UART_STATUS_REG
|
||||
static inline uint32_t get_uart_status_reg(volatile uart_t* reg) { return reg->STATUS_REG; }
|
||||
static inline void set_uart_status_reg(volatile uart_t* reg, uint32_t value) { reg->STATUS_REG = value; }
|
||||
static inline uint32_t get_uart_status_reg_read_error(volatile uart_t* reg) { return (reg->STATUS_REG >> 0) & 0x1; }
|
||||
static inline uint32_t get_uart_status_reg_stall(volatile uart_t* reg) { return (reg->STATUS_REG >> 1) & 0x1; }
|
||||
static inline uint32_t get_uart_status_reg_break_line(volatile uart_t* reg) { return (reg->STATUS_REG >> 8) & 0x1; }
|
||||
static inline uint32_t get_uart_status_reg_break_detected(volatile uart_t* reg) { return (reg->STATUS_REG >> 9) & 0x1; }
|
||||
static inline void set_uart_status_reg_break_detected(volatile uart_t* reg, uint8_t value) {
|
||||
reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 9)) | (value << 9);
|
||||
}
|
||||
static inline uint32_t get_uart_status_reg_set_break(volatile uart_t* reg) { return (reg->STATUS_REG >> 10) & 0x1; }
|
||||
static inline void set_uart_status_reg_set_break(volatile uart_t* reg, uint8_t value) {
|
||||
reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 10)) | (value << 10);
|
||||
}
|
||||
static inline uint32_t get_uart_status_reg_clear_break(volatile uart_t* reg) { return (reg->STATUS_REG >> 11) & 0x1; }
|
||||
static inline void set_uart_status_reg_clear_break(volatile uart_t* reg, uint8_t value) {
|
||||
reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 11)) | (value << 11);
|
||||
}
|
||||
|
||||
#endif /* _BSP_UART_H */
|
||||
32
port/moonlight/hwtimer.h
Normal file
32
port/moonlight/hwtimer.h
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef RISCV_HWTIMER_H
|
||||
#define RISCV_HWTIMER_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#define TICKNUM_PER_SECOND 32768
|
||||
#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 1000)
|
||||
|
||||
static inline int hwtimer_init(void) {
|
||||
uint64_t time = get_aclint_mtime(aclint);
|
||||
set_aclint_mtimecmp(aclint, time + TICKNUM_PER_TIMER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hwtimer_handler(void) {
|
||||
uint64_t time = get_aclint_mtime(aclint);
|
||||
set_aclint_mtimecmp(aclint, time + TICKNUM_PER_TIMER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
1067
port/moonlight/mnrs_network_driver.c
Normal file
1067
port/moonlight/mnrs_network_driver.c
Normal file
File diff suppressed because it is too large
Load Diff
24
port/moonlight/platform.h
Normal file
24
port/moonlight/platform.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "uart.h"
|
||||
#include "gen/ethmac.h"
|
||||
#include "aclint.h"
|
||||
#include "riscv-csr.h"
|
||||
#include "riscv-traps.h"
|
||||
|
||||
#define PERIPH(TYPE, ADDR) ((volatile TYPE*)(ADDR))
|
||||
#define APB_BASE 0x10000000
|
||||
#define uart PERIPH(uart_t, APB_BASE + 0x01000)
|
||||
#define aclint PERIPH(aclint_t, APB_BASE + 0x30000)
|
||||
#define ethmac0 PERIPH(ethmac_t, 0x18000000)
|
||||
#define ethmac1 PERIPH(ethmac_t, 0x18001000)
|
||||
|
||||
#define UART0_IRQ 16
|
||||
#define TIMER0_IRQ0 17
|
||||
#define TIMER0_IRQ1 18
|
||||
#define QSPI_IRQ 19
|
||||
#define I2S_IRQ 20
|
||||
#define CAM_IRQ 21
|
||||
#define DMA_IRQ 22
|
||||
#define GPIO_ORQ 23
|
||||
#define ETH0_IRQ 24
|
||||
#define ETH1_IRQ 25
|
||||
|
||||
3791
port/moonlight/riscv-csr.h
Normal file
3791
port/moonlight/riscv-csr.h
Normal file
File diff suppressed because it is too large
Load Diff
68
port/moonlight/riscv-traps.h
Normal file
68
port/moonlight/riscv-traps.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
RISC-V machine interrupts.
|
||||
SPDX-License-Identifier: Unlicense
|
||||
|
||||
https://five-embeddev.com/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RISCV_TRAPS_H
|
||||
#define RISCV_TRAPS_H
|
||||
|
||||
enum {
|
||||
RISCV_INT_MSI = 3,
|
||||
RISCV_INT_MTI = 7,
|
||||
RISCV_INT_MEI = 11,
|
||||
RISCV_INT_SSI = 1,
|
||||
RISCV_INT_STI = 5,
|
||||
RISCV_INT_SEI = 9,
|
||||
RISCV_INT_USI = 0,
|
||||
RISCV_INT_UTI = 4,
|
||||
RISCV_INT_UEI = 8,
|
||||
};
|
||||
|
||||
enum {
|
||||
RISCV_INT_POS_MSI = 3,
|
||||
RISCV_INT_POS_MTI = 7,
|
||||
RISCV_INT_POS_MEI = 11,
|
||||
RISCV_INT_POS_SSI = 1,
|
||||
RISCV_INT_POS_STI = 5,
|
||||
RISCV_INT_POS_SEI = 9,
|
||||
RISCV_INT_POS_USI = 0,
|
||||
RISCV_INT_POS_UTI = 4,
|
||||
RISCV_INT_POS_UEI = 8,
|
||||
};
|
||||
|
||||
enum {
|
||||
RISCV_INT_MASK_MSI = (1UL<<RISCV_INT_POS_MSI),
|
||||
RISCV_INT_MASK_MTI = (1UL<<RISCV_INT_POS_MTI),
|
||||
RISCV_INT_MASK_MEI = (1UL<<RISCV_INT_POS_MEI),
|
||||
RISCV_INT_MASK_SSI = (1UL<<RISCV_INT_POS_SSI),
|
||||
RISCV_INT_MASK_STI = (1UL<<RISCV_INT_POS_STI),
|
||||
RISCV_INT_MASK_SEI = (1UL<<RISCV_INT_POS_SEI),
|
||||
RISCV_INT_MASK_USI = (1UL<<RISCV_INT_POS_USI),
|
||||
RISCV_INT_MASK_UTI = (1UL<<RISCV_INT_POS_UTI),
|
||||
RISCV_INT_MASK_UEI = (1UL<<RISCV_INT_POS_UEI),
|
||||
};
|
||||
|
||||
enum {
|
||||
RISCV_EXCP_INSTRUCTION_ADDRESS_MISALIGNED=0, /* Instruction address misaligned */
|
||||
RISCV_EXCP_INSTRUCTION_ACCESS_FAULT=1, /* Instruction access fault */
|
||||
RISCV_EXCP_ILLEGAL_INSTRUCTION=2, /* Illegal instruction */
|
||||
RISCV_EXCP_BREAKPOINT=3, /* Breakpoint */
|
||||
RISCV_EXCP_LOAD_ADDRESS_MISALIGNED=4, /* Load address misaligned */
|
||||
RISCV_EXCP_LOAD_ACCESS_FAULT=5, /* Load access fault */
|
||||
RISCV_EXCP_STORE_AMO_ADDRESS_MISALIGNED =6, /* Store/AMO address misaligned */
|
||||
RISCV_EXCP_STORE_AMO_ACCESS_FAULT=7, /* Store/AMO access fault */
|
||||
RISCV_EXCP_ENVIRONMENT_CALL_FROM_U_MODE=8, /* Environment call from U-mode */
|
||||
RISCV_EXCP_ENVIRONMENT_CALL_FROM_S_MODE=9, /* Environment call from S-mode */
|
||||
RISCV_EXCP_RESERVED10=10, /* Reserved */
|
||||
RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE=11, /* Environment call from M-mode */
|
||||
RISCV_EXCP_INSTRUCTION_PAGE_FAULT=12, /* Instruction page fault */
|
||||
RISCV_EXCP_LOAD_PAGE_FAULT=13, /* Load page fault */
|
||||
RISCV_EXCP_RESERVED14=14, /* Reserved */
|
||||
RISCV_EXCP_STORE_AMO_PAGE_FAULT=15, /* Store/AMO page fault */
|
||||
};
|
||||
|
||||
|
||||
#endif /* RISCV_TRAPS_H */
|
||||
57
port/moonlight/trap_non_vectored.c
Normal file
57
port/moonlight/trap_non_vectored.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "hwtimer.h"
|
||||
#include <stdint.h>
|
||||
#include <tx_api.h>
|
||||
#include <tx_port.h>
|
||||
#include <stdio.h>
|
||||
#include "riscv-traps.h"
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define INTERRUPT_BIT 0x8000000000000000ull
|
||||
#else
|
||||
#define INTERRUPT_BIT 0x80000000ull
|
||||
#endif
|
||||
#define OS_IS_INTERRUPT(mcause) (mcause & INTERRUPT_BIT)
|
||||
#define OS_IS_TICK_INT(mcause) (mcause == (0x7 | INTERRUPT_BIT))
|
||||
#define OS_IS_SOFT_INT(mcause) (mcause == (0x3 | INTERRUPT_BIT))
|
||||
#define OS_IS_EXT_INT(mcause) (mcause == (0xb | INTERRUPT_BIT))
|
||||
|
||||
extern void _tx_timer_interrupt(void);
|
||||
extern uintptr_t exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval);
|
||||
|
||||
void (*irq_handler[__riscv_xlen])();
|
||||
|
||||
int register_irq_handler(unsigned irq_num, void (*handler)()) {
|
||||
if(irq_num<__riscv_xlen){
|
||||
irq_handler[irq_num] = handler;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
|
||||
if(OS_IS_INTERRUPT(mcause)) {
|
||||
unsigned irq_id = mcause&(__riscv_xlen-1);
|
||||
switch(irq_id){
|
||||
case RISCV_INT_MTI:
|
||||
hwtimer_handler();
|
||||
_tx_timer_interrupt();
|
||||
break;
|
||||
case RISCV_INT_MEI:
|
||||
puts("[INTERRUPT]: handler ext irq error!\n");
|
||||
while(1)
|
||||
;
|
||||
break;
|
||||
default:
|
||||
if(irq_handler[irq_id])
|
||||
irq_handler[irq_id]();
|
||||
else {
|
||||
printf("[INTERRUPT]: Unkown Interrupt %d!!\n", mcause&0xff);
|
||||
puts("[INTERRUPT]: now can't deal with the interrupt!\n");
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exception( mcause, mepc, mtval);
|
||||
}
|
||||
}
|
||||
78
port/moonlight/trap_vectored.c
Normal file
78
port/moonlight/trap_vectored.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Baremetal main program with timer interrupt.
|
||||
SPDX-License-Identifier: Unlicense
|
||||
|
||||
https://five-embeddev.com/
|
||||
|
||||
Tested with sifive-hifive-revb, but should not have any
|
||||
dependencies to any particular implementation.
|
||||
|
||||
*/
|
||||
|
||||
// RISC-V CSR definitions and access classes
|
||||
#include "riscv-csr.h"
|
||||
#include "riscv-interrupt.h"
|
||||
#include "hwtimer.h"
|
||||
#include "vector_table.h"
|
||||
|
||||
extern void _tx_timer_interrupt(void);
|
||||
|
||||
// Machine mode interrupt service routine
|
||||
|
||||
// Global to hold current timestamp, written in MTI handler.
|
||||
static volatile uint64_t timestamp = 0;
|
||||
|
||||
#define RISCV_MTVEC_MODE_VECTORED 1
|
||||
|
||||
int init_irq(void) {
|
||||
// Global interrupt disable
|
||||
csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
|
||||
csr_write_mie(0);
|
||||
|
||||
// Setup the IRQ handler entry point, set the mode to vectored
|
||||
csr_write_mtvec((uint_xlen_t) riscv_mtvec_table | RISCV_MTVEC_MODE_VECTORED);
|
||||
|
||||
// Enable MIE.MTI
|
||||
csr_set_bits_mie(MIE_MTI_BIT_MASK);
|
||||
|
||||
// Global interrupt enable
|
||||
csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK);
|
||||
|
||||
// Setup timer for 1 second interval
|
||||
hwtimer_init();
|
||||
|
||||
// Busy loop
|
||||
do {
|
||||
// Wait for timer interrupt
|
||||
__asm__ volatile ("wfi");
|
||||
// Try a synchronous exception.
|
||||
__asm__ volatile ("ecall");
|
||||
} while (1);
|
||||
|
||||
// Will not reach here
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
// Force the alignment for mtvec.BASE. A 'C' extension program could be aligned to to bytes.
|
||||
#pragma GCC optimize ("align-functions=4")
|
||||
// The 'riscv_mtvec_mti' function is added to the vector table by the vector_table.c
|
||||
void riscv_mtvec_mti(void) {
|
||||
hwtimer_handler();
|
||||
_tx_timer_interrupt();
|
||||
}
|
||||
// The 'riscv_mtvec_exception' function is added to the vector table by the vector_table.c
|
||||
// This function looks at the cause of the exception, if it is an 'ecall' instruction then increment a global counter.
|
||||
void riscv_mtvec_exception(void) {
|
||||
uint_xlen_t this_cause = csr_read_mcause();
|
||||
uint_xlen_t this_pc = csr_read_mepc();
|
||||
//uint_xlen_t this_value = csr_read_mtval();
|
||||
switch (this_cause) {
|
||||
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE:
|
||||
ecall_count++;
|
||||
// Make sure the return address is the instruction AFTER ecall
|
||||
csr_write_mepc(this_pc+4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
134
port/moonlight/tx_timer_interrupt.c
Normal file
134
port/moonlight/tx_timer_interrupt.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_timer.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* interrupt context save/restore functions are called along with the */
|
||||
/* expiration functions. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_timer_interrupt(VOID)
|
||||
{
|
||||
/* Increment system clock. */
|
||||
_tx_timer_system_clock++;
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
/* Decrement the time_slice. */
|
||||
_tx_timer_time_slice--;
|
||||
|
||||
/* Check for expiration. */
|
||||
if (_tx_timer_time_slice == 0)
|
||||
{
|
||||
|
||||
/* Set the time-slice expired flag. */
|
||||
_tx_timer_expired_time_slice = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test for timer expiration. */
|
||||
if (*_tx_timer_current_ptr)
|
||||
{
|
||||
|
||||
/* Set expiration flag. */
|
||||
_tx_timer_expired = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
_tx_timer_current_ptr++;
|
||||
|
||||
/* Check for wrap-around. */
|
||||
if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
{
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
_tx_timer_current_ptr = _tx_timer_list_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if anything has expired. */
|
||||
if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
{
|
||||
|
||||
/* Did a timer expire? */
|
||||
if (_tx_timer_expired)
|
||||
{
|
||||
|
||||
/* Process timer expiration. */
|
||||
_tx_timer_expiration_process();
|
||||
}
|
||||
|
||||
/* Did time slice expire? */
|
||||
if (_tx_timer_expired_time_slice)
|
||||
{
|
||||
|
||||
/* Time slice interrupted thread. */
|
||||
_tx_thread_time_slice();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
port/moonlight/uart.h
Normal file
25
port/moonlight/uart.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _DEVICES_UART_H
|
||||
#define _DEVICES_UART_H
|
||||
#include "gen/uart.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint32_t uart_get_tx_free(volatile uart_t* reg) { return get_uart_rx_tx_reg_tx_free(reg); }
|
||||
|
||||
static inline uint32_t uart_get_tx_empty(volatile uart_t* reg) { return get_uart_rx_tx_reg_tx_empty(reg); }
|
||||
|
||||
static inline uint32_t uart_get_rx_avail(volatile uart_t* reg) { return get_uart_rx_tx_reg_rx_avail(reg); }
|
||||
|
||||
static inline void uart_write(volatile uart_t* reg, uint8_t data) {
|
||||
while(get_uart_rx_tx_reg_tx_free(reg) == 0)
|
||||
;
|
||||
set_uart_rx_tx_reg_data(reg, data);
|
||||
}
|
||||
|
||||
static inline uint8_t uart_read(volatile uart_t* reg) {
|
||||
uint32_t res = get_uart_rx_tx_reg_data(reg);
|
||||
while((res & 0x10000) == 0)
|
||||
res = get_uart_rx_tx_reg_data(reg);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* _DEVICES_UART_H */
|
||||
166
port/moonlight/vector_table.c
Normal file
166
port/moonlight/vector_table.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Baremetal main program with timer interrupt.
|
||||
SPDX-License-Identifier: Unlicense
|
||||
|
||||
https://five-embeddev.com/
|
||||
|
||||
Tested with sifive-hifive-revb, but should not have any
|
||||
dependencies to any particular implementation.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Makes use of GCC interrupt and weak reference/alias attributes
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html#RISC-V-Function-Attributes
|
||||
|
||||
// Vector table - not to be called.
|
||||
void riscv_mtvec_table(void) __attribute__ ((naked, section(".text.mtvec_table") ,aligned(256)));
|
||||
void riscv_stvec_table(void) __attribute__ ((naked, section(".text.stvec_table") ,aligned(256)));
|
||||
void riscv_utvec_table(void) __attribute__ ((naked, section(".text.utvec_table") ,aligned(256)));
|
||||
|
||||
// Default "NOP" implementations
|
||||
static void riscv_nop_machine(void) __attribute__ ((interrupt ("machine")) );
|
||||
static void riscv_nop_supervisor(void) __attribute__ ((interrupt ("supervisor")) );
|
||||
static void riscv_nop_user(void) __attribute__ ((interrupt ("user")) );
|
||||
|
||||
// Weak alias to the "NOP" implementations. If another function
|
||||
void riscv_mtvec_exception(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_msi(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_mti(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_mei(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_ssi(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_sti(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
|
||||
void riscv_mtvec_sei(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
|
||||
|
||||
void riscv_stvec_exception(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
|
||||
void riscv_stvec_ssi(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
|
||||
void riscv_stvec_sti(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
|
||||
void riscv_stvec_sei(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
|
||||
|
||||
void riscv_utvec_usi(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
|
||||
void riscv_utvec_uti(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
|
||||
void riscv_utvec_uei(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
|
||||
|
||||
#ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
|
||||
|
||||
void moonlight_mtvec_irq0(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq1(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq2(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq3(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq4(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq5(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq6(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq7(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq8(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq9(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq10(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq11(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq12(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq13(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq14(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
void moonlight_mtvec_irq15(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
|
||||
|
||||
#endif // #ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
|
||||
|
||||
#pragma GCC push_options
|
||||
|
||||
// Ensure the vector table is aligned.
|
||||
// The bottom 4 bits of MTVEC are ignored - so align to 16 bytes
|
||||
|
||||
// Vector table. Do not call!
|
||||
// Possible entries defined by mcause table
|
||||
// http://five-embeddev.com/riscv-isa-manual/latest/machine.html#sec:mcause
|
||||
//
|
||||
// When vectored interrupts are enabled, interrupt cause 0, which
|
||||
// corresponds to user-mode software interrupts, are vectored to the
|
||||
// same location as synchronous exceptions. This ambiguity does not
|
||||
// arise in practice, since user-mode software interrupts are either
|
||||
// disabled or delegated to user mode.
|
||||
void riscv_mtvec_table(void) {
|
||||
__asm__ volatile (
|
||||
".org riscv_mtvec_table + 0*4;"
|
||||
"jal zero,riscv_mtvec_exception;" /* 0 */
|
||||
".org riscv_mtvec_table + 1*4;"
|
||||
"jal zero,riscv_mtvec_ssi;" /* 1 */
|
||||
".org riscv_mtvec_table + 3*4;"
|
||||
"jal zero,riscv_mtvec_msi;" /* 3 */
|
||||
".org riscv_mtvec_table + 5*4;"
|
||||
"jal zero,riscv_mtvec_sti;" /* 5 */
|
||||
".org riscv_mtvec_table + 7*4;"
|
||||
"jal zero,riscv_mtvec_mti;" /* 7 */
|
||||
".org riscv_mtvec_table + 9*4;"
|
||||
"jal zero,riscv_mtvec_sei;" /* 9 */
|
||||
".org riscv_mtvec_table + 11*4;"
|
||||
"jal zero,riscv_mtvec_mei;" /* 11 */
|
||||
#ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
|
||||
".org riscv_mtvec_table + 16*4;"
|
||||
"jal moonlight_mtvec_irq0;"
|
||||
"jal moonlight_mtvec_irq1;"
|
||||
"jal moonlight_mtvec_irq2;"
|
||||
"jal moonlight_mtvec_irq3;"
|
||||
"jal moonlight_mtvec_irq4;"
|
||||
"jal moonlight_mtvec_irq5;"
|
||||
"jal moonlight_mtvec_irq6;"
|
||||
"jal moonlight_mtvec_irq7;"
|
||||
"jal moonlight_mtvec_irq8;"
|
||||
"jal moonlight_mtvec_irq9;"
|
||||
"jal moonlight_mtvec_irq10;"
|
||||
"jal moonlight_mtvec_irq11;"
|
||||
"jal moonlight_mtvec_irq12;"
|
||||
"jal moonlight_mtvec_irq13;"
|
||||
"jal moonlight_mtvec_irq14;"
|
||||
"jal moonlight_mtvec_irq15;"
|
||||
#endif
|
||||
: /* output: none */
|
||||
: /* input : immediate */
|
||||
: /* clobbers: none */
|
||||
);
|
||||
}
|
||||
// Vector table. Do not call!
|
||||
// See scause table for possible entries.
|
||||
// http://five-embeddev.com/riscv-isa-manual/latest/supervisor.html#sec:scause
|
||||
void riscv_stvec_table(void) {
|
||||
__asm__ volatile (
|
||||
".org riscv_stvec_table + 0*4;"
|
||||
"jal zero,riscv_stvec_exception;" /* 0 */
|
||||
".org riscv_stvec_table + 1*4;"
|
||||
"jal zero,riscv_stvec_ssi;" /* 1 */
|
||||
".org riscv_stvec_table + 5*4;"
|
||||
"jal zero,riscv_stvec_sti;" /* 5 */
|
||||
".org riscv_stvec_table + 9*4;"
|
||||
"jal zero,riscv_stvec_sei;" /* 9 */
|
||||
: /* output: none */
|
||||
: /* input : immediate */
|
||||
: /* clobbers: none */
|
||||
);
|
||||
}
|
||||
// Vector table. Do not call!
|
||||
void riscv_utvec_table(void) {
|
||||
__asm__ volatile (
|
||||
".org riscv_utvec_table + 0*4;"
|
||||
"jal zero,riscv_utvec_usi;" /* 0 */
|
||||
".org riscv_utvec_table + 4*4;"
|
||||
"jal zero,riscv_utvec_uti;" /* 4 */
|
||||
".org riscv_utvec_table + 8*4;"
|
||||
"jal zero,riscv_utvec_uei;" /* 8 */
|
||||
: /* output: none */
|
||||
: /* input : immediate */
|
||||
: /* clobbers: none */
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure all ISR functions are aligned.
|
||||
#pragma GCC optimize ("align-functions=4")
|
||||
|
||||
static void riscv_nop_machine(void) {
|
||||
// Nop machine mode interrupt.
|
||||
}
|
||||
static void riscv_nop_supervisor(void) {
|
||||
// Nop supervisor mode interrupt.
|
||||
}
|
||||
static void riscv_nop_user(void) {
|
||||
// Nop user mode interrupt.
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
113
port/moonlight/vector_table.h
Normal file
113
port/moonlight/vector_table.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Baremetal main program with timer interrupt.
|
||||
SPDX-License-Identifier: Unlicense
|
||||
|
||||
https://five-embeddev.com/
|
||||
|
||||
Tested with sifive-hifive-revb, but should not have any
|
||||
dependencies to any particular implementation.
|
||||
|
||||
Declarations of interrupt service routine entry points.
|
||||
|
||||
If no implementation is defined then an alias to a default "NOP"
|
||||
implementation will be linked instead.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef VECTOR_TABLE_H
|
||||
#define VECTOR_TABLE_H
|
||||
|
||||
|
||||
/** Symbol for machine mode vector table - do not call
|
||||
*/
|
||||
void riscv_mtvec_table(void) __attribute__ ((naked));
|
||||
void riscv_stvec_table(void) __attribute__ ((naked));
|
||||
void riscv_utvec_table(void) __attribute__ ((naked));
|
||||
|
||||
/** Machine mode syncronous exception handler.
|
||||
|
||||
http://five-embeddev.com/riscv-isa-manual/latest/machine.html#machine-trap-vector-base-address-register-mtvec
|
||||
|
||||
When vectored interrupts are enabled, interrupt cause 0, which
|
||||
corresponds to user-mode software interrupts, are vectored to the same
|
||||
location as synchronous exceptions. This ambiguity does not arise in
|
||||
practice, since user-mode software interrupts are either disabled or
|
||||
delegated to user mode.
|
||||
|
||||
*/
|
||||
void riscv_mtvec_exception(void) __attribute__ ((interrupt ("machine")) );
|
||||
|
||||
/** Machine mode software interrupt */
|
||||
void riscv_mtvec_msi(void) __attribute__ ((interrupt ("machine") ));
|
||||
/** Machine mode timer interrupt */
|
||||
void riscv_mtvec_mti(void) __attribute__ ((interrupt ("machine") ));
|
||||
/** Machine mode al interrupt */
|
||||
void riscv_mtvec_mei(void) __attribute__ ((interrupt ("machine") ));
|
||||
|
||||
/** Supervisor mode software interrupt */
|
||||
void riscv_mtvec_ssi(void) __attribute__ ((interrupt ("machine")) );
|
||||
/** Supervisor mode timer interrupt */
|
||||
void riscv_mtvec_sti(void) __attribute__ ((interrupt ("machine")) );
|
||||
/** Supervisor mode al interrupt */
|
||||
void riscv_mtvec_sei(void) __attribute__ ((interrupt ("machine")) );
|
||||
|
||||
/** Supervisor mode syncronous exception handler. */
|
||||
void riscv_stvec_exception(void) __attribute__ ((interrupt ("supervisor")) );
|
||||
|
||||
/** Supervisor mode software interrupt */
|
||||
void riscv_stvec_ssi(void) __attribute__ ((interrupt ("supervisor")) );
|
||||
/** Supervisor mode timer interrupt */
|
||||
void riscv_stvec_sti(void) __attribute__ ((interrupt ("supervisor")) );
|
||||
/** Supervisor mode al interrupt */
|
||||
void riscv_stvec_sei(void) __attribute__ ((interrupt ("supervisor")) );
|
||||
|
||||
/** User mode software interrupt */
|
||||
void riscv_utvec_usi(void) __attribute__ ((interrupt ("user")) );
|
||||
/** User mode timer interrupt */
|
||||
void riscv_utvec_uti(void) __attribute__ ((interrupt ("user")) );
|
||||
/** User mode al interrupt */
|
||||
void riscv_utvec_uei(void) __attribute__ ((interrupt ("user")) );
|
||||
|
||||
#ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
|
||||
|
||||
/* Platform interrupts, bits 16+ of mie, mip etc
|
||||
*/
|
||||
|
||||
/* Platform interrupt 0, bit 16 of mip/mie */
|
||||
void riscv_mtvec_platform_irq0(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 1, bit 17 of mip/mie */
|
||||
void riscv_mtvec_platform_irq1(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 2, bit 18 of mip/mie */
|
||||
void riscv_mtvec_platform_irq2(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 3, bit 19 of mip/mie */
|
||||
void riscv_mtvec_platform_irq3(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 4, bit 20 of mip/mie */
|
||||
void riscv_mtvec_platform_irq4(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 5, bit 21 of mip/mie */
|
||||
void riscv_mtvec_platform_irq5(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 6, bit 22 of mip/mie */
|
||||
void riscv_mtvec_platform_irq6(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 7, bit 23 of mip/mie */
|
||||
void riscv_mtvec_platform_irq7(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 8, bit 24 of mip/mie */
|
||||
void riscv_mtvec_platform_irq8(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 9, bit 25 of mip/mie */
|
||||
void riscv_mtvec_platform_irq9(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 10, bit 26 of mip/mie */
|
||||
void riscv_mtvec_platform_irq10(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 11, bit 27 of mip/mie */
|
||||
void riscv_mtvec_platform_irq11(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 12, bit 28 of mip/mie */
|
||||
void riscv_mtvec_platform_irq12(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 13, bit 29 of mip/mie */
|
||||
void riscv_mtvec_platform_irq13(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 14, bit 30 of mip/mie */
|
||||
void riscv_mtvec_platform_irq14(void) __attribute__ ((interrupt ("machine")) );
|
||||
/* Platform interrupt 15, bit 31 of mip/mie */
|
||||
void riscv_mtvec_platform_irq15(void) __attribute__ ((interrupt ("machine")) );
|
||||
|
||||
|
||||
#endif // #ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
|
||||
|
||||
|
||||
#endif // #ifndef VECTOR_TABLE_H
|
||||
41
port/picolibc/port.c
Normal file
41
port/picolibc/port.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
extern void uart_putc(char c);
|
||||
extern int uart_getc(void);
|
||||
|
||||
static int
|
||||
board_putc(char c, FILE *file)
|
||||
{
|
||||
(void) file; /* Not used in this function */
|
||||
uart_putc(c); /* Defined by underlying system */
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
board_getc(FILE *file)
|
||||
{
|
||||
unsigned char c;
|
||||
(void) file; /* Not used in this function */
|
||||
c = uart_getc(); /* Defined by underlying system */
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
board_flush(FILE *file)
|
||||
{
|
||||
(void) file; /* Not used in this function */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FILE __stdio = FDEV_SETUP_STREAM(board_putc, board_getc, board_flush, _FDEV_SETUP_RW);
|
||||
/*
|
||||
* Picolibc requires the application to define these
|
||||
* when using stdio in freestanding environments.
|
||||
*/
|
||||
// FILE * const stdin = NULL;
|
||||
// FILE * const stdout = NULL;
|
||||
// FILE * const stderr = NULL;
|
||||
FILE *const stdin = &__stdio;
|
||||
__strong_reference(stdin, stdout);
|
||||
__strong_reference(stdin, stderr);
|
||||
20
port/threadx/CMakeLists.txt
Normal file
20
port/threadx/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
#${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
#${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
|
||||
#${CMAKE_CURRENT_LIST_DIR}/src/platform_rand.c
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
373
port/threadx/inc/csr.h
Normal file
373
port/threadx/inc/csr.h
Normal file
@@ -0,0 +1,373 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef CSR_H
|
||||
#define CSR_H
|
||||
|
||||
|
||||
// Machine Status Register, mstatus
|
||||
#define MSTATUS_MPP_MASK (3L << 11) // previous mode.
|
||||
#define MSTATUS_MPP_M (3L << 11)
|
||||
#define MSTATUS_MPP_S (1L << 11)
|
||||
#define MSTATUS_MPP_U (0L << 11)
|
||||
#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable.
|
||||
#define MSTATUS_MPIE (1L << 7)
|
||||
#define MSTATUS_FS (1L << 13)
|
||||
|
||||
// Machine-mode Interrupt Enable
|
||||
#define MIE_MTIE (1L << 7)
|
||||
#define MIE_MSIE (1L << 3)
|
||||
#define MIE_MEIE (1L << 11)
|
||||
#define MIE_STIE (1L << 5) // supervisor timer
|
||||
#define MIE_SSIE (1L << 1)
|
||||
#define MIE_SEIE (1L << 9)
|
||||
|
||||
// Supervisor Status Register, sstatus
|
||||
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
|
||||
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
|
||||
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
|
||||
#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
|
||||
#define SSTATUS_UIE (1L << 0) // User Interrupt Enable
|
||||
#define SSTATUS_SPIE (1L << 5)
|
||||
#define SSTATUS_UPIE (1L << 4)
|
||||
|
||||
// Supervisor Interrupt Enable
|
||||
#define SIE_SEIE (1L << 9) // external
|
||||
#define SIE_STIE (1L << 5) // timer
|
||||
#define SIE_SSIE (1L << 1) // software
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint64_t riscv_get_core()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, mhartid" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_mstatus()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, mstatus" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_mstatus(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw mstatus, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// machine exception program counter, holds the
|
||||
// instruction address to which a return from
|
||||
// exception will go.
|
||||
static inline void riscv_writ_mepc(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw mepc, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_sstatus()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, sstatus" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_sstatus(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw sstatus, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Supervisor Interrupt Pending
|
||||
static inline uint64_t riscv_get_sip()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, sip" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_sip(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw sip, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_sie()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, sie" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_sie(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw sie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_mie()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, mie" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_mie(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// supervisor exception program counter, holds the
|
||||
// instruction address to which a return from
|
||||
// exception will go.
|
||||
static inline void riscv_writ_sepc(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw sepc, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_sepc()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, sepc" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine Exception Delegation
|
||||
static inline uint64_t riscv_get_medeleg()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, medeleg" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_medeleg(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw medeleg, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Machine Interrupt Delegation
|
||||
static inline uint64_t riscv_get_mideleg()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, mideleg" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_mideleg(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw mideleg, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Supervisor Trap-Vector Base Address
|
||||
// low two bits are mode.
|
||||
static inline void riscv_writ_stvec(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw stvec, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_stvec()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, stvec" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// Supervisor Timer Comparison Register
|
||||
static inline uint64_t riscv_get_stimecmp()
|
||||
{
|
||||
uint64_t x;
|
||||
// asm volatile("csrr %0, stimecmp" : "=r" (x) );
|
||||
asm volatile("csrr %0, 0x14d" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_stimecmp(uint64_t x)
|
||||
{
|
||||
// asm volatile("csrw stimecmp, %0" : : "r" (x));
|
||||
asm volatile("csrw 0x14d, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Machine Environment Configuration Register
|
||||
static inline uint64_t riscv_get_menvcfg()
|
||||
{
|
||||
uint64_t x;
|
||||
// asm volatile("csrr %0, menvcfg" : "=r" (x) );
|
||||
asm volatile("csrr %0, 0x30a" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_menvcfg(uint64_t x)
|
||||
{
|
||||
// asm volatile("csrw menvcfg, %0" : : "r" (x));
|
||||
asm volatile("csrw 0x30a, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Physical Memory Protection
|
||||
static inline void riscv_writ_pmpcfg0(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw pmpcfg0, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline void riscv_writ_pmpaddr0(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw pmpaddr0, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// supervisor address translation and protection;
|
||||
// holds the address of the page table.
|
||||
static inline void riscv_writ_satp(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw satp, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_satp()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, satp" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// Supervisor Trap Cause
|
||||
static inline uint64_t riscv_get_scause()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, scause" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// Supervisor Trap Value
|
||||
static inline uint64_t riscv_get_stval()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, stval" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode Counter-Enable
|
||||
static inline void riscv_writ_mcounteren(uint64_t x)
|
||||
{
|
||||
asm volatile("csrw mcounteren, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_mcounteren()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, mcounteren" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// machine-mode cycle counter
|
||||
static inline uint64_t riscv_get_time()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("csrr %0, time" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// enable device interrupts
|
||||
static inline void riscv_sintr_on()
|
||||
{
|
||||
uint64_t sstatus = riscv_get_sstatus();
|
||||
sstatus |= SSTATUS_SIE;
|
||||
riscv_writ_sstatus(sstatus);
|
||||
}
|
||||
|
||||
// disable device interrupts
|
||||
static inline void riscv_sintr_off()
|
||||
{
|
||||
uint64_t sstatus = riscv_get_sstatus();
|
||||
sstatus &= (~SSTATUS_SIE);
|
||||
riscv_writ_sstatus(sstatus);
|
||||
}
|
||||
|
||||
// are device interrupts enabled?
|
||||
static inline int riscv_sintr_get()
|
||||
{
|
||||
uint64_t x = riscv_get_sstatus();
|
||||
return (x & SSTATUS_SIE) != 0;
|
||||
}
|
||||
|
||||
static inline void riscv_sintr_restore(int x)
|
||||
{
|
||||
if(x)
|
||||
riscv_sintr_on();
|
||||
else
|
||||
riscv_sintr_off();
|
||||
}
|
||||
|
||||
// enable device interrupts
|
||||
static inline void riscv_mintr_on()
|
||||
{
|
||||
uint64_t mstatus = riscv_get_mstatus();
|
||||
mstatus |= MSTATUS_MIE;
|
||||
riscv_writ_mstatus(mstatus);
|
||||
}
|
||||
|
||||
// disable device interrupts
|
||||
static inline void riscv_mintr_off()
|
||||
{
|
||||
uint64_t mstatus = riscv_get_mstatus();
|
||||
mstatus &= (~MSTATUS_MIE);
|
||||
riscv_writ_mstatus(mstatus);
|
||||
}
|
||||
|
||||
// are device interrupts enabled?
|
||||
static inline int riscv_mintr_get()
|
||||
{
|
||||
uint64_t x = riscv_get_mstatus();
|
||||
return (x & MSTATUS_MIE) != 0;
|
||||
}
|
||||
|
||||
static inline void riscv_mintr_restore(int x)
|
||||
{
|
||||
if(x)
|
||||
riscv_mintr_on();
|
||||
else
|
||||
riscv_mintr_off();
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_sp()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mv %0, sp" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// read and write tp, the thread pointer, which xv6 uses to hold
|
||||
// this core's hartid (core number), the index into cpus[].
|
||||
static inline uint64_t riscv_get_tp()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mv %0, tp" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void riscv_writ_tp(uint64_t x)
|
||||
{
|
||||
asm volatile("mv tp, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64_t riscv_get_ra()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mv %0, ra" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// flush the TLB.
|
||||
static inline void sfence_vma()
|
||||
{
|
||||
// the zero, zero means flush all TLB entries.
|
||||
asm volatile("sfence.vma zero, zero");
|
||||
}
|
||||
|
||||
#endif // __ASSEMBLER__
|
||||
|
||||
#endif
|
||||
194
port/threadx/inc/nx_port.h
Normal file
194
port/threadx/inc/nx_port.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
* Copyright (c) 2025-present Eclipse ThreadX Contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** NetX Component */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* nx_port.h PIC32x/Microchip */
|
||||
/* 6.4.3 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the NetX */
|
||||
/* real-time TCP/IP function identically on a variety of different */
|
||||
/* processor architectures. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-31-2022 Zhen Kong Initial PIC32x/Microchip */
|
||||
/* Support Version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NX_PORT_H
|
||||
#define NX_PORT_H
|
||||
#include "tx_port.h"
|
||||
/* Determine if the optional NetX user define file should be used. */
|
||||
|
||||
#ifdef NX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* Yes, include the user defines in nx_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "nx_user.h"
|
||||
#endif
|
||||
|
||||
/* Default to little endian, since this is what most RISC-V targets are. */
|
||||
|
||||
#define NX_LITTLE_ENDIAN
|
||||
|
||||
/* Define various constants for the port. */
|
||||
|
||||
#ifndef NX_IP_PERIODIC_RATE
|
||||
#define NX_IP_PERIODIC_RATE \
|
||||
10 /* Default IP periodic rate of 1 second for \
|
||||
ports with 1ms timer interrupts. This \
|
||||
value may be defined instead at the \
|
||||
command line and this value will not be \
|
||||
used. */
|
||||
#endif
|
||||
|
||||
/* Define macros that swap the endian for little endian ports. */
|
||||
#ifdef NX_LITTLE_ENDIAN
|
||||
#define NX_CHANGE_ULONG_ENDIAN(arg) \
|
||||
{ \
|
||||
ULONG _i; \
|
||||
ULONG _tmp; \
|
||||
_i = (UINT)arg; \
|
||||
/* _i = A, B, C, D */ \
|
||||
_tmp = _i ^ (((_i) >> 16) | (_i << 16)); \
|
||||
/* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \
|
||||
_tmp &= 0xff00ffff; \
|
||||
/* _tmp = A^C, 0, C^A, D^B */ \
|
||||
_i = ((_i) >> 8) | (_i << 24); \
|
||||
/* _i = D, A, B, C */ \
|
||||
_i = _i ^ ((_tmp) >> 8); \
|
||||
/* _i = D, C, B, A */ \
|
||||
arg = _i; \
|
||||
}
|
||||
#define NX_CHANGE_USHORT_ENDIAN(a) (a = (((a >> 8) | (a << 8)) & 0xFFFF))
|
||||
|
||||
#ifndef htonl
|
||||
#define htonl(val) NX_CHANGE_ULONG_ENDIAN(val)
|
||||
#endif /* htonl */
|
||||
|
||||
#ifndef ntohl
|
||||
#define ntohl(val) NX_CHANGE_ULONG_ENDIAN(val)
|
||||
#endif /* ntohl */
|
||||
|
||||
#ifndef htons
|
||||
#define htons(val) NX_CHANGE_USHORT_ENDIAN(val)
|
||||
#endif /*htons */
|
||||
|
||||
#ifndef ntohs
|
||||
#define ntohs(val) NX_CHANGE_USHORT_ENDIAN(val)
|
||||
#endif /*ntohs */
|
||||
|
||||
#else
|
||||
|
||||
#define NX_CHANGE_ULONG_ENDIAN(a)
|
||||
#define NX_CHANGE_USHORT_ENDIAN(a)
|
||||
|
||||
#ifndef htons
|
||||
#define htons(val) (val)
|
||||
#endif /* htons */
|
||||
|
||||
#ifndef ntohs
|
||||
#define ntohs(val) (val)
|
||||
#endif /* ntohs */
|
||||
|
||||
#ifndef ntohl
|
||||
#define ntohl(val) (val)
|
||||
#endif
|
||||
|
||||
#ifndef htonl
|
||||
#define htonl(val) (val)
|
||||
#endif /* htonl */
|
||||
|
||||
#endif
|
||||
|
||||
/* Define several macros for the error checking shell in NetX. */
|
||||
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
|
||||
#define NX_CALLER_CHECKING_EXTERNS \
|
||||
extern TX_THREAD* _tx_thread_current_ptr; \
|
||||
extern TX_THREAD _tx_timer_thread; \
|
||||
extern volatile ULONG TX_THREAD_GET_SYSTEM_STATE();
|
||||
|
||||
#define NX_THREADS_ONLY_CALLER_CHECKING \
|
||||
if((TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == TX_NULL) || (_tx_thread_current_ptr == &_tx_timer_thread)) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_INIT_AND_THREADS_CALLER_CHECKING \
|
||||
if(((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG)0xF0F0F0F0))) || \
|
||||
(_tx_thread_current_ptr == &_tx_timer_thread)) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_NOT_ISR_CALLER_CHECKING \
|
||||
if((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG)0xF0F0F0F0))) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_THREAD_WAIT_CALLER_CHECKING \
|
||||
if((wait_option) && \
|
||||
((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#else
|
||||
|
||||
#define NX_CALLER_CHECKING_EXTERNS \
|
||||
extern TX_THREAD* _tx_thread_current_ptr; \
|
||||
extern volatile ULONG TX_THREAD_GET_SYSTEM_STATE();
|
||||
|
||||
#define NX_THREADS_ONLY_CALLER_CHECKING \
|
||||
if((TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == TX_NULL)) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_INIT_AND_THREADS_CALLER_CHECKING \
|
||||
if(((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG)0xF0F0F0F0)))) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_NOT_ISR_CALLER_CHECKING \
|
||||
if((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG)0xF0F0F0F0))) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#define NX_THREAD_WAIT_CALLER_CHECKING \
|
||||
if((wait_option) && ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \
|
||||
return (NX_CALLER_ERROR);
|
||||
|
||||
#endif
|
||||
|
||||
/* Define the version ID of NetX. This may be utilized by the application. */
|
||||
|
||||
#ifdef NX_SYSTEM_INIT
|
||||
CHAR _nx_version_id[] = "Copyright (c) 2024 Microsoft Corporation. * NetX Duo PIC32x/MPLAB Version 6.4.1 *";
|
||||
#else
|
||||
extern CHAR _nx_version_id[];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
785
port/threadx/inc/nx_user.h
Normal file
785
port/threadx/inc/nx_user.h
Normal file
@@ -0,0 +1,785 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
* Copyright (c) 2025-present Eclipse ThreadX Contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** NetX Component */
|
||||
/** */
|
||||
/** User Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* nx_user.h PORTABLE C */
|
||||
/* 6.4.3 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Yuxin Zhou, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains user defines for configuring NetX in specific */
|
||||
/* ways. This file will have an effect only if the application and */
|
||||
/* NetX library are built with NX_INCLUDE_USER_DEFINE_FILE defined. */
|
||||
/* Note that all the defines in this file may also be made on the */
|
||||
/* command line when building NetX library and application objects. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
||||
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
||||
/* resulting in version 6.1 */
|
||||
/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
|
||||
/* supported TCP/IP offload, */
|
||||
/* resulting in version 6.1.8 */
|
||||
/* 04-25-2022 Yuxin Zhou Modified comment(s), */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* 10-31-2023 Tiejun Zhou Modified comment(s), */
|
||||
/* supported random IP id, */
|
||||
/* resulting in version 6.3.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NX_USER_H
|
||||
#define NX_USER_H
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define NX_CRYPTO_HUGE_NUMBER_BITS 16
|
||||
#else
|
||||
#define NX_CRYPTO_HUGE_NUMBER_BITS 32
|
||||
#endif
|
||||
/* Define various build options for the NetX Duo port. The application should either make changes
|
||||
here by commenting or un-commenting the conditional compilation defined OR supply the defines
|
||||
though the compiler's equivalent of the -D option. */
|
||||
|
||||
/* Override various options with default values already assigned in nx_api.h or nx_port.h. Please
|
||||
also refer to nx_port.h for descriptions on each of these options. */
|
||||
|
||||
/* Configuration options for Interface */
|
||||
|
||||
/* NX_MAX_PHYSICAL_INTERFACES defines the number physical network interfaces
|
||||
present to NetX Duo IP layer. Physical interface does not include
|
||||
loopback interface. By default there is at least one physical interface
|
||||
in the system. */
|
||||
/*
|
||||
#define NX_MAX_PHYSICAL_INTERFACES 1
|
||||
*/
|
||||
|
||||
/* Defined, this option disables NetX Duo support on the 127.0.0.1 loopback interface.
|
||||
127.0.0.1 loopback interface is enabled by default. Uncomment out the follow code to disable
|
||||
the loopback interface. */
|
||||
/*
|
||||
#define NX_DISABLE_LOOPBACK_INTERFACE
|
||||
*/
|
||||
|
||||
/* If defined, the link driver is able to specify extra capability, such as checksum offloading features. */
|
||||
/*
|
||||
#define NX_ENABLE_INTERFACE_CAPABILITY
|
||||
*/
|
||||
|
||||
/* Configuration options for IP */
|
||||
|
||||
/* This defines specifies the number of ThreadX timer ticks in one second. The default value is based
|
||||
on ThreadX timer interrupt. */
|
||||
/*
|
||||
#ifdef TX_TIMER_TICKS_PER_SECOND
|
||||
#define NX_IP_PERIODIC_RATE TX_TIMER_TICKS_PER_SECOND
|
||||
#else
|
||||
#define NX_IP_PERIODIC_RATE 100
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Defined, NX_ENABLE_IP_RAW_PACKET_FILTER allows an application to install a filter
|
||||
for incoming raw packets. This feature is disabled by default. */
|
||||
/*
|
||||
#define NX_ENABLE_IP_RAW_PACKET_FILTER
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum number of RAW packets can be queued for receive. The default
|
||||
value is 20. */
|
||||
/*
|
||||
#define NX_IP_RAW_MAX_QUEUE_DEPTH 20
|
||||
*/
|
||||
|
||||
/* Defined, this option enables IP static routing feature. By default IP static routing
|
||||
feature is not compiled in. */
|
||||
/*
|
||||
#define NX_ENABLE_IP_STATIC_ROUTING
|
||||
*/
|
||||
|
||||
/* This define specifies the size of IP routing table. The default value is 8. */
|
||||
/*
|
||||
#define NX_IP_ROUTING_TABLE_SIZE 8
|
||||
*/
|
||||
|
||||
/* Defined, this option enables random IP id. By default IP id is increased by one for each packet. */
|
||||
/*
|
||||
#define NX_ENABLE_IP_ID_RANDOMIZATION
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum number of multicast groups that can be joined.
|
||||
The default value is 7. */
|
||||
/*
|
||||
#define NX_MAX_MULTICAST_GROUPS 7
|
||||
*/
|
||||
|
||||
/* Configuration options for IPv6 */
|
||||
|
||||
/* Disable IPv6 processing in NetX Duo. */
|
||||
/*
|
||||
#define NX_DISABLE_IPV6
|
||||
*/
|
||||
|
||||
/* Define the number of entries in IPv6 address pool. */
|
||||
/*
|
||||
#ifdef NX_MAX_PHYSICAL_INTERFACES
|
||||
#define NX_MAX_IPV6_ADDRESSES (NX_MAX_PHYSICAL_INTERFACES * 3)
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Do not process IPv6 ICMP Redirect Messages. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_REDIRECT_PROCESS
|
||||
*/
|
||||
|
||||
/* Do not process IPv6 Router Advertisement Messages. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_ROUTER_ADVERTISEMENT_PROCESS
|
||||
*/
|
||||
|
||||
/* Do not send IPv6 Router Solicitation Messages. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_ROUTER_SOLICITATION
|
||||
*/
|
||||
|
||||
/* Define the max number of router solicitations a host sends until a router response
|
||||
is received. If no response is received, the host concludes no router is present. */
|
||||
/*
|
||||
#define NX_ICMPV6_MAX_RTR_SOLICITATIONS 3
|
||||
*/
|
||||
|
||||
/* Define the interval between which the host sends router solicitations in seconds. */
|
||||
/*
|
||||
#define NX_ICMPV6_RTR_SOLICITATION_INTERVAL 4
|
||||
*/
|
||||
|
||||
/* Define the maximum delay for the initial router solicitation in seconds. */
|
||||
/*
|
||||
#define NX_ICMPV6_RTR_SOLICITATION_DELAY 1
|
||||
*/
|
||||
|
||||
/* Do not send ICMPv4 Error Messages. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV4_ERROR_MESSAGE
|
||||
*/
|
||||
|
||||
/* Do not send ICMPv6 Error Messages. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_ERROR_MESSAGE
|
||||
*/
|
||||
|
||||
/* Disable the Duplicate Address Detection (DAD) protocol when configuring the host IP address. */
|
||||
/*
|
||||
#define NX_DISABLE_IPV6_DAD
|
||||
*/
|
||||
|
||||
/* If defined, application is able to control whether or not to perform IPv6 stateless
|
||||
address autoconfiguration with nxd_ipv6_stateless_address_autoconfig_enable() or
|
||||
nxd_ipv6_stateless_address_autoconfig_disable() service. If defined, the system starts
|
||||
with IPv6 stateless address autoconfiguration enabled. This feature is disabled by default. */
|
||||
/*
|
||||
#define NX_IPV6_STATELESS_AUTOCONFIG_CONTROL
|
||||
*/
|
||||
|
||||
/* If enabled, application is able to install a callback function to get notified
|
||||
when an interface IPv6 address is changed. By default this feature is disabled. */
|
||||
/*
|
||||
#define NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY
|
||||
*/
|
||||
|
||||
/* Defined, this option prevents NetX Duo from removing stale (old) cache table entries
|
||||
whose timeout has not expired so are otherwise still valid) to make room for new entries
|
||||
when the table is full. Static and router entries are not purged. */
|
||||
/*
|
||||
#define NX_DISABLE_IPV6_PURGE_UNUSED_CACHE_ENTRIES
|
||||
*/
|
||||
|
||||
/* This define enables simple IPv6 multicast group join/leave function. By default
|
||||
the IPv6 multicast join/leave function is not enabled. */
|
||||
/*
|
||||
#define NX_ENABLE_IPV6_MULTICAST
|
||||
*/
|
||||
|
||||
/* Defined, Minimum Path MTU Discovery feature is enabled. */
|
||||
/*
|
||||
#define NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
|
||||
*/
|
||||
|
||||
/* Define wait interval in seconds to reset the path MTU for a destination
|
||||
table entry after decreasing it in response to a packet too big error message.
|
||||
RFC 1981 Section 5.4 states the minimum time to wait is
|
||||
5 minutes and recommends 10 minutes.
|
||||
*/
|
||||
/*
|
||||
#define NX_PATH_MTU_INCREASE_WAIT_INTERVAL 600
|
||||
*/
|
||||
|
||||
/* Configuration options for Neighbor Discovery. */
|
||||
/* Define values used for Neighbor Discovery protocol.
|
||||
The default values are suggested by RFC2461, chapter 10. */
|
||||
|
||||
/* Define the maximum number of multicast Neighbor Solicitation packets
|
||||
NetX Duo sends for a packet destination needing physical mapping
|
||||
to the IP address. */
|
||||
/*
|
||||
#define NX_MAX_MULTICAST_SOLICIT 3
|
||||
*/
|
||||
|
||||
/* Define the maximum number of unicast Neighbor Solicitation packets
|
||||
NetX Duo sends for a cache entry whose reachable time has expired
|
||||
and gone "stale". */
|
||||
/*
|
||||
#define NX_MAX_UNICAST_SOLICIT 3
|
||||
*/
|
||||
|
||||
/* Define the length of time, in seconds, that a Neighbor Cache table entry
|
||||
remains in the reachable state before it becomes state. */
|
||||
/*
|
||||
#define NX_REACHABLE_TIME 30
|
||||
*/
|
||||
|
||||
/* Define the length of time, in milliseconds, between retransmitting
|
||||
Neighbor Solicitation (NS) packets. */
|
||||
/*
|
||||
#define NX_RETRANS_TIMER 1000
|
||||
*/
|
||||
|
||||
/* Define the length of time, in seconds, for a Neighbor Cache entry
|
||||
to remain in the Delay state. This is the Delay first probe timer. */
|
||||
/*
|
||||
#define NX_DELAY_FIRST_PROBE_TIME 5
|
||||
*/
|
||||
|
||||
/* This defines specifies the maximum number of packets that can be queued while waiting for a
|
||||
Neighbor Discovery to resolve an IPv6 address. The default value is 4. */
|
||||
/*
|
||||
#define NX_ND_MAX_QUEUE_DEPTH 4
|
||||
*/
|
||||
|
||||
/* Define the maximum ICMPv6 Duplicate Address Detect Transmit . */
|
||||
/*
|
||||
#define NX_IPV6_DAD_TRANSMITS 3
|
||||
*/
|
||||
|
||||
/* Define the number of neighbor cache entries. */
|
||||
/*
|
||||
#define NX_IPV6_NEIGHBOR_CACHE_SIZE 16
|
||||
*/
|
||||
|
||||
/* Define the size of the IPv6 destination table. */
|
||||
/*
|
||||
#define NX_IPV6_DESTINATION_TABLE_SIZE 8
|
||||
*/
|
||||
|
||||
/* Define the size of the IPv6 prefix table. */
|
||||
/*
|
||||
#define NX_IPV6_PREFIX_LIST_TABLE_SIZE 8
|
||||
*/
|
||||
|
||||
/* Configuration options for IPSEC */
|
||||
|
||||
/* This define enables IPSEC in NetX Duo. */
|
||||
/*
|
||||
#define NX_IPSEC_ENABLE
|
||||
*/
|
||||
|
||||
/* Configuration options for NAT */
|
||||
|
||||
/* This define enables NAT process in NetX Duo. */
|
||||
/*
|
||||
#define NX_NAT_ENABLE
|
||||
*/
|
||||
|
||||
/* Configuration options for IGMP */
|
||||
|
||||
/* Defined, IGMP v2 support is disabled. By default NetX Duo
|
||||
is built with IGMPv2 enabled . By uncommenting this option,
|
||||
NetX Duo reverts back to IGMPv1 only. */
|
||||
/*
|
||||
#define NX_DISABLE_IGMPV2
|
||||
*/
|
||||
|
||||
/* Configuration options for ARP */
|
||||
|
||||
/* When defines, ARP reply is sent when address conflict occurs. */
|
||||
/*
|
||||
#define NX_ARP_DEFEND_BY_REPLY
|
||||
*/
|
||||
|
||||
/* To use the ARP collision handler to check for invalid ARP messages
|
||||
matching existing entries in the table (man in the middle attack),
|
||||
enable this feature. */
|
||||
/*
|
||||
#define NX_ENABLE_ARP_MAC_CHANGE_NOTIFICATION
|
||||
*/
|
||||
|
||||
/* This define specifies the number of seconds ARP entries remain valid. The default value of 0 disables
|
||||
aging of ARP entries. */
|
||||
/*
|
||||
#define NX_ARP_EXPIRATION_RATE 0
|
||||
*/
|
||||
|
||||
/* This define specifies the number of seconds between ARP retries. The default value is 10, which represents
|
||||
10 seconds. */
|
||||
/*
|
||||
#define NX_ARP_UPDATE_RATE 10
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum number of ARP retries made without an ARP response. The default
|
||||
value is 18. */
|
||||
/*
|
||||
#define NX_ARP_MAXIMUM_RETRIES 18
|
||||
*/
|
||||
|
||||
/* This defines specifies the maximum number of packets that can be queued while waiting for an ARP
|
||||
response. The default value is 4. */
|
||||
/*
|
||||
#define NX_ARP_MAX_QUEUE_DEPTH 4
|
||||
*/
|
||||
|
||||
/* Defined, this option disables entering ARP request information in the ARP cache. */
|
||||
/*
|
||||
#define NX_DISABLE_ARP_AUTO_ENTRY
|
||||
*/
|
||||
|
||||
/* Define the ARP defend interval. The default value is 10 seconds. */
|
||||
/*
|
||||
#define NX_ARP_DEFEND_INTERVAL 10
|
||||
*/
|
||||
|
||||
/* Configuration options for TCP */
|
||||
|
||||
/* This define specifies how the number of system ticks (NX_IP_PERIODIC_RATE) is divided to calculate the
|
||||
timer rate for the TCP delayed ACK processing. The default value is 5, which represents 200ms. */
|
||||
/*
|
||||
#define NX_TCP_ACK_TIMER_RATE 5
|
||||
*/
|
||||
|
||||
/* This define specifies how the number of system ticks (NX_IP_PERIODIC_RATE) is divided to calculate the
|
||||
fast TCP timer rate. The fast TCP timer is used to drive various TCP timers, including the delayed ACK
|
||||
timer. The default value is 10, which represents 100ms. */
|
||||
/*
|
||||
#define NX_TCP_FAST_TIMER_RATE 10
|
||||
*/
|
||||
|
||||
/* This define specifies how the number of system ticks (NX_IP_PERIODIC_RATE) is divided to calculate the
|
||||
timer rate for the TCP transmit retry processing. The default value is 1, which represents 1 second. */
|
||||
/*
|
||||
#define NX_TCP_TRANSMIT_TIMER_RATE 1
|
||||
*/
|
||||
|
||||
/* This define specifies how many seconds of inactivity before the keepalive timer activates. The default
|
||||
value is 7200, which represents 2 hours. */
|
||||
/*
|
||||
#define NX_TCP_KEEPALIVE_INITIAL 7200
|
||||
*/
|
||||
|
||||
/* This define specifies how many seconds between retries of the keepalive timer assuming the other side
|
||||
of the connection is not responding. The default value is 75, which represents 75 seconds between
|
||||
retries. */
|
||||
/*
|
||||
#define NX_TCP_KEEPALIVE_RETRY 75
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum packets that are out of order. The default value is 8. */
|
||||
/*
|
||||
#define NX_TCP_MAX_OUT_OF_ORDER_PACKETS 8
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum number of TCP server listen requests. The default value is 10. */
|
||||
/*
|
||||
#define NX_MAX_LISTEN_REQUESTS 10
|
||||
*/
|
||||
|
||||
/* Defined, this option enables the optional TCP keepalive timer. */
|
||||
/*
|
||||
#define NX_ENABLE_TCP_KEEPALIVE
|
||||
*/
|
||||
|
||||
/* Defined, this option enables the optional TCP immediate ACK response processing. */
|
||||
/*
|
||||
#define NX_TCP_IMMEDIATE_ACK
|
||||
*/
|
||||
|
||||
/* This define specifies the number of TCP packets to receive before sending an ACK. */
|
||||
/* The default value is 2: ack every 2 packets. */
|
||||
/*
|
||||
#define NX_TCP_ACK_EVERY_N_PACKETS 2
|
||||
*/
|
||||
|
||||
/* Automatically define NX_TCP_ACK_EVERY_N_PACKETS to 1 if NX_TCP_IMMEDIATE_ACK is defined.
|
||||
This is needed for backward compatibility. */
|
||||
#if(defined(NX_TCP_IMMEDIATE_ACK) && !defined(NX_TCP_ACK_EVERY_N_PACKETS))
|
||||
#define NX_TCP_ACK_EVERY_N_PACKETS 1
|
||||
#endif
|
||||
|
||||
/* This define specifies how many transmit retires are allowed before the connection is deemed broken.
|
||||
The default value is 10. */
|
||||
/*
|
||||
#define NX_TCP_MAXIMUM_RETRIES 10
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum depth of the TCP transmit queue before TCP send requests are
|
||||
suspended or rejected. The default value is 20, which means that a maximum of 20 packets can be in
|
||||
the transmit queue at any given time. */
|
||||
/*
|
||||
#define NX_TCP_MAXIMUM_TX_QUEUE 20
|
||||
*/
|
||||
|
||||
/* This define specifies how the retransmit timeout period changes between successive retries. If this
|
||||
value is 0, the initial retransmit timeout is the same as subsequent retransmit timeouts. If this
|
||||
value is 1, each successive retransmit is twice as long. The default value is 0. */
|
||||
/*
|
||||
#define NX_TCP_RETRY_SHIFT 0
|
||||
*/
|
||||
|
||||
/* This define specifies how many keepalive retries are allowed before the connection is deemed broken.
|
||||
The default value is 10. */
|
||||
/*
|
||||
#define NX_TCP_KEEPALIVE_RETRIES 10
|
||||
*/
|
||||
|
||||
/* Defined, this option enables the TCP window scaling feature. (RFC 1323). Default disabled. */
|
||||
/*
|
||||
#define NX_ENABLE_TCP_WINDOW_SCALING
|
||||
*/
|
||||
|
||||
/* Defined, this option disables the reset processing during disconnect when the timeout value is
|
||||
specified as NX_NO_WAIT. */
|
||||
/*
|
||||
#define NX_DISABLE_RESET_DISCONNECT
|
||||
*/
|
||||
|
||||
/* If defined, the incoming SYN packet (connection request) is checked for a minimum acceptable
|
||||
MSS for the host to accept the connection. The default minimum should be based on the host
|
||||
application packet pool payload, socket transmit queue depth and relevant application specific parameters. */
|
||||
/*
|
||||
#define NX_ENABLE_TCP_MSS_CHECK
|
||||
#define NX_TCP_MSS_MINIMUM 128
|
||||
*/
|
||||
|
||||
/* If defined, NetX Duo has a notify callback for the transmit TCP socket queue decreased from
|
||||
the maximum queue depth. */
|
||||
/*
|
||||
#define NX_ENABLE_TCP_QUEUE_DEPTH_UPDATE_NOTIFY
|
||||
*/
|
||||
|
||||
/* Defined, feature of low watermark is enabled. */
|
||||
/*
|
||||
#define NX_ENABLE_LOW_WATERMARK
|
||||
*/
|
||||
|
||||
/* Define the maximum receive queue for TCP socket. */
|
||||
/*
|
||||
#ifdef NX_ENABLE_LOW_WATERMARK
|
||||
#define NX_TCP_MAXIMUM_RX_QUEUE 20
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Configuration options for fragmentation */
|
||||
|
||||
/* Defined, this option disables both IPv4 and IPv6 fragmentation and reassembly logic. */
|
||||
/*
|
||||
#define NX_DISABLE_FRAGMENTATION
|
||||
*/
|
||||
|
||||
/* Defined, this option process IP fragmentation immediately. */
|
||||
/*
|
||||
#define NX_FRAGMENT_IMMEDIATE_ASSEMBLY
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum time of IP reassembly. The default value is 60.
|
||||
By default this option is not defined. */
|
||||
/*
|
||||
#define NX_IP_MAX_REASSEMBLY_TIME 60
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum time of IPv4 reassembly. The default value is 15.
|
||||
Note that if NX_IP_MAX_REASSEMBLY_TIME is defined, this option is automatically defined as 60.
|
||||
By default this option is not defined. */
|
||||
/*
|
||||
#define NX_IPV4_MAX_REASSEMBLY_TIME 15
|
||||
*/
|
||||
|
||||
/* This define specifies the maximum time of IPv6 reassembly. The default value is 60.
|
||||
Note that if NX_IP_MAX_REASSEMBLY_TIME is defined, this option is automatically defined as 60.
|
||||
By default this option is not defined. */
|
||||
/*
|
||||
#define NX_IPV6_MAX_REASSEMBLY_TIME 60
|
||||
*/
|
||||
|
||||
/* Configuration options for checksum */
|
||||
|
||||
/* Defined, this option disables checksum logic on received ICMPv4 packets.
|
||||
Note that if NX_DISABLE_ICMP_RX_CHECKSUM is defined, this option is
|
||||
automatically defined. By default this option is not defined.*/
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV4_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on received ICMPv6 packets.
|
||||
Note that if NX_DISABLE_ICMP_RX_CHECKSUM is defined, this option is
|
||||
automatically defined. By default this option is not defined.*/
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on received ICMPv4 or ICMPv6 packets.
|
||||
Note that if NX_DISABLE_ICMP_RX_CHECKSUM is defined, NX_DISABLE_ICMPV4_RX_CHECKSUM
|
||||
and NX_DISABLE_ICMPV6_RX_CHECKSUM are automatically defined. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMP_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted ICMPv4 packets.
|
||||
Note that if NX_DISABLE_ICMP_TX_CHECKSUM is defined, this option is
|
||||
automatically defined. By default this option is not defined.*/
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV4_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted ICMPv6 packets.
|
||||
Note that if NX_DISABLE_ICMP_TX_CHECKSUM is defined, this option is
|
||||
automatically defined. By default this option is not defined.*/
|
||||
/*
|
||||
#define NX_DISABLE_ICMPV6_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted ICMPv4 or ICMPv6 packets.
|
||||
Note that if NX_DISABLE_ICMP_TX_CHECKSUM is defined, NX_DISABLE_ICMPV4_TX_CHECKSUM
|
||||
and NX_DISABLE_ICMPV6_TX_CHECKSUM are automatically defined. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMP_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on received IP packets. This is useful if the link-layer
|
||||
has reliable checksum or CRC logic. */
|
||||
/*
|
||||
#define NX_DISABLE_IP_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted IP packets. */
|
||||
/*
|
||||
#define NX_DISABLE_IP_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on received TCP packets. */
|
||||
/*
|
||||
#define NX_DISABLE_TCP_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted TCP packets. */
|
||||
/*
|
||||
#define NX_DISABLE_TCP_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on received UDP packets. */
|
||||
|
||||
/*
|
||||
#define NX_DISABLE_UDP_RX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Defined, this option disables checksum logic on transmitted UDP packets. Note that
|
||||
IPV6 requires the UDP checksum computed for outgoing packets. If this option is
|
||||
defined, the IPv6 NetX Duo host must ensure the UDP checksum is computed elsewhere
|
||||
before the packet is transmitted. */
|
||||
/*
|
||||
#define NX_DISABLE_UDP_TX_CHECKSUM
|
||||
*/
|
||||
|
||||
/* Configuration options for statistics. */
|
||||
|
||||
/* Defined, ARP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_ARP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, IP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_IP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, ICMP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_ICMP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, IGMP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_IGMP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, packet information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_PACKET_INFO
|
||||
*/
|
||||
|
||||
/* Defined, RARP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_RARP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, TCP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_TCP_INFO
|
||||
*/
|
||||
|
||||
/* Defined, UDP information gathering is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_UDP_INFO
|
||||
*/
|
||||
|
||||
/* Configuration options for Packet Pool */
|
||||
|
||||
/* This define specifies the size of the physical packet header. The default value is 16 (based on
|
||||
a typical 16-byte Ethernet header). */
|
||||
/*
|
||||
#define NX_PHYSICAL_HEADER 16
|
||||
*/
|
||||
|
||||
/* This define specifies the size of the physical packet trailer and is typically used to reserve storage
|
||||
for things like Ethernet CRCs, etc. */
|
||||
/*
|
||||
#define NX_PHYSICAL_TRAILER 4
|
||||
*/
|
||||
|
||||
/* Defined, this option disables the addition size checking on received packets. */
|
||||
/*
|
||||
#define NX_DISABLE_RX_SIZE_CHECKING
|
||||
*/
|
||||
|
||||
/* Defined, packet debug infromation is enabled. */
|
||||
/*
|
||||
#define NX_ENABLE_PACKET_DEBUG_INFO
|
||||
*/
|
||||
|
||||
/* Defined, NX_PACKET structure is padded for alignment purpose. The default is no padding. */
|
||||
/*
|
||||
#define NX_PACKET_HEADER_PAD
|
||||
#define NX_PACKET_HEADER_PAD_SIZE 1
|
||||
*/
|
||||
|
||||
/* Defined, packet header and payload are aligned automatically by the value. The default value is sizeof(ULONG). */
|
||||
/*
|
||||
#define NX_PACKET_ALIGNMENT sizeof(ULONG)
|
||||
*/
|
||||
|
||||
/* If defined, the packet chain feature is removed. */
|
||||
/*
|
||||
#define NX_DISABLE_PACKET_CHAIN
|
||||
*/
|
||||
|
||||
/* Defined, the IP instance manages two packet pools. */
|
||||
/*
|
||||
#define NX_ENABLE_DUAL_PACKET_POOL
|
||||
*/
|
||||
|
||||
/* Configuration options for Others */
|
||||
|
||||
/* Defined, this option bypasses the basic NetX error checking. This define is typically used
|
||||
after the application is fully debugged. */
|
||||
/*
|
||||
#define NX_DISABLE_ERROR_CHECKING
|
||||
*/
|
||||
|
||||
/* Defined, this option enables deferred driver packet handling. This allows the driver to place a raw
|
||||
packet on the IP instance and have the driver's real processing routine called from the NetX internal
|
||||
IP helper thread. */
|
||||
/*
|
||||
#define NX_DRIVER_DEFERRED_PROCESSING
|
||||
*/
|
||||
|
||||
/* Defined, the source address of incoming packet is checked. The default is disabled. */
|
||||
/*
|
||||
#define NX_ENABLE_SOURCE_ADDRESS_CHECK
|
||||
*/
|
||||
|
||||
/* Defined, the extended notify support is enabled. This feature adds additional callback/notify services
|
||||
to NetX Duo API for notifying the application of socket events, such as TCP connection and disconnect
|
||||
completion. These extended notify functions are mainly used by the BSD wrapper. The default is this
|
||||
feature is disabled. */
|
||||
/*
|
||||
#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
|
||||
*/
|
||||
|
||||
/* Defined, ASSERT is disabled. The default is enabled. */
|
||||
/*
|
||||
#define NX_DISABLE_ASSERT
|
||||
*/
|
||||
|
||||
/* Define the process when assert fails. */
|
||||
/*
|
||||
#define NX_ASSERT_FAIL while (1) tx_thread_sleep(NX_WAIT_FOREVER);
|
||||
*/
|
||||
|
||||
/* Defined, the IPv4 feature is disabled. */
|
||||
/*
|
||||
#define NX_DISABLE_IPV4
|
||||
*/
|
||||
|
||||
/* Defined, the destination address of ICMP packet is checked. The default is disabled.
|
||||
An ICMP Echo Request destined to an IP broadcast or IP multicast address will be silently discarded.
|
||||
*/
|
||||
/*
|
||||
#define NX_ENABLE_ICMP_ADDRESS_CHECK
|
||||
*/
|
||||
|
||||
/* Define the max string length. The default value is 1024. */
|
||||
/*
|
||||
#define NX_MAX_STRING_LENGTH 1024
|
||||
*/
|
||||
|
||||
/* Defined, the TCP/IP offload feature is enabled.
|
||||
NX_ENABLE_INTERFACE_CAPABILITY must be defined to enable this feature. */
|
||||
/*
|
||||
#define NX_ENABLE_TCPIP_OFFLOAD
|
||||
*/
|
||||
|
||||
/* Defined, the VLAN feature is enabled.
|
||||
Note: Require driver support to use APIs from this file.
|
||||
A quick check in driver is to search for
|
||||
NX_LINK_RAW_PACKET_SEND. VLAN APIs are not supported if not found. */
|
||||
/*
|
||||
#define NX_ENABLE_VLAN
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int rand(void);
|
||||
void srand(unsigned seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NX_RAND rand
|
||||
#define NX_SRAND srand
|
||||
#endif
|
||||
279
port/threadx/inc/tx_port.h
Normal file
279
port/threadx/inc/tx_port.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define SLL32 sllw
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define LWU lwu
|
||||
#define LOG_REGBYTES 3
|
||||
#else
|
||||
#define SLL32 sll
|
||||
#define STORE sw
|
||||
#define LOAD lw
|
||||
#define LWU lw
|
||||
#define LOG_REGBYTES 2
|
||||
#endif
|
||||
#define REGBYTES (1 << LOG_REGBYTES)
|
||||
#define TX_THREAD_STACK_END_OFFSET 2*4 + 2*REGBYTES
|
||||
#define TX_THREAD_TIME_SLICE_OFFSET 3*4+ 3*REGBYTES
|
||||
|
||||
#else /*not __ASSEMBLER__ */
|
||||
|
||||
/* Include for memset. */
|
||||
#include <string.h>
|
||||
/* include for strtoul*/
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "nx_user.h"
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef int LONG;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
#define ULONG64_DEFINED
|
||||
#define ALIGN_TYPE_DEFINED
|
||||
#define ALIGN_TYPE ULONG64
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 1024 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
/* Define various constants for the ThreadX RISC-V port. */
|
||||
|
||||
#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */
|
||||
#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||
how the ThreadX library was built. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
|
||||
|
||||
/* Define the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#endif
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
#define TX_THREAD_EXTENSION_1
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#define TX_THREAD_EXTENSION_3
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
#define TX_THREAD_USER_EXTENSION
|
||||
#endif
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||
access of critical kernel information. The restore interrupt macro must
|
||||
restore the interrupt posture of the running thread prior to the value
|
||||
present prior to the disable macro. In most cases, the save area macro
|
||||
is used to define a local function save area for the disable and restore
|
||||
macros. */
|
||||
|
||||
#ifdef TX_DISABLE_INLINE
|
||||
|
||||
ULONG64 _tx_thread_interrupt_control(unsigned int new_posture);
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA register ULONG64 interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
|
||||
|
||||
#else
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA ULONG64 interrupt_save;
|
||||
/* Atomically read mstatus into interrupt_save and clear bit 3 of mstatus. */
|
||||
#define TX_DISABLE \
|
||||
{ __asm__("csrrci %0, mstatus, 0x08" : "=r"(interrupt_save) :); };
|
||||
/* We only care about mstatus.mie (bit 3), so mask interrupt_save and write to mstatus. */
|
||||
#define TX_RESTORE \
|
||||
{ \
|
||||
register ULONG64 __tempmask = interrupt_save & 0x08; \
|
||||
__asm__("csrrs x0, mstatus, %0 \n\t" : : "r"(__tempmask) :); \
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||
|
||||
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] = "Copyright (c) 2024 Microsoft Corporation. * ThreadX RISC-V64/GNU Version 6.4.2 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
#endif /*not __ASSEMBLER__ */
|
||||
#endif
|
||||
163
port/threadx/src/tx_initialize_low_level.S
Normal file
163
port/threadx/src/tx_initialize_low_level.S
Normal file
@@ -0,0 +1,163 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
#include "csr.h"
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* trap_entry RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Jer6y , luojun@oerv.isrc.iscas.ac.cn */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for riscv processor trap handle */
|
||||
/* It will do the contex save and call c trap_handler and do contex */
|
||||
/* load */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* trap_handler */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* hardware exception */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-25-2024 Jerry Luo */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
.global trap_entry
|
||||
.extern _tx_thread_context_restore
|
||||
trap_entry:
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, -65*REGBYTES // Allocate space for all registers - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, -32*REGBYTES // Allocate space for all registers - without floating point enabled
|
||||
#endif
|
||||
|
||||
STORE x1, 28*REGBYTES(sp) // Store RA, 28*REGBYTES(because call will override ra [ra is a calle register in riscv])
|
||||
|
||||
call _tx_thread_context_save
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
csrr a2, mtval
|
||||
addi sp, sp, -8
|
||||
STORE ra, 0(sp)
|
||||
call trap_handler
|
||||
LOAD ra, 0(sp)
|
||||
addi sp, sp, 8
|
||||
call _tx_thread_context_restore
|
||||
// it will nerver return
|
||||
.weak trap_handler
|
||||
trap_handler:
|
||||
1:
|
||||
j 1b
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_initialize_low_level(VOID)
|
||||
*/
|
||||
.global _tx_initialize_low_level
|
||||
.weak _tx_initialize_low_level
|
||||
.extern _end
|
||||
.extern board_init
|
||||
_tx_initialize_low_level:
|
||||
STORE sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
||||
|
||||
la t0, _end // Pickup first free address
|
||||
STORE t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||
li t0, MSTATUS_MIE
|
||||
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
||||
li t0, (MSTATUS_MPP_M | MSTATUS_MPIE )
|
||||
csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit
|
||||
li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
|
||||
csrrs zero, mie, t0 // set mie
|
||||
#ifdef __riscv_flen
|
||||
li t0, MSTATUS_FS
|
||||
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
||||
fscsr x0
|
||||
#endif
|
||||
addi sp, sp, -8
|
||||
STORE ra, 0(sp)
|
||||
call board_init
|
||||
LOAD ra, 0(sp)
|
||||
addi sp, sp, 8
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
ret
|
||||
382
port/threadx/src/tx_thread_context_restore.S
Normal file
382
port/threadx/src/tx_thread_context_restore.S
Normal file
@@ -0,0 +1,382 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the interrupt context if it is processing a */
|
||||
/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||
/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||
/* if no thread was running, the function returns to the scheduler. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_restore(VOID)
|
||||
{ */
|
||||
.global _tx_thread_context_restore
|
||||
_tx_thread_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
csrci mstatus, 0x08 // Disable interrupts
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
call _tx_execution_isr_exit // Call the ISR execution exit function
|
||||
#endif
|
||||
|
||||
/* Determine if interrupts are nested. */
|
||||
/* if (--_tx_thread_system_state)
|
||||
{ */
|
||||
|
||||
la t0, _tx_thread_system_state // Pickup addr of nested interrupt count
|
||||
lw t1, 0(t0) // Pickup nested interrupt count
|
||||
addi t1, t1, -1 // Decrement the nested interrupt counter
|
||||
sw t1, 0(t0) // Store new nested count
|
||||
beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
/* Recover floating point registers. */
|
||||
#if defined(__riscv_float_abi_single)
|
||||
flw f0, 31*REGBYTES(sp) // Recover ft0
|
||||
flw f1, 32*REGBYTES(sp) // Recover ft1
|
||||
flw f2, 33*REGBYTES(sp) // Recover ft2
|
||||
flw f3, 34*REGBYTES(sp) // Recover ft3
|
||||
flw f4, 35*REGBYTES(sp) // Recover ft4
|
||||
flw f5, 36*REGBYTES(sp) // Recover ft5
|
||||
flw f6, 37*REGBYTES(sp) // Recover ft6
|
||||
flw f7, 38*REGBYTES(sp) // Recover ft7
|
||||
flw f10,41*REGBYTES(sp) // Recover fa0
|
||||
flw f11,42*REGBYTES(sp) // Recover fa1
|
||||
flw f12,43*REGBYTES(sp) // Recover fa2
|
||||
flw f13,44*REGBYTES(sp) // Recover fa3
|
||||
flw f14,45*REGBYTES(sp) // Recover fa4
|
||||
flw f15,46*REGBYTES(sp) // Recover fa5
|
||||
flw f16,47*REGBYTES(sp) // Recover fa6
|
||||
flw f17,48*REGBYTES(sp) // Recover fa7
|
||||
flw f28,59*REGBYTES(sp) // Recover ft8
|
||||
flw f29,60*REGBYTES(sp) // Recover ft9
|
||||
flw f30,61*REGBYTES(sp) // Recover ft10
|
||||
flw f31,62*REGBYTES(sp) // Recover ft11
|
||||
lw t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fld f0, 31*REGBYTES(sp) // Recover ft0
|
||||
fld f1, 32*REGBYTES(sp) // Recover ft1
|
||||
fld f2, 33*REGBYTES(sp) // Recover ft2
|
||||
fld f3, 34*REGBYTES(sp) // Recover ft3
|
||||
fld f4, 35*REGBYTES(sp) // Recover ft4
|
||||
fld f5, 36*REGBYTES(sp) // Recover ft5
|
||||
fld f6, 37*REGBYTES(sp) // Recover ft6
|
||||
fld f7, 38*REGBYTES(sp) // Recover ft7
|
||||
fld f10,41*REGBYTES(sp) // Recover fa0
|
||||
fld f11,42*REGBYTES(sp) // Recover fa1
|
||||
fld f12,43*REGBYTES(sp) // Recover fa2
|
||||
fld f13,44*REGBYTES(sp) // Recover fa3
|
||||
fld f14,45*REGBYTES(sp) // Recover fa4
|
||||
fld f15,46*REGBYTES(sp) // Recover fa5
|
||||
fld f16,47*REGBYTES(sp) // Recover fa6
|
||||
fld f17,48*REGBYTES(sp) // Recover fa7
|
||||
fld f28,59*REGBYTES(sp) // Recover ft8
|
||||
fld f29,60*REGBYTES(sp) // Recover ft9
|
||||
fld f30,61*REGBYTES(sp) // Recover ft10
|
||||
fld f31,62*REGBYTES(sp) // Recover ft11
|
||||
LOAD t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#endif
|
||||
|
||||
/* Recover standard registers. */
|
||||
|
||||
/* Restore registers,
|
||||
Skip global pointer because that does not change.
|
||||
Also skip the saved registers since they have been restored by any function we called,
|
||||
except s0 since we use it ourselves. */
|
||||
|
||||
LOAD t0, 30*REGBYTES(sp) // Recover mepc
|
||||
csrw mepc, t0 // Setup mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
LOAD x5, 19*REGBYTES(sp) // Recover t0
|
||||
LOAD x6, 18*REGBYTES(sp) // Recover t1
|
||||
LOAD x7, 17*REGBYTES(sp) // Recover t2
|
||||
LOAD x8, 12*REGBYTES(sp) // Recover s0
|
||||
LOAD x10, 27*REGBYTES(sp) // Recover a0
|
||||
LOAD x11, 26*REGBYTES(sp) // Recover a1
|
||||
LOAD x12, 25*REGBYTES(sp) // Recover a2
|
||||
LOAD x13, 24*REGBYTES(sp) // Recover a3
|
||||
LOAD x14, 23*REGBYTES(sp) // Recover a4
|
||||
LOAD x15, 22*REGBYTES(sp) // Recover a5
|
||||
LOAD x16, 21*REGBYTES(sp) // Recover a6
|
||||
LOAD x17, 20*REGBYTES(sp) // Recover a7
|
||||
LOAD x28, 16*REGBYTES(sp) // Recover t3
|
||||
LOAD x29, 15*REGBYTES(sp) // Recover t4
|
||||
LOAD x30, 14*REGBYTES(sp) // Recover t5
|
||||
LOAD x31, 13*REGBYTES(sp) // Recover t6
|
||||
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point enabled
|
||||
#endif
|
||||
mret // Return to point of interrupt
|
||||
|
||||
/* } */
|
||||
_tx_thread_not_nested_restore:
|
||||
/* Determine if a thread was interrupted and no preemption is required. */
|
||||
/* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||
|| (_tx_thread_preempt_disable))
|
||||
{ */
|
||||
|
||||
LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer
|
||||
beqz t1, _tx_thread_idle_system_restore // If NULL, idle system restore
|
||||
|
||||
LOAD t2, _tx_thread_preempt_disable // Pickup preempt disable flag
|
||||
bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread
|
||||
|
||||
LOAD t2, _tx_thread_execute_ptr // Pickup thread execute pointer
|
||||
bne t1, t2, _tx_thread_preempt_restore // If higher-priority thread is ready, preempt
|
||||
|
||||
|
||||
_tx_thread_no_preempt_restore:
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
/* SP = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
LOAD sp, 2*REGBYTES(t1) // Switch back to thread's stack
|
||||
|
||||
/* Recover floating point registers. */
|
||||
#if defined(__riscv_float_abi_single)
|
||||
flw f0, 31*REGBYTES(sp) // Recover ft0
|
||||
flw f1, 32*REGBYTES(sp) // Recover ft1
|
||||
flw f2, 33*REGBYTES(sp) // Recover ft2
|
||||
flw f3, 34*REGBYTES(sp) // Recover ft3
|
||||
flw f4, 35*REGBYTES(sp) // Recover ft4
|
||||
flw f5, 36*REGBYTES(sp) // Recover ft5
|
||||
flw f6, 37*REGBYTES(sp) // Recover ft6
|
||||
flw f7, 38*REGBYTES(sp) // Recover ft7
|
||||
flw f10,41*REGBYTES(sp) // Recover fa0
|
||||
flw f11,42*REGBYTES(sp) // Recover fa1
|
||||
flw f12,43*REGBYTES(sp) // Recover fa2
|
||||
flw f13,44*REGBYTES(sp) // Recover fa3
|
||||
flw f14,45*REGBYTES(sp) // Recover fa4
|
||||
flw f15,46*REGBYTES(sp) // Recover fa5
|
||||
flw f16,47*REGBYTES(sp) // Recover fa6
|
||||
flw f17,48*REGBYTES(sp) // Recover fa7
|
||||
flw f28,59*REGBYTES(sp) // Recover ft8
|
||||
flw f29,60*REGBYTES(sp) // Recover ft9
|
||||
flw f30,61*REGBYTES(sp) // Recover ft10
|
||||
flw f31,62*REGBYTES(sp) // Recover ft11
|
||||
lw t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fld f0, 31*REGBYTES(sp) // Recover ft0
|
||||
fld f1, 32*REGBYTES(sp) // Recover ft1
|
||||
fld f2, 33*REGBYTES(sp) // Recover ft2
|
||||
fld f3, 34*REGBYTES(sp) // Recover ft3
|
||||
fld f4, 35*REGBYTES(sp) // Recover ft4
|
||||
fld f5, 36*REGBYTES(sp) // Recover ft5
|
||||
fld f6, 37*REGBYTES(sp) // Recover ft6
|
||||
fld f7, 38*REGBYTES(sp) // Recover ft7
|
||||
fld f10,41*REGBYTES(sp) // Recover fa0
|
||||
fld f11,42*REGBYTES(sp) // Recover fa1
|
||||
fld f12,43*REGBYTES(sp) // Recover fa2
|
||||
fld f13,44*REGBYTES(sp) // Recover fa3
|
||||
fld f14,45*REGBYTES(sp) // Recover fa4
|
||||
fld f15,46*REGBYTES(sp) // Recover fa5
|
||||
fld f16,47*REGBYTES(sp) // Recover fa6
|
||||
fld f17,48*REGBYTES(sp) // Recover fa7
|
||||
fld f28,59*REGBYTES(sp) // Recover ft8
|
||||
fld f29,60*REGBYTES(sp) // Recover ft9
|
||||
fld f30,61*REGBYTES(sp) // Recover ft10
|
||||
fld f31,62*REGBYTES(sp) // Recover ft11
|
||||
LOAD t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#endif
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
/* Recover standard registers. */
|
||||
/* Restore registers,
|
||||
Skip global pointer because that does not change */
|
||||
|
||||
LOAD t0, 30*REGBYTES(sp) // Recover mepc
|
||||
csrw mepc, t0 // Setup mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
LOAD x5, 19*REGBYTES(sp) // Recover t0
|
||||
LOAD x6, 18*REGBYTES(sp) // Recover t1
|
||||
LOAD x7, 17*REGBYTES(sp) // Recover t2
|
||||
LOAD x8, 12*REGBYTES(sp) // Recover s0
|
||||
LOAD x10, 27*REGBYTES(sp) // Recover a0
|
||||
LOAD x11, 26*REGBYTES(sp) // Recover a1
|
||||
LOAD x12, 25*REGBYTES(sp) // Recover a2
|
||||
LOAD x13, 24*REGBYTES(sp) // Recover a3
|
||||
LOAD x14, 23*REGBYTES(sp) // Recover a4
|
||||
LOAD x15, 22*REGBYTES(sp) // Recover a5
|
||||
LOAD x16, 21*REGBYTES(sp) // Recover a6
|
||||
LOAD x17, 20*REGBYTES(sp) // Recover a7
|
||||
LOAD x28, 16*REGBYTES(sp) // Recover t3
|
||||
LOAD x29, 15*REGBYTES(sp) // Recover t4
|
||||
LOAD x30, 14*REGBYTES(sp) // Recover t5
|
||||
LOAD x31, 13*REGBYTES(sp) // Recover t6
|
||||
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point enabled
|
||||
#endif
|
||||
mret // Return to point of interrupt
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
_tx_thread_preempt_restore:
|
||||
/* Instead of directly activating the thread again, ensure we save the
|
||||
entire stack frame by saving the remaining registers. */
|
||||
|
||||
LOAD t0, 2*REGBYTES(t1) // Pickup thread's stack pointer
|
||||
ori t3, x0, 1 // Build interrupt stack type
|
||||
STORE t3, 0(t0) // Store stack type
|
||||
|
||||
/* Store floating point preserved registers. */
|
||||
#ifdef __riscv_float_abi_single
|
||||
fsw f8, 39*REGBYTES(t0) // Store fs0
|
||||
fsw f9, 40*REGBYTES(t0) // Store fs1
|
||||
fsw f18, 49*REGBYTES(t0) // Store fs2
|
||||
fsw f19, 50*REGBYTES(t0) // Store fs3
|
||||
fsw f20, 51*REGBYTES(t0) // Store fs4
|
||||
fsw f21, 52*REGBYTES(t0) // Store fs5
|
||||
fsw f22, 53*REGBYTES(t0) // Store fs6
|
||||
fsw f23, 54*REGBYTES(t0) // Store fs7
|
||||
fsw f24, 55*REGBYTES(t0) // Store fs8
|
||||
fsw f25, 56*REGBYTES(t0) // Store fs9
|
||||
fsw f26, 57*REGBYTES(t0) // Store fs10
|
||||
fsw f27, 58*REGBYTES(t0) // Store fs11
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fsd f8, 39*REGBYTES(t0) // Store fs0
|
||||
fsd f9, 40*REGBYTES(t0) // Store fs1
|
||||
fsd f18, 49*REGBYTES(t0) // Store fs2
|
||||
fsd f19, 50*REGBYTES(t0) // Store fs3
|
||||
fsd f20, 51*REGBYTES(t0) // Store fs4
|
||||
fsd f21, 52*REGBYTES(t0) // Store fs5
|
||||
fsd f22, 53*REGBYTES(t0) // Store fs6
|
||||
fsd f23, 54*REGBYTES(t0) // Store fs7
|
||||
fsd f24, 55*REGBYTES(t0) // Store fs8
|
||||
fsd f25, 56*REGBYTES(t0) // Store fs9
|
||||
fsd f26, 57*REGBYTES(t0) // Store fs10
|
||||
fsd f27, 58*REGBYTES(t0) // Store fs11
|
||||
#endif
|
||||
|
||||
/* Store standard preserved registers. */
|
||||
|
||||
STORE x9, 11*REGBYTES(t0) // Store s1
|
||||
STORE x18, 10*REGBYTES(t0) // Store s2
|
||||
STORE x19, 9*REGBYTES(t0) // Store s3
|
||||
STORE x20, 8*REGBYTES(t0) // Store s4
|
||||
STORE x21, 7*REGBYTES(t0) // Store s5
|
||||
STORE x22, 6*REGBYTES(t0) // Store s6
|
||||
STORE x23, 5*REGBYTES(t0) // Store s7
|
||||
STORE x24, 4*REGBYTES(t0) // Store s8
|
||||
STORE x25, 3*REGBYTES(t0) // Store s9
|
||||
STORE x26, 2*REGBYTES(t0) // Store s10
|
||||
STORE x27, 1*REGBYTES(t0) // Store s11
|
||||
// Note: s0 is already stored!
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
la t0, _tx_timer_time_slice // Pickup time slice variable address
|
||||
lw t2, 0(t0) // Pickup time slice
|
||||
beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice
|
||||
_tx_timer_time_slice = 0; */
|
||||
|
||||
sw t2, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time slice
|
||||
sw x0, 0(t0) // Clear global time slice
|
||||
|
||||
|
||||
/* } */
|
||||
_tx_thread_dont_save_ts:
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
/* Return to the scheduler. */
|
||||
/* _tx_thread_schedule(); */
|
||||
|
||||
STORE x0, _tx_thread_current_ptr, t0 // Clear current thread pointer*/
|
||||
/* } */
|
||||
|
||||
_tx_thread_idle_system_restore:
|
||||
/* Just return back to the scheduler! */
|
||||
j _tx_thread_schedule // Return to scheduler
|
||||
|
||||
/* } */
|
||||
283
port/threadx/src/tx_thread_context_save.S
Normal file
283
port/threadx/src/tx_thread_context_save.S
Normal file
@@ -0,0 +1,283 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function saves the context of an executing thread in the */
|
||||
/* beginning of interrupt processing. The function also ensures that */
|
||||
/* the system stack is used upon return to the calling ISR. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_save(VOID)
|
||||
{ */
|
||||
.global _tx_thread_context_save
|
||||
_tx_thread_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that interrupts are locked
|
||||
out and the interrupt stack fame has been allocated and x1 (ra) has
|
||||
been saved on the stack. */
|
||||
|
||||
STORE t0, 19*REGBYTES(sp) // First store t0 and t1
|
||||
STORE t1, 18*REGBYTES(sp)
|
||||
|
||||
la t0, _tx_thread_system_state // Pickup address of system state
|
||||
lw t1, 0(t0) // Pickup system state
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++)
|
||||
{ */
|
||||
beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition
|
||||
addi t1, t1, 1 // Increment the interrupt counter
|
||||
sw t1, 0(t0) // Store the interrupt counter
|
||||
|
||||
/* Nested interrupt condition.
|
||||
Save the reset of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
STORE x7, 17*REGBYTES(sp) // Store t2
|
||||
STORE x8, 12*REGBYTES(sp) // Store s0
|
||||
STORE x10, 27*REGBYTES(sp) // Store a0
|
||||
STORE x11, 26*REGBYTES(sp) // Store a1
|
||||
STORE x12, 25*REGBYTES(sp) // Store a2
|
||||
STORE x13, 24*REGBYTES(sp) // Store a3
|
||||
STORE x14, 23*REGBYTES(sp) // Store a4
|
||||
STORE x15, 22*REGBYTES(sp) // Store a5
|
||||
STORE x16, 21*REGBYTES(sp) // Store a6
|
||||
STORE x17, 20*REGBYTES(sp) // Store a7
|
||||
STORE x28, 16*REGBYTES(sp) // Store t3
|
||||
STORE x29, 15*REGBYTES(sp) // Store t4
|
||||
STORE x30, 14*REGBYTES(sp) // Store t5
|
||||
STORE x31, 13*REGBYTES(sp) // Store t6
|
||||
csrr t0, mepc // Load exception program counter
|
||||
STORE t0, 30*REGBYTES(sp) // Save it on the stack
|
||||
|
||||
/* Save floating point scratch registers. */
|
||||
#if defined(__riscv_float_abi_single)
|
||||
fsw f0, 31*REGBYTES(sp) // Store ft0
|
||||
fsw f1, 32*REGBYTES(sp) // Store ft1
|
||||
fsw f2, 33*REGBYTES(sp) // Store ft2
|
||||
fsw f3, 34*REGBYTES(sp) // Store ft3
|
||||
fsw f4, 35*REGBYTES(sp) // Store ft4
|
||||
fsw f5, 36*REGBYTES(sp) // Store ft5
|
||||
fsw f6, 37*REGBYTES(sp) // Store ft6
|
||||
fsw f7, 38*REGBYTES(sp) // Store ft7
|
||||
fsw f10,41*REGBYTES(sp) // Store fa0
|
||||
fsw f11,42*REGBYTES(sp) // Store fa1
|
||||
fsw f12,43*REGBYTES(sp) // Store fa2
|
||||
fsw f13,44*REGBYTES(sp) // Store fa3
|
||||
fsw f14,45*REGBYTES(sp) // Store fa4
|
||||
fsw f15,46*REGBYTES(sp) // Store fa5
|
||||
fsw f16,47*REGBYTES(sp) // Store fa6
|
||||
fsw f17,48*REGBYTES(sp) // Store fa7
|
||||
fsw f28,59*REGBYTES(sp) // Store ft8
|
||||
fsw f29,60*REGBYTES(sp) // Store ft9
|
||||
fsw f30,61*REGBYTES(sp) // Store ft10
|
||||
fsw f31,62*REGBYTES(sp) // Store ft11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 63*REGBYTES(sp) // Store fcsr
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fsd f0, 31*REGBYTES(sp) // Store ft0
|
||||
fsd f1, 32*REGBYTES(sp) // Store ft1
|
||||
fsd f2, 33*REGBYTES(sp) // Store ft2
|
||||
fsd f3, 34*REGBYTES(sp) // Store ft3
|
||||
fsd f4, 35*REGBYTES(sp) // Store ft4
|
||||
fsd f5, 36*REGBYTES(sp) // Store ft5
|
||||
fsd f6, 37*REGBYTES(sp) // Store ft6
|
||||
fsd f7, 38*REGBYTES(sp) // Store ft7
|
||||
fsd f10,41*REGBYTES(sp) // Store fa0
|
||||
fsd f11,42*REGBYTES(sp) // Store fa1
|
||||
fsd f12,43*REGBYTES(sp) // Store fa2
|
||||
fsd f13,44*REGBYTES(sp) // Store fa3
|
||||
fsd f14,45*REGBYTES(sp) // Store fa4
|
||||
fsd f15,46*REGBYTES(sp) // Store fa5
|
||||
fsd f16,47*REGBYTES(sp) // Store fa6
|
||||
fsd f17,48*REGBYTES(sp) // Store fa7
|
||||
fsd f28,59*REGBYTES(sp) // Store ft8
|
||||
fsd f29,60*REGBYTES(sp) // Store ft9
|
||||
fsd f30,61*REGBYTES(sp) // Store ft10
|
||||
fsd f31,62*REGBYTES(sp) // Store ft11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 63*REGBYTES(sp) // Store fcsr
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
call _tx_execution_isr_enter // Call the ISR execution enter function
|
||||
#endif
|
||||
|
||||
ret // Return to calling ISR
|
||||
|
||||
_tx_thread_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr)
|
||||
{ */
|
||||
addi t1, t1, 1 // Increment the interrupt counter
|
||||
sw t1, 0(t0) // Store the interrupt counter
|
||||
|
||||
/* Not nested: Find the user thread that was running and load our SP */
|
||||
|
||||
LOAD t0, _tx_thread_current_ptr // Pickup current thread pointer
|
||||
beqz t0, _tx_thread_idle_system_save // If NULL, idle system was interrupted
|
||||
|
||||
/* Save the standard scratch registers. */
|
||||
|
||||
STORE x7, 17*REGBYTES(sp) // Store t2
|
||||
STORE x8, 12*REGBYTES(sp) // Store s0
|
||||
STORE x10, 27*REGBYTES(sp) // Store a0
|
||||
STORE x11, 26*REGBYTES(sp) // Store a1
|
||||
STORE x12, 25*REGBYTES(sp) // Store a2
|
||||
STORE x13, 24*REGBYTES(sp) // Store a3
|
||||
STORE x14, 23*REGBYTES(sp) // Store a4
|
||||
STORE x15, 22*REGBYTES(sp) // Store a5
|
||||
STORE x16, 21*REGBYTES(sp) // Store a6
|
||||
STORE x17, 20*REGBYTES(sp) // Store a7
|
||||
STORE x28, 16*REGBYTES(sp) // Store t3
|
||||
STORE x29, 15*REGBYTES(sp) // Store t4
|
||||
STORE x30, 14*REGBYTES(sp) // Store t5
|
||||
STORE x31, 13*REGBYTES(sp) // Store t6
|
||||
|
||||
csrr t0, mepc // Load exception program counter
|
||||
STORE t0, 30*REGBYTES(sp) // Save it on the stack
|
||||
|
||||
/* Save floating point scratch registers. */
|
||||
#if defined(__riscv_float_abi_single)
|
||||
fsw f0, 31*REGBYTES(sp) // Store ft0
|
||||
fsw f1, 32*REGBYTES(sp) // Store ft1
|
||||
fsw f2, 33*REGBYTES(sp) // Store ft2
|
||||
fsw f3, 34*REGBYTES(sp) // Store ft3
|
||||
fsw f4, 35*REGBYTES(sp) // Store ft4
|
||||
fsw f5, 36*REGBYTES(sp) // Store ft5
|
||||
fsw f6, 37*REGBYTES(sp) // Store ft6
|
||||
fsw f7, 38*REGBYTES(sp) // Store ft7
|
||||
fsw f10,41*REGBYTES(sp) // Store fa0
|
||||
fsw f11,42*REGBYTES(sp) // Store fa1
|
||||
fsw f12,43*REGBYTES(sp) // Store fa2
|
||||
fsw f13,44*REGBYTES(sp) // Store fa3
|
||||
fsw f14,45*REGBYTES(sp) // Store fa4
|
||||
fsw f15,46*REGBYTES(sp) // Store fa5
|
||||
fsw f16,47*REGBYTES(sp) // Store fa6
|
||||
fsw f17,48*REGBYTES(sp) // Store fa7
|
||||
fsw f28,59*REGBYTES(sp) // Store ft8
|
||||
fsw f29,60*REGBYTES(sp) // Store ft9
|
||||
fsw f30,61*REGBYTES(sp) // Store ft10
|
||||
fsw f31,62*REGBYTES(sp) // Store ft11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 63*REGBYTES(sp) // Store fcsr
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fsd f0, 31*REGBYTES(sp) // Store ft0
|
||||
fsd f1, 32*REGBYTES(sp) // Store ft1
|
||||
fsd f2, 33*REGBYTES(sp) // Store ft2
|
||||
fsd f3, 34*REGBYTES(sp) // Store ft3
|
||||
fsd f4, 35*REGBYTES(sp) // Store ft4
|
||||
fsd f5, 36*REGBYTES(sp) // Store ft5
|
||||
fsd f6, 37*REGBYTES(sp) // Store ft6
|
||||
fsd f7, 38*REGBYTES(sp) // Store ft7
|
||||
fsd f10,41*REGBYTES(sp) // Store fa0
|
||||
fsd f11,42*REGBYTES(sp) // Store fa1
|
||||
fsd f12,43*REGBYTES(sp) // Store fa2
|
||||
fsd f13,44*REGBYTES(sp) // Store fa3
|
||||
fsd f14,45*REGBYTES(sp) // Store fa4
|
||||
fsd f15,46*REGBYTES(sp) // Store fa5
|
||||
fsd f16,47*REGBYTES(sp) // Store fa6
|
||||
fsd f17,48*REGBYTES(sp) // Store fa7
|
||||
fsd f28,59*REGBYTES(sp) // Store ft8
|
||||
fsd f29,60*REGBYTES(sp) // Store ft9
|
||||
fsd f30,61*REGBYTES(sp) // Store ft10
|
||||
fsd f31,62*REGBYTES(sp) // Store ft11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 63*REGBYTES(sp) // Store fcsr
|
||||
#endif
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
LOAD t1, _tx_thread_current_ptr // Pickup current thread pointer
|
||||
STORE sp, 2*REGBYTES(t1) // Save stack pointer
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
/* _tx_execution_isr_enter is called with thread stack pointer */
|
||||
call _tx_execution_isr_enter // Call the ISR execution enter function
|
||||
#endif
|
||||
|
||||
|
||||
LOAD sp, _tx_thread_system_stack_ptr // Switch to system stack
|
||||
ret // Return to calling ISR
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
|
||||
_tx_thread_idle_system_save:
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
call _tx_execution_isr_enter // Call the ISR execution enter function
|
||||
#endif
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
/* }
|
||||
} */
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, 32*REGBYTES // Recover the reserved stack space
|
||||
#endif
|
||||
ret // Return to calling ISR
|
||||
81
port/threadx/src/tx_thread_interrupt_control.S
Normal file
81
port/threadx/src/tx_thread_interrupt_control.S
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
RETURN_MASK = 0x000000000000000F
|
||||
SET_SR_MASK = 0xFFFFFFFFFFFFFFF0
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for changing the interrupt lockout */
|
||||
/* posture of the system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
{ */
|
||||
.global _tx_thread_interrupt_control
|
||||
_tx_thread_interrupt_control:
|
||||
/* Pickup current interrupt lockout posture. */
|
||||
|
||||
csrr t0, mstatus
|
||||
mv t1, t0 // Save original mstatus for return
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
li t2, SET_SR_MASK // Build set SR mask
|
||||
and t0, t0, t2 // Isolate interrupt lockout bits
|
||||
or t0, t0, a0 // Put new lockout bits in
|
||||
csrw mstatus, t0
|
||||
andi a0, t1, RETURN_MASK // Return original mstatus.
|
||||
ret
|
||||
/* } */
|
||||
305
port/threadx/src/tx_thread_schedule.S
Normal file
305
port/threadx/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,305 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_schedule(VOID)
|
||||
{ */
|
||||
.global _tx_thread_schedule
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* Enable interrupts. */
|
||||
csrsi mstatus, 0x08 // Enable interrupts
|
||||
|
||||
/* Wait for a thread to execute. */
|
||||
/* do
|
||||
{ */
|
||||
|
||||
la t0, _tx_thread_execute_ptr // Pickup address of execute ptr
|
||||
_tx_thread_schedule_loop:
|
||||
LOAD t1, 0(t0) // Pickup next thread to execute
|
||||
beqz t1, _tx_thread_schedule_loop // If NULL, wait for thread to execute
|
||||
|
||||
/* }
|
||||
while(_tx_thread_execute_ptr == TX_NULL); */
|
||||
|
||||
/* Yes! We have a thread to execute. Lockout interrupts and
|
||||
transfer control to it. */
|
||||
csrci mstatus, 0x08 // Lockout interrupts
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = _tx_thread_execute_ptr; */
|
||||
|
||||
la t0, _tx_thread_current_ptr // Pickup current thread pointer address
|
||||
STORE t1, 0(t0) // Set current thread pointer
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_run_count++; */
|
||||
|
||||
LOAD t2, 1*REGBYTES(t1) // Pickup run count
|
||||
LOAD t3, 6*REGBYTES(t1) // Pickup time slice value
|
||||
addi t2, t2, 1 // Increment run count
|
||||
STORE t2, 1*REGBYTES(t1) // Store new run count
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */
|
||||
|
||||
la t2, _tx_timer_time_slice // Pickup time-slice variable address
|
||||
|
||||
/* Switch to the thread's stack. */
|
||||
/* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack
|
||||
STORE t3, 0(t2) // Store new time-slice*/
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
call _tx_execution_thread_enter // Call the thread execution enter function
|
||||
#endif
|
||||
|
||||
/* Determine if an interrupt frame or a synchronous task suspension frame
|
||||
is present. */
|
||||
|
||||
LOAD t2, 0(sp) // Pickup stack type
|
||||
beqz t2, _tx_thread_synch_return // If 0, solicited thread return
|
||||
|
||||
/* Determine if floating point registers need to be recovered. */
|
||||
|
||||
#if defined(__riscv_float_abi_single)
|
||||
flw f0, 31*REGBYTES(sp) // Recover ft0
|
||||
flw f1, 32*REGBYTES(sp) // Recover ft1
|
||||
flw f2, 33*REGBYTES(sp) // Recover ft2
|
||||
flw f3, 34*REGBYTES(sp) // Recover ft3
|
||||
flw f4, 35*REGBYTES(sp) // Recover ft4
|
||||
flw f5, 36*REGBYTES(sp) // Recover ft5
|
||||
flw f6, 37*REGBYTES(sp) // Recover ft6
|
||||
flw f7, 38*REGBYTES(sp) // Recover ft7
|
||||
flw f8, 39*REGBYTES(sp) // Recover fs0
|
||||
flw f9, 40*REGBYTES(sp) // Recover fs1
|
||||
flw f10,41*REGBYTES(sp) // Recover fa0
|
||||
flw f11,42*REGBYTES(sp) // Recover fa1
|
||||
flw f12,43*REGBYTES(sp) // Recover fa2
|
||||
flw f13,44*REGBYTES(sp) // Recover fa3
|
||||
flw f14,45*REGBYTES(sp) // Recover fa4
|
||||
flw f15,46*REGBYTES(sp) // Recover fa5
|
||||
flw f16,47*REGBYTES(sp) // Recover fa6
|
||||
flw f17,48*REGBYTES(sp) // Recover fa7
|
||||
flw f18,49*REGBYTES(sp) // Recover fs2
|
||||
flw f19,50*REGBYTES(sp) // Recover fs3
|
||||
flw f20,51*REGBYTES(sp) // Recover fs4
|
||||
flw f21,52*REGBYTES(sp) // Recover fs5
|
||||
flw f22,53*REGBYTES(sp) // Recover fs6
|
||||
flw f23,54*REGBYTES(sp) // Recover fs7
|
||||
flw f24,55*REGBYTES(sp) // Recover fs8
|
||||
flw f25,56*REGBYTES(sp) // Recover fs9
|
||||
flw f26,57*REGBYTES(sp) // Recover fs10
|
||||
flw f27,58*REGBYTES(sp) // Recover fs11
|
||||
flw f28,59*REGBYTES(sp) // Recover ft8
|
||||
flw f29,60*REGBYTES(sp) // Recover ft9
|
||||
flw f30,61*REGBYTES(sp) // Recover ft10
|
||||
flw f31,62*REGBYTES(sp) // Recover ft11
|
||||
LOAD t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fld f0, 31*REGBYTES(sp) // Recover ft0
|
||||
fld f1, 32*REGBYTES(sp) // Recover ft1
|
||||
fld f2, 33*REGBYTES(sp) // Recover ft2
|
||||
fld f3, 34*REGBYTES(sp) // Recover ft3
|
||||
fld f4, 35*REGBYTES(sp) // Recover ft4
|
||||
fld f5, 36*REGBYTES(sp) // Recover ft5
|
||||
fld f6, 37*REGBYTES(sp) // Recover ft6
|
||||
fld f7, 38*REGBYTES(sp) // Recover ft7
|
||||
fld f8, 39*REGBYTES(sp) // Recover fs0
|
||||
fld f9, 40*REGBYTES(sp) // Recover fs1
|
||||
fld f10,41*REGBYTES(sp) // Recover fa0
|
||||
fld f11,42*REGBYTES(sp) // Recover fa1
|
||||
fld f12,43*REGBYTES(sp) // Recover fa2
|
||||
fld f13,44*REGBYTES(sp) // Recover fa3
|
||||
fld f14,45*REGBYTES(sp) // Recover fa4
|
||||
fld f15,46*REGBYTES(sp) // Recover fa5
|
||||
fld f16,47*REGBYTES(sp) // Recover fa6
|
||||
fld f17,48*REGBYTES(sp) // Recover fa7
|
||||
fld f18,49*REGBYTES(sp) // Recover fs2
|
||||
fld f19,50*REGBYTES(sp) // Recover fs3
|
||||
fld f20,51*REGBYTES(sp) // Recover fs4
|
||||
fld f21,52*REGBYTES(sp) // Recover fs5
|
||||
fld f22,53*REGBYTES(sp) // Recover fs6
|
||||
fld f23,54*REGBYTES(sp) // Recover fs7
|
||||
fld f24,55*REGBYTES(sp) // Recover fs8
|
||||
fld f25,56*REGBYTES(sp) // Recover fs9
|
||||
fld f26,57*REGBYTES(sp) // Recover fs10
|
||||
fld f27,58*REGBYTES(sp) // Recover fs11
|
||||
fld f28,59*REGBYTES(sp) // Recover ft8
|
||||
fld f29,60*REGBYTES(sp) // Recover ft9
|
||||
fld f30,61*REGBYTES(sp) // Recover ft10
|
||||
fld f31,62*REGBYTES(sp) // Recover ft11
|
||||
LOAD t0, 63*REGBYTES(sp) // Recover fcsr
|
||||
#endif
|
||||
|
||||
/* Recover standard registers. */
|
||||
|
||||
LOAD t0, 30*REGBYTES(sp) // Recover mepc
|
||||
csrw mepc, t0 // Store mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
LOAD x5, 19*REGBYTES(sp) // Recover t0
|
||||
LOAD x6, 18*REGBYTES(sp) // Recover t1
|
||||
LOAD x7, 17*REGBYTES(sp) // Recover t2
|
||||
LOAD x8, 12*REGBYTES(sp) // Recover s0
|
||||
LOAD x9, 11*REGBYTES(sp) // Recover s1
|
||||
LOAD x10, 27*REGBYTES(sp) // Recover a0
|
||||
LOAD x11, 26*REGBYTES(sp) // Recover a1
|
||||
LOAD x12, 25*REGBYTES(sp) // Recover a2
|
||||
LOAD x13, 24*REGBYTES(sp) // Recover a3
|
||||
LOAD x14, 23*REGBYTES(sp) // Recover a4
|
||||
LOAD x15, 22*REGBYTES(sp) // Recover a5
|
||||
LOAD x16, 21*REGBYTES(sp) // Recover a6
|
||||
LOAD x17, 20*REGBYTES(sp) // Recover a7
|
||||
LOAD x18, 10*REGBYTES(sp) // Recover s2
|
||||
LOAD x19, 9*REGBYTES(sp) // Recover s3
|
||||
LOAD x20, 8*REGBYTES(sp) // Recover s4
|
||||
LOAD x21, 7*REGBYTES(sp) // Recover s5
|
||||
LOAD x22, 6*REGBYTES(sp) // Recover s6
|
||||
LOAD x23, 5*REGBYTES(sp) // Recover s7
|
||||
LOAD x24, 4*REGBYTES(sp) // Recover s8
|
||||
LOAD x25, 3*REGBYTES(sp) // Recover s9
|
||||
LOAD x26, 2*REGBYTES(sp) // Recover s10
|
||||
LOAD x27, 1*REGBYTES(sp) // Recover s11
|
||||
LOAD x28, 16*REGBYTES(sp) // Recover t3
|
||||
LOAD x29, 15*REGBYTES(sp) // Recover t4
|
||||
LOAD x30, 14*REGBYTES(sp) // Recover t5
|
||||
LOAD x31, 13*REGBYTES(sp) // Recover t6
|
||||
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point registers
|
||||
#else
|
||||
addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point registers
|
||||
#endif
|
||||
mret // Return to point of interrupt
|
||||
|
||||
_tx_thread_synch_return:
|
||||
|
||||
#if defined(__riscv_float_abi_single)
|
||||
flw f8, 15*REGBYTES(sp) // Recover fs0
|
||||
flw f9, 16*REGBYTES(sp) // Recover fs1
|
||||
flw f18,17*REGBYTES(sp) // Recover fs2
|
||||
flw f19,18*REGBYTES(sp) // Recover fs3
|
||||
flw f20,19*REGBYTES(sp) // Recover fs4
|
||||
flw f21,20*REGBYTES(sp) // Recover fs5
|
||||
flw f22,21*REGBYTES(sp) // Recover fs6
|
||||
flw f23,22*REGBYTES(sp) // Recover fs7
|
||||
flw f24,23*REGBYTES(sp) // Recover fs8
|
||||
flw f25,24*REGBYTES(sp) // Recover fs9
|
||||
flw f26,25*REGBYTES(sp) // Recover fs10
|
||||
flw f27,26*REGBYTES(sp) // Recover fs11
|
||||
LOAD t0, 27*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fld f8, 15*REGBYTES(sp) // Recover fs0
|
||||
fld f9, 16*REGBYTES(sp) // Recover fs1
|
||||
fld f18,17*REGBYTES(sp) // Recover fs2
|
||||
fld f19,18*REGBYTES(sp) // Recover fs3
|
||||
fld f20,19*REGBYTES(sp) // Recover fs4
|
||||
fld f21,20*REGBYTES(sp) // Recover fs5
|
||||
fld f22,21*REGBYTES(sp) // Recover fs6
|
||||
fld f23,22*REGBYTES(sp) // Recover fs7
|
||||
fld f24,23*REGBYTES(sp) // Recover fs8
|
||||
fld f25,24*REGBYTES(sp) // Recover fs9
|
||||
fld f26,25*REGBYTES(sp) // Recover fs10
|
||||
fld f27,26*REGBYTES(sp) // Recover fs11
|
||||
LOAD t0, 27*REGBYTES(sp) // Recover fcsr
|
||||
csrw fcsr, t0 //
|
||||
#endif
|
||||
|
||||
/* Recover standard preserved registers. */
|
||||
/* Recover standard registers. */
|
||||
|
||||
LOAD x1, 13*REGBYTES(sp) // Recover RA
|
||||
LOAD x8, 12*REGBYTES(sp) // Recover s0
|
||||
LOAD x9, 11*REGBYTES(sp) // Recover s1
|
||||
LOAD x18, 10*REGBYTES(sp) // Recover s2
|
||||
LOAD x19, 9*REGBYTES(sp) // Recover s3
|
||||
LOAD x20, 8*REGBYTES(sp) // Recover s4
|
||||
LOAD x21, 7*REGBYTES(sp) // Recover s5
|
||||
LOAD x22, 6*REGBYTES(sp) // Recover s6
|
||||
LOAD x23, 5*REGBYTES(sp) // Recover s7
|
||||
LOAD x24, 4*REGBYTES(sp) // Recover s8
|
||||
LOAD x25, 3*REGBYTES(sp) // Recover s9
|
||||
LOAD x26, 2*REGBYTES(sp) // Recover s10
|
||||
LOAD x27, 1*REGBYTES(sp) // Recover s11
|
||||
LOAD t0, 14*REGBYTES(sp) // Recover mstatus
|
||||
csrw mstatus, t0 // Store mstatus, enables interrupt
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, 29*REGBYTES // Recover stack frame
|
||||
#else
|
||||
addi sp, sp, 16*REGBYTES // Recover stack frame
|
||||
#endif
|
||||
ret // Return to thread
|
||||
|
||||
/* } */
|
||||
227
port/threadx/src/tx_thread_stack_build.S
Normal file
227
port/threadx/src/tx_thread_stack_build.S
Normal file
@@ -0,0 +1,227 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
{ */
|
||||
.global _tx_thread_stack_build
|
||||
_tx_thread_stack_build:
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the RISC-V should look like the following after it is built:
|
||||
Reg Index
|
||||
Stack Top: 1 0 Interrupt stack frame type
|
||||
x27 1 Initial s11
|
||||
x26 2 Initial s10
|
||||
x25 3 Initial s9
|
||||
x24 4 Initial s8
|
||||
x23 5 Initial s7
|
||||
x22 6 Initial s6
|
||||
x21 7 Initial s5
|
||||
x20 8 Initial s4
|
||||
x19 9 Initial s3
|
||||
x18 10 Initial s2
|
||||
x9 11 Initial s1
|
||||
x8 12 Initial s0
|
||||
x31 13 Initial t6
|
||||
x30 14 Initial t5
|
||||
x29 15 Initial t4
|
||||
x28 16 Initial t3
|
||||
x7 17 Initial t2
|
||||
x6 18 Initial t1
|
||||
x5 19 Initial t0
|
||||
x17 20 Initial a7
|
||||
x16 21 Initial a6
|
||||
x15 22 Initial a5
|
||||
x14 23 Initial a4
|
||||
x13 24 Initial a3
|
||||
x12 25 Initial a2
|
||||
x11 26 Initial a1
|
||||
x10 27 Initial a0
|
||||
x1 28 Initial ra
|
||||
-- 29 reserved
|
||||
mepc 30 Initial mepc
|
||||
If floating point support:
|
||||
f0 31 Inital ft0
|
||||
f1 32 Inital ft1
|
||||
f2 33 Inital ft2
|
||||
f3 34 Inital ft3
|
||||
f4 35 Inital ft4
|
||||
f5 36 Inital ft5
|
||||
f6 37 Inital ft6
|
||||
f7 38 Inital ft7
|
||||
f8 39 Inital fs0
|
||||
f9 40 Inital fs1
|
||||
f10 41 Inital fa0
|
||||
f11 42 Inital fa1
|
||||
f12 43 Inital fa2
|
||||
f13 44 Inital fa3
|
||||
f14 45 Inital fa4
|
||||
f15 46 Inital fa5
|
||||
f16 47 Inital fa6
|
||||
f17 48 Inital fa7
|
||||
f18 49 Inital fs2
|
||||
f19 50 Inital fs3
|
||||
f20 51 Inital fs4
|
||||
f21 52 Inital fs5
|
||||
f22 53 Inital fs6
|
||||
f23 54 Inital fs7
|
||||
f24 55 Inital fs8
|
||||
f25 56 Inital fs9
|
||||
f26 57 Inital fs10
|
||||
f27 58 Inital fs11
|
||||
f28 59 Inital ft8
|
||||
f29 60 Inital ft9
|
||||
f30 61 Inital ft10
|
||||
f31 62 Inital ft11
|
||||
fscr 63 Inital fscr
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LOAD t0, TX_THREAD_STACK_END_OFFSET(a0) // Pickup end of stack area
|
||||
andi t0, t0, -4*REGBYTES // Ensure alignment (16-byte for RV32 & 32-byte for RV64)
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi t0, t0, -65*REGBYTES
|
||||
#else
|
||||
addi t0, t0, -32*REGBYTES // Allocate space for the stack frame
|
||||
#endif
|
||||
li t1, 1 // Build stack type
|
||||
STORE t1, 0*REGBYTES(t0) // Place stack type on the top
|
||||
STORE x0, 1*REGBYTES(t0) // Initial s11
|
||||
STORE x0, 2*REGBYTES(t0) // Initial s10
|
||||
STORE x0, 3*REGBYTES(t0) // Initial s9
|
||||
STORE x0, 4*REGBYTES(t0) // Initial s8
|
||||
STORE x0, 5*REGBYTES(t0) // Initial s7
|
||||
STORE x0, 6*REGBYTES(t0) // Initial s6
|
||||
STORE x0, 7*REGBYTES(t0) // Initial s5
|
||||
STORE x0, 8*REGBYTES(t0) // Initial s4
|
||||
STORE x0, 9*REGBYTES(t0) // Initial s3
|
||||
STORE x0, 10*REGBYTES(t0) // Initial s2
|
||||
STORE x0, 11*REGBYTES(t0) // Initial s1
|
||||
STORE x0, 12*REGBYTES(t0) // Initial s0
|
||||
STORE x0, 13*REGBYTES(t0) // Initial t6
|
||||
STORE x0, 14*REGBYTES(t0) // Initial t5
|
||||
STORE x0, 15*REGBYTES(t0) // Initial t4
|
||||
STORE x0, 16*REGBYTES(t0) // Initial t3
|
||||
STORE x0, 17*REGBYTES(t0) // Initial t2
|
||||
STORE x0, 18*REGBYTES(t0) // Initial t1
|
||||
STORE x0, 19*REGBYTES(t0) // Initial t0
|
||||
STORE x0, 20*REGBYTES(t0) // Initial a7
|
||||
STORE x0, 21*REGBYTES(t0) // Initial a6
|
||||
STORE x0, 22*REGBYTES(t0) // Initial a5
|
||||
STORE x0, 23*REGBYTES(t0) // Initial a4
|
||||
STORE x0, 24*REGBYTES(t0) // Initial a3
|
||||
STORE x0, 25*REGBYTES(t0) // Initial a2
|
||||
STORE x0, 26*REGBYTES(t0) // Initial a1
|
||||
STORE x0, 27*REGBYTES(t0) // Initial a0
|
||||
STORE x0, 28*REGBYTES(t0) // Initial ra
|
||||
STORE a1, 30*REGBYTES(t0) // Initial mepc
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
STORE x0, 31*REGBYTES(t0) // Inital ft0
|
||||
STORE x0, 32*REGBYTES(t0) // Inital ft1
|
||||
STORE x0, 33*REGBYTES(t0) // Inital ft2
|
||||
STORE x0, 34*REGBYTES(t0) // Inital ft3
|
||||
STORE x0, 35*REGBYTES(t0) // Inital ft4
|
||||
STORE x0, 36*REGBYTES(t0) // Inital ft5
|
||||
STORE x0, 37*REGBYTES(t0) // Inital ft6
|
||||
STORE x0, 38*REGBYTES(t0) // Inital ft7
|
||||
STORE x0, 39*REGBYTES(t0) // Inital fs0
|
||||
STORE x0, 40*REGBYTES(t0) // Inital fs1
|
||||
STORE x0, 41*REGBYTES(t0) // Inital fa0
|
||||
STORE x0, 42*REGBYTES(t0) // Inital fa1
|
||||
STORE x0, 43*REGBYTES(t0) // Inital fa2
|
||||
STORE x0, 44*REGBYTES(t0) // Inital fa3
|
||||
STORE x0, 45*REGBYTES(t0) // Inital fa4
|
||||
STORE x0, 46*REGBYTES(t0) // Inital fa5
|
||||
STORE x0, 47*REGBYTES(t0) // Inital fa6
|
||||
STORE x0, 48*REGBYTES(t0) // Inital fa7
|
||||
STORE x0, 49*REGBYTES(t0) // Inital fs2
|
||||
STORE x0, 50*REGBYTES(t0) // Inital fs3
|
||||
STORE x0, 51*REGBYTES(t0) // Inital fs4
|
||||
STORE x0, 52*REGBYTES(t0) // Inital fs5
|
||||
STORE x0, 53*REGBYTES(t0) // Inital fs6
|
||||
STORE x0, 54*REGBYTES(t0) // Inital fs7
|
||||
STORE x0, 55*REGBYTES(t0) // Inital fs8
|
||||
STORE x0, 56*REGBYTES(t0) // Inital fs9
|
||||
STORE x0, 57*REGBYTES(t0) // Inital fs10
|
||||
STORE x0, 58*REGBYTES(t0) // Inital fs11
|
||||
STORE x0, 59*REGBYTES(t0) // Inital ft8
|
||||
STORE x0, 60*REGBYTES(t0) // Inital ft9
|
||||
STORE x0, 61*REGBYTES(t0) // Inital ft10
|
||||
STORE x0, 62*REGBYTES(t0) // Inital ft11
|
||||
csrr a1, fcsr // Read fcsr and use it for initial value for each thread
|
||||
STORE a1, 63*REGBYTES(t0) // Initial fscr
|
||||
STORE x0, 64*REGBYTES(t0) // Reserved word (0)
|
||||
#else
|
||||
STORE x0, 31*REGBYTES(t0) // Reserved word (0)
|
||||
#endif
|
||||
|
||||
/* Setup stack pointer. */
|
||||
/* thread_ptr -> tx_thread_stack_ptr = t0; */
|
||||
|
||||
STORE t0, 2*REGBYTES(a0) // Save stack pointer in thread's
|
||||
ret // control block and return
|
||||
/* } */
|
||||
174
port/threadx/src/tx_thread_system_return.S
Normal file
174
port/threadx/src/tx_thread_system_return.S
Normal file
@@ -0,0 +1,174 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is target processor specific. It is used to transfer */
|
||||
/* control from a thread back to the system. Only a minimal context */
|
||||
/* is saved since the compiler assumes temp registers are going to get */
|
||||
/* slicked by a function call anyway. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_system_return(VOID)
|
||||
{ */
|
||||
.global _tx_thread_system_return
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Save minimal context on the stack. */
|
||||
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, -29*REGBYTES // Allocate space on the stack - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, -16*REGBYTES // Allocate space on the stack - without floating point enabled
|
||||
#endif
|
||||
|
||||
/* Store floating point preserved registers. */
|
||||
#if defined(__riscv_float_abi_single)
|
||||
fsw f8, 15*REGBYTES(sp) // Store fs0
|
||||
fsw f9, 16*REGBYTES(sp) // Store fs1
|
||||
fsw f18, 17*REGBYTES(sp) // Store fs2
|
||||
fsw f19, 18*REGBYTES(sp) // Store fs3
|
||||
fsw f20, 19*REGBYTES(sp) // Store fs4
|
||||
fsw f21, 20*REGBYTES(sp) // Store fs5
|
||||
fsw f22, 21*REGBYTES(sp) // Store fs6
|
||||
fsw f23, 22*REGBYTES(sp) // Store fs7
|
||||
fsw f24, 23*REGBYTES(sp) // Store fs8
|
||||
fsw f25, 24*REGBYTES(sp) // Store fs9
|
||||
fsw f26, 25*REGBYTES(sp) // Store fs10
|
||||
fsw f27, 26*REGBYTES(sp) // Store fs11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 27*REGBYTES(sp) // Store fcsr
|
||||
#elif defined(__riscv_float_abi_double)
|
||||
fsd f8, 15*REGBYTES(sp) // Store fs0
|
||||
fsd f9, 16*REGBYTES(sp) // Store fs1
|
||||
fsd f18, 17*REGBYTES(sp) // Store fs2
|
||||
fsd f19, 18*REGBYTES(sp) // Store fs3
|
||||
fsd f20, 19*REGBYTES(sp) // Store fs4
|
||||
fsd f21, 20*REGBYTES(sp) // Store fs5
|
||||
fsd f22, 21*REGBYTES(sp) // Store fs6
|
||||
fsd f23, 22*REGBYTES(sp) // Store fs7
|
||||
fsd f24, 23*REGBYTES(sp) // Store fs8
|
||||
fsd f25, 24*REGBYTES(sp) // Store fs9
|
||||
fsd f26, 25*REGBYTES(sp) // Store fs10
|
||||
fsd f27, 26*REGBYTES(sp) // Store fs11
|
||||
csrr t0, fcsr
|
||||
STORE t0, 27*REGBYTES(sp) // Store fcsr
|
||||
#endif
|
||||
|
||||
STORE x0, 0(sp) // Solicited stack type
|
||||
STORE x1, 13*REGBYTES(sp) // Save RA
|
||||
STORE x8, 12*REGBYTES(sp) // Save s0
|
||||
STORE x9, 11*REGBYTES(sp) // Save s1
|
||||
STORE x18, 10*REGBYTES(sp) // Save s2
|
||||
STORE x19, 9*REGBYTES(sp) // Save s3
|
||||
STORE x20, 8*REGBYTES(sp) // Save s4
|
||||
STORE x21, 7*REGBYTES(sp) // Save s5
|
||||
STORE x22, 6*REGBYTES(sp) // Save s6
|
||||
STORE x23, 5*REGBYTES(sp) // Save s7
|
||||
STORE x24, 4*REGBYTES(sp) // Save s8
|
||||
STORE x25, 3*REGBYTES(sp) // Save s9
|
||||
STORE x26, 2*REGBYTES(sp) // Save s10
|
||||
STORE x27, 1*REGBYTES(sp) // Save s11
|
||||
csrr t0, mstatus // Pickup mstatus
|
||||
STORE t0, 14*REGBYTES(sp) // Save mstatus
|
||||
|
||||
|
||||
/* Lockout interrupts. - will be enabled in _tx_thread_schedule */
|
||||
|
||||
csrci mstatus, 0xF
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
call _tx_execution_thread_exit // Call the thread execution exit function
|
||||
#endif
|
||||
|
||||
la t0, _tx_thread_current_ptr // Pickup address of pointer
|
||||
LOAD t1, 0(t0) // Pickup current thread pointer
|
||||
la t2,_tx_thread_system_stack_ptr // Pickup stack pointer address
|
||||
|
||||
/* Save current stack and switch to system stack. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
|
||||
SP = _tx_thread_system_stack_ptr; */
|
||||
|
||||
STORE sp, 2*REGBYTES(t1) // Save stack pointer
|
||||
LOAD sp, 0(t2) // Switch to system stack
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
la t4, _tx_timer_time_slice // Pickup time slice variable addr
|
||||
lw t3, 0(t4) // Pickup time slice value
|
||||
la t2, _tx_thread_schedule // Pickup address of scheduling loop
|
||||
beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it
|
||||
|
||||
/* Save time-slice for the thread and clear the current time-slice. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
|
||||
sw t3, TX_THREAD_TIME_SLICE_OFFSET(t1) // Save current time-slice for thread
|
||||
sw x0, 0(t4) // Clear time-slice variable
|
||||
|
||||
/* } */
|
||||
_tx_thread_dont_save_ts:
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
STORE x0, 0(t0) // Clear current thread pointer
|
||||
jr t2 // Return to thread scheduler
|
||||
|
||||
/* } */
|
||||
Reference in New Issue
Block a user