diff --git a/.cproject b/.cproject index d66b3fa..4734f10 100644 --- a/.cproject +++ b/.cproject @@ -14,17 +14,28 @@ - + - - + + + + + + - - + + + + + + + + + @@ -39,4 +50,5 @@ + \ No newline at end of file diff --git a/env/TGC5L/.gitignore b/env/TGCP/.gitignore similarity index 100% rename from env/TGC5L/.gitignore rename to env/TGCP/.gitignore diff --git a/env/TGC5L/init.c b/env/TGCP/init.c similarity index 100% rename from env/TGC5L/init.c rename to env/TGCP/init.c diff --git a/env/TGC5L/link.lds b/env/TGCP/link.lds similarity index 100% rename from env/TGC5L/link.lds rename to env/TGCP/link.lds diff --git a/env/TGC5L/platform.h b/env/TGCP/platform.h similarity index 100% rename from env/TGC5L/platform.h rename to env/TGCP/platform.h diff --git a/env/ehrenberg/init.c b/env/ehrenberg/init.c index 2ae1f7a..065b961 100644 --- a/env/ehrenberg/init.c +++ b/env/ehrenberg/init.c @@ -5,16 +5,9 @@ #include "platform.h" #include "encoding.h" -#if __riscv_xlen == 32 -#define MCAUSE_INT 0x80000000UL -#define MCAUSE_CAUSE 0x000003FFUL -#else -#define MCAUSE_INT 0x8000000000000000UL -#define MCAUSE_CAUSE 0x00000000000003FFUL -#endif extern int main(int argc, char** argv); -extern void trap_entry(); +extern void trap_entry(void); #define IRQ_M_SOFT 3 #define IRQ_M_TIMER 7 #define IRQ_M_EXT 11 @@ -48,7 +41,7 @@ static uint32_t mtime_hi(void) return ret; } -uint64_t get_timer_value() +uint64_t get_timer_value(void) { while (1) { uint32_t hi = mtime_hi(); @@ -90,10 +83,9 @@ void __attribute__((weak)) handle_m_ext_interrupt(){ } void __attribute__((weak)) handle_m_time_interrupt(){ - uint64_t time = ((uint64_t)mtimer->mtimeh)<<32 || mtimer->mtime; - time+=MTIMER_NEXT_TICK_INC; - mtimer->mtimecmph = time>>32; - mtimer->mtimecmp = time; + uint64_t time = get_aclint_mtime(aclint); + time+=MTIMER_NEXT_TICK_INC; + set_aclint_mtime(aclint, time); } void __attribute__((weak)) default_handler(void) { @@ -119,7 +111,7 @@ void _init() #ifndef NO_INIT init_pll(); uart_init(115200); - printf("core freq at %d Hz\n", get_cpu_freq()); + printf("core freq at %lu Hz\n", get_cpu_freq()); write_csr(mtvec, &trap_entry); if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping @@ -134,6 +126,6 @@ void _init() } -void _fini() +void _fini(void) { } diff --git a/env/ehrenberg/platform.h b/env/ehrenberg/platform.h index cec65bd..711bac3 100644 --- a/env/ehrenberg/platform.h +++ b/env/ehrenberg/platform.h @@ -3,33 +3,33 @@ #ifndef _ISS_PLATFORM_H #define _ISS_PLATFORM_H -// Some things missing from the official encoding.h -#define MCAUSE_INT 0x80000000 -#define MCAUSE_CAUSE 0x7FFFFFFF +#if __riscv_xlen == 32 +#define MCAUSE_INT 0x80000000UL +#define MCAUSE_CAUSE 0x000003FFUL +#else +#define MCAUSE_INT 0x8000000000000000UL +#define MCAUSE_CAUSE 0x00000000000003FFUL +#endif #define APB_BUS #include "ehrenberg/devices/gpio.h" -#include "ehrenberg/devices/interrupt.h" -#include "ehrenberg/devices/timer.h" #include "ehrenberg/devices/uart.h" +#include "ehrenberg/devices/timer.h" +#include "ehrenberg/devices/aclint.h" +#include "ehrenberg/devices/interrupt.h" #include "ehrenberg/devices/qspi.h" #define PERIPH(TYPE, ADDR) ((volatile TYPE*) (ADDR)) #define APB_BASE 0xF0000000 -#define TIMER_BASE (APB_BASE+0x30000) -#define gpio_a PERIPH(gpio_t, APB_BASE+0x00000) -//#define gpio_b PERIPH(gpio_t, APB_BASE+0x10000) -#define uart PERIPH(uart_t, APB_BASE+0x10000) -#define prescaler PERIPH(uart_t, TIMER_BASE+0x0) -#define timer_a PERIPH(uart_t, TIMER_BASE+0x10) -#define timer_b PERIPH(uart_t, TIMER_BASE+0x20) -#define mtimer PERIPH(mtimer_t, APB_BASE+0x30000) -#define irq PERIPH(irq_t, APB_BASE+0x40000) -#define qspi PERIPH(qspi_t, APB_BASE+0x50000) -//volatile qspi_t* const qspi = (qspi_t*)(APB_BASE+0x50000); +#define gpio PERIPH(gpio_t, APB_BASE+0x0000) +#define uart PERIPH(uart_t, APB_BASE+0x1000) +#define timer PERIPH(timer_t, APB_BASE+0x20000) +#define aclint PERIPH(aclint_t, APB_BASE+0x30000) +#define irq PERIPH(irq_t, APB_BASE+0x40000) +#define qspi PERIPH(qspi_t, APB_BASE+0x50000) #define XIP_START_LOC 0xE0040000 @@ -40,6 +40,5 @@ void init_pll(void); unsigned long get_cpu_freq(void); unsigned long get_timer_freq(void); -uint64_t get_timer_value(void); #endif /* _ISS_PLATFORM_H */ diff --git a/env/tgc-vp/.gitignore b/env/tgc-vp/.gitignore deleted file mode 100644 index cc5bb74..0000000 --- a/env/tgc-vp/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/*.o diff --git a/env/tgc-vp/init.c b/env/tgc-vp/init.c deleted file mode 100644 index 690f754..0000000 --- a/env/tgc-vp/init.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include - -#include "platform.h" -#include "encoding.h" - -extern int main(int argc, char** argv); -extern void trap_entry(); - -static unsigned long mtime_lo(void) -{ - unsigned long ret; - __asm volatile("rdtime %0":"=r"(ret)); - return ret; -} - - -#if __riscv_xlen==32 - -static uint32_t mtime_hi(void) -{ - unsigned long ret; - __asm volatile("rdtimeh %0":"=r"(ret)); - return ret; -} - -uint64_t get_timer_value() -{ - while (1) { - uint32_t hi = mtime_hi(); - uint32_t lo = mtime_lo(); - if (hi == mtime_hi()) - return ((uint64_t)hi << 32) | lo; - } -} - -#elif __riscv_xlen==64 - -uint64_t get_timer_value() -{ - return mtime_lo(); -} - -#endif - -unsigned long get_timer_freq() -{ - return 32768; -} - -unsigned long get_cpu_freq() -{ - return 10000000; -} - -void init_pll(void){ - -} - -static void uart_init(size_t baud_rate) -{ - GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; - GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; - UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1; - UART0_REG(UART_REG_TXCTRL) |= UART_TXEN; -} - -#ifdef USE_PLIC -extern void handle_m_ext_interrupt(); -#endif - -#ifdef USE_M_TIME -extern void handle_m_time_interrupt(); -#endif - -uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) -{ - if (0){ -#ifdef USE_PLIC - // External Machine-Level interrupt from PLIC - } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { - handle_m_ext_interrupt(); -#endif -#ifdef USE_M_TIME - // External Machine-Level interrupt from PLIC - } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ - handle_m_time_interrupt(); -#endif - } - else { - write(1, "trap\n", 5); - _exit(1 + mcause); - } - return epc; -} - -void _init() -{ - -#ifndef NO_INIT - init_pll(); - uart_init(115200); - printf("core freq at %d Hz\n", get_cpu_freq()); - write_csr(mtvec, &trap_entry); - if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present - write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping - write_csr(fcsr, 0); // initialize rounding mode, undefined at reset - } -#endif - -} - -void _fini() -{ -} diff --git a/env/tgc-vp/link.lds b/env/tgc-vp/link.lds deleted file mode 100644 index 3561a66..0000000 --- a/env/tgc-vp/link.lds +++ /dev/null @@ -1,174 +0,0 @@ -OUTPUT_ARCH( "riscv" ) - -ENTRY( _start ) - -MEMORY -{ - flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 512M - ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 128K -} - -PHDRS -{ - flash PT_LOAD; - ram_init PT_LOAD; - ram PT_NULL; -} - -SECTIONS -{ - __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; - - .init ORIGIN(flash) : - { - KEEP (*(SORT_NONE(.init))) - } >flash AT>flash :flash - - .text : - { - *(.text.unlikely .text.unlikely.*) - *(.text.startup .text.startup.*) - *(.text .text.*) - *(.gnu.linkonce.t.*) - } >flash AT>flash :flash - - .fini : - { - KEEP (*(SORT_NONE(.fini))) - } >flash AT>flash :flash - - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - .rodata : - { - *(.rdata) - *(.rodata .rodata.*) - *(.gnu.linkonce.r.*) - } >flash AT>flash :flash - - . = ALIGN(4); - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >flash AT>flash :flash - - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } >flash AT>flash :flash - - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >flash AT>flash :flash - - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } >flash AT>flash :flash - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } >flash AT>flash :flash - - .lalign : - { - . = ALIGN(4); - PROVIDE( _data_lma = . ); - } >flash AT>flash :flash - - .dalign : - { - . = ALIGN(4); - PROVIDE( _data = . ); - } >ram AT>flash :ram_init - - .data : - { - __DATA_BEGIN__ = .; - *(.data .data.*) - *(.gnu.linkonce.d.*) - } >ram AT>flash :ram_init - - .srodata : - { - PROVIDE( _gp = . + 0x800 ); - *(.srodata.cst16) - *(.srodata.cst8) - *(.srodata.cst4) - *(.srodata.cst2) - *(.srodata .srodata.*) - } >ram AT>flash :ram_init - - .sdata : - { - __SDATA_BEGIN__ = .; - *(.sdata .sdata.*) - *(.gnu.linkonce.s.*) - } >ram AT>flash :ram_init - - . = ALIGN(4); - PROVIDE( _edata = . ); - PROVIDE( edata = . ); - - PROVIDE( _fbss = . ); - PROVIDE( __bss_start = . ); - .bss : - { - *(.sbss*) - *(.gnu.linkonce.sb.*) - *(.bss .bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN(4); - } >ram AT>ram :ram - - . = ALIGN(8); - __BSS_END__ = .; - __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800)); - PROVIDE( _end = . ); - PROVIDE( end = . ); - - .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : - { - PROVIDE( _heap_end = . ); - . = __stack_size; - PROVIDE( _sp = . ); - } >ram AT>ram :ram - - PROVIDE( tohost = 0xfffffff0 ); - PROVIDE( fromhost = 0xfffffff8 ); -} diff --git a/env/tgc-vp/platform.h b/env/tgc-vp/platform.h deleted file mode 100644 index 9c6caa7..0000000 --- a/env/tgc-vp/platform.h +++ /dev/null @@ -1,127 +0,0 @@ -// See LICENSE for license details. - -#ifndef _ISS_PLATFORM_H -#define _ISS_PLATFORM_H - -// Some things missing from the official encoding.h -#define MCAUSE_INT 0x80000000 -#define MCAUSE_CAUSE 0x7FFFFFFF - -#include "bits.h" -#include "tgc-vp/devices/aon.h" -#include "tgc-vp/devices/clint.h" -#include "tgc-vp/devices/gpio.h" -#include "tgc-vp/devices/otp.h" -#include "tgc-vp/devices/plic.h" -#include "tgc-vp/devices/prci.h" -#include "tgc-vp/devices/pwm.h" -#include "tgc-vp/devices/spi.h" -#include "tgc-vp/devices/uart.h" - -/**************************************************************************** - * Platform definitions - *****************************************************************************/ - -// Memory map -#define MASKROM_BASE_ADDR _AC(0x00001000,UL) -#define TRAPVEC_TABLE_BASE_ADDR _AC(0x00001010,UL) -#define OTP_MMAP_ADDR _AC(0x00020000,UL) -#define CLINT_BASE_ADDR _AC(0x02000000,UL) -#define PLIC_BASE_ADDR _AC(0x0C000000,UL) -#define AON_BASE_ADDR _AC(0x10000000,UL) -#define PRCI_BASE_ADDR _AC(0x10008000,UL) -#define OTP_BASE_ADDR _AC(0x10010000,UL) -#define GPIO_BASE_ADDR _AC(0x10012000,UL) -#define UART0_BASE_ADDR _AC(0x10013000,UL) -#define SPI0_BASE_ADDR _AC(0x10014000,UL) -#define PWM0_BASE_ADDR _AC(0x10015000,UL) -#define UART1_BASE_ADDR _AC(0x10023000,UL) -#define SPI1_BASE_ADDR _AC(0x10024000,UL) -#define PWM1_BASE_ADDR _AC(0x10025000,UL) -#define SPI2_BASE_ADDR _AC(0x10034000,UL) -#define PWM2_BASE_ADDR _AC(0x10035000,UL) -#define SPI0_MMAP_ADDR _AC(0x20000000,UL) -#define MEM_BASE_ADDR _AC(0x80000000,UL) - -// IOF masks -#define IOF0_SPI1_MASK _AC(0x000007FC,UL) -#define SPI11_NUM_SS (4) -#define IOF_SPI1_SS0 (2u) -#define IOF_SPI1_SS1 (8u) -#define IOF_SPI1_SS2 (9u) -#define IOF_SPI1_SS3 (10u) -#define IOF_SPI1_MOSI (3u) -#define IOF_SPI1_MISO (4u) -#define IOF_SPI1_SCK (5u) -#define IOF_SPI1_DQ0 (3u) -#define IOF_SPI1_DQ1 (4u) -#define IOF_SPI1_DQ2 (6u) -#define IOF_SPI1_DQ3 (7u) - -#define IOF0_SPI2_MASK _AC(0xFC000000,UL) -#define SPI2_NUM_SS (1) -#define IOF_SPI2_SS0 (26u) -#define IOF_SPI2_MOSI (27u) -#define IOF_SPI2_MISO (28u) -#define IOF_SPI2_SCK (29u) -#define IOF_SPI2_DQ0 (27u) -#define IOF_SPI2_DQ1 (28u) -#define IOF_SPI2_DQ2 (30u) -#define IOF_SPI2_DQ3 (31u) - -//#define IOF0_I2C_MASK _AC(0x00003000,UL) - -#define IOF0_UART0_MASK _AC(0x00030000, UL) -#define IOF_UART0_RX (16u) -#define IOF_UART0_TX (17u) - -#define IOF0_UART1_MASK _AC(0x03000000, UL) -#define IOF_UART1_RX (24u) -#define IOF_UART1_TX (25u) - -#define IOF1_PWM0_MASK _AC(0x0000000F, UL) -#define IOF1_PWM1_MASK _AC(0x00780000, UL) -#define IOF1_PWM2_MASK _AC(0x00003C00, UL) - -// Interrupt numbers -#define INT_RESERVED 0 -#define INT_WDOGCMP 1 -#define INT_RTCCMP 2 -#define INT_UART0_BASE 3 -#define INT_UART1_BASE 4 -#define INT_SPI0_BASE 5 -#define INT_SPI1_BASE 6 -#define INT_SPI2_BASE 7 -#define INT_GPIO_BASE 8 -#define INT_PWM0_BASE 40 -#define INT_PWM1_BASE 44 -#define INT_PWM2_BASE 48 - -// Helper functions -#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i))) -#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i))) -#define AON_REG(offset) _REG32(AON_BASE_ADDR, offset) -#define CLINT_REG(offset) _REG32(CLINT_BASE_ADDR, offset) -#define GPIO_REG(offset) _REG32(GPIO_BASE_ADDR, offset) -#define OTP_REG(offset) _REG32(OTP_BASE_ADDR, offset) -#define PLIC_REG(offset) _REG32(PLIC_BASE_ADDR, offset) -#define PRCI_REG(offset) _REG32(PRCI_BASE_ADDR, offset) -#define PWM0_REG(offset) _REG32(PWM0_BASE_ADDR, offset) -#define PWM1_REG(offset) _REG32(PWM1_BASE_ADDR, offset) -#define PWM2_REG(offset) _REG32(PWM2_BASE_ADDR, offset) -#define SPI0_REG(offset) _REG32(SPI0_BASE_ADDR, offset) -#define SPI1_REG(offset) _REG32(SPI1_BASE_ADDR, offset) -#define SPI2_REG(offset) _REG32(SPI2_BASE_ADDR, offset) -#define UART0_REG(offset) _REG32(UART0_BASE_ADDR, offset) -#define UART1_REG(offset) _REG32(UART1_BASE_ADDR, offset) - -// Misc - -#include - -void init_pll(void); -unsigned long get_cpu_freq(void); -unsigned long get_timer_freq(void); -uint64_t get_timer_value(void); - -#endif /* _ISS_PLATFORM_H */ diff --git a/env/tgc_vp b/env/tgc_vp new file mode 120000 index 0000000..4f09dcb --- /dev/null +++ b/env/tgc_vp @@ -0,0 +1 @@ +ehrenberg/ \ No newline at end of file diff --git a/include/ehrenberg/devices/aclint.h b/include/ehrenberg/devices/aclint.h new file mode 100644 index 0000000..bc53b41 --- /dev/null +++ b/include/ehrenberg/devices/aclint.h @@ -0,0 +1,29 @@ +#ifndef _BSP_ACLINT_H +#define _BSP_ACLINT_H + +#include +#include "gen/Apb3AClint.h" + +#define aclint_t apb3aclint_t + +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){ + uint64_t value = ((uint64_t)get_aclint_mtime_hi(reg) << 32) | (uint64_t)get_aclint_mtime_lo(reg); + return value; +} + +static void set_aclint_mtimecmp(volatile aclint_t* reg, uint64_t value){ + 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 /* _BSP_ACLINT_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gen/Apb3AClint.h b/include/ehrenberg/devices/gen/Apb3AClint.h new file mode 100644 index 0000000..f9fd1d4 --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3AClint.h @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3ACLINT_H +#define _BSP_APB3ACLINT_H + +#include + +typedef struct __attribute((__packed__)) { + volatile uint32_t MSIP0; + volatile uint32_t MTIMECMP0LO; + volatile uint32_t MTIMECMP0HI; + volatile uint32_t MTIME_LO; + volatile uint32_t MTIME_HI; +}apb3aclint_t; + +inline uint32_t get_aclint_msip0(volatile apb3aclint_t *reg){ + return (reg->MSIP0 >> 0) & 0x1; +} +inline void set_aclint_msip0(volatile apb3aclint_t *reg, uint8_t value){ + reg->MSIP0 = (reg->MSIP0 & ~(0x1U << 0)) | (value << 0); +} +inline uint32_t get_aclint_mtimecmp0lo(volatile apb3aclint_t *reg){ + return (reg->MTIMECMP0LO >> 0) & 0xffffffff; +} +inline void set_aclint_mtimecmp0lo(volatile apb3aclint_t *reg, uint32_t value){ + reg->MTIMECMP0LO = (reg->MTIMECMP0LO & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_aclint_mtimecmp0hi(volatile apb3aclint_t *reg){ + return (reg->MTIMECMP0HI >> 0) & 0xffffffff; +} +inline void set_aclint_mtimecmp0hi(volatile apb3aclint_t *reg, uint32_t value){ + reg->MTIMECMP0HI = (reg->MTIMECMP0HI & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_aclint_mtime_lo(volatile apb3aclint_t *reg){ + return (reg->MTIME_LO >> 0) & 0xffffffff; +} +inline void set_aclint_mtime_lo(volatile apb3aclint_t *reg, uint32_t value){ + reg->MTIME_LO = (reg->MTIME_LO & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_aclint_mtime_hi(volatile apb3aclint_t *reg){ + return (reg->MTIME_HI >> 0) & 0xffffffff; +} +inline void set_aclint_mtime_hi(volatile apb3aclint_t *reg, uint32_t value){ + reg->MTIME_HI = (reg->MTIME_HI & ~(0xffffffffU << 0)) | (value << 0); +} +#endif /* _BSP_APB3ACLINT_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gen/Apb3Gpio.h b/include/ehrenberg/devices/gen/Apb3Gpio.h new file mode 100644 index 0000000..dbd9251 --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3Gpio.h @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3GPIO_H +#define _BSP_APB3GPIO_H + +#include + +typedef struct __attribute((__packed__)) { + volatile uint32_t VALUE; + volatile uint32_t WRITE; + volatile uint32_t WRITEENABLE; +}apb3gpio_t; + +inline uint32_t get_gpio_value(volatile apb3gpio_t *reg){ + return (reg->VALUE >> 0) & 0xffffffff; +} +inline uint32_t get_gpio_write(volatile apb3gpio_t *reg){ + return (reg->WRITE >> 0) & 0xffffffff; +} +inline void set_gpio_write(volatile apb3gpio_t *reg, uint32_t value){ + reg->WRITE = (reg->WRITE & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_gpio_writeEnable(volatile apb3gpio_t *reg){ + return (reg->WRITEENABLE >> 0) & 0xffffffff; +} +inline void set_gpio_writeEnable(volatile apb3gpio_t *reg, uint32_t value){ + reg->WRITEENABLE = (reg->WRITEENABLE & ~(0xffffffffU << 0)) | (value << 0); +} +#endif /* _BSP_APB3GPIO_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gen/Apb3IrqCtrl.h b/include/ehrenberg/devices/gen/Apb3IrqCtrl.h new file mode 100644 index 0000000..a832395 --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3IrqCtrl.h @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3IRQCTRL_H +#define _BSP_APB3IRQCTRL_H + +#include + +typedef struct __attribute((__packed__)) { + volatile uint32_t PENDINGSREG; + volatile uint32_t MASKSREG; +}apb3irqctrl_t; + +inline uint32_t get_irq_pendingsReg(volatile apb3irqctrl_t *reg){ + return (reg->PENDINGSREG >> 0) & 0xf; +} +inline void set_irq_pendingsReg(volatile apb3irqctrl_t *reg, uint8_t value){ + reg->PENDINGSREG = (reg->PENDINGSREG & ~(0xfU << 0)) | (value << 0); +} +inline uint32_t get_irq_masksReg(volatile apb3irqctrl_t *reg){ + return (reg->MASKSREG >> 0) & 0xf; +} +inline void set_irq_masksReg(volatile apb3irqctrl_t *reg, uint8_t value){ + reg->MASKSREG = (reg->MASKSREG & ~(0xfU << 0)) | (value << 0); +} +#endif /* _BSP_APB3IRQCTRL_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gen/Apb3SpiXdrMasterCtrl.h b/include/ehrenberg/devices/gen/Apb3SpiXdrMasterCtrl.h new file mode 100644 index 0000000..7d7a927 --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3SpiXdrMasterCtrl.h @@ -0,0 +1,214 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3SPIXDRMASTERCTRL_H +#define _BSP_APB3SPIXDRMASTERCTRL_H + +#include + +typedef struct __attribute((__packed__)) { + volatile uint32_t DATA; + volatile uint32_t STATUS; + volatile uint32_t CONFIG; + volatile uint32_t INTR; + uint32_t fill0[4]; + volatile uint32_t SCLK_CONFIG; + volatile uint32_t SSGEN_SETUP; + volatile uint32_t SSGEN_HOLD; + volatile uint32_t SSGEN_DISABLE; + volatile uint32_t SSGEN_ACTIVE_HIGH; + uint32_t fill1[3]; + volatile uint32_t XIP_ENABLE; + volatile uint32_t XIP_CONFIG; + volatile uint32_t XIP_MODE; + uint32_t fill2[1]; + volatile uint32_t XIP_WRITE; + volatile uint32_t XIP_READ_WRITE; + volatile uint32_t XIP_READ; +}apb3spixdrmasterctrl_t; + +#define SPI_XIP_CONFIG_INSTRUCTION_OFFS 0 +#define SPI_XIP_CONFIG_INSTRUCTION_MASK 0xff +#define SPI_XIP_CONFIG_INSTRUCTION(V) ((V & SPI_XIP_CONFIG_INSTRUCTION_MASK) << SPI_XIP_CONFIG_INSTRUCTION_OFFS) + +#define SPI_XIP_CONFIG_ENABLE_OFFS 8 +#define SPI_XIP_CONFIG_ENABLE_MASK 1 +#define SPI_XIP_CONFIG_ENABLE(V) ((V & SPI_XIP_CONFIG_ENABLE_MASK) << SPI_XIP_CONFIG_ENABLE_OFFS) + +#define SPI_XIP_CONFIG_DUMMY_VALUE_OFFS 16 +#define SPI_XIP_CONFIG_DUMMY_VALUE_MASK 0xff +#define SPI_XIP_CONFIG_DUMMY_VALUE(V) ((V & SPI_XIP_CONFIG_DUMMY_VALUE_MASK) << SPI_XIP_CONFIG_DUMMY_VALUE_OFFS) + +#define SPI_XIP_CONFIG_DUMMY_COUNT_OFFS 24 +#define SPI_XIP_CONFIG_DUMMY_COUNT_MASK 0xf +#define SPI_XIP_CONFIG_DUMMY_COUNT(V) ((V & SPI_XIP_CONFIG_DUMMY_COUNT_MASK) << SPI_XIP_CONFIG_DUMMY_COUNT_OFFS) + +inline void set_spi_data_data(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->DATA = (reg->DATA & ~(0xffU << 0)) | (value << 0); +} +inline uint32_t get_spi_data_write(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->DATA >> 8) & 0x1; +} +inline void set_spi_data_write(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->DATA = (reg->DATA & ~(0x1U << 8)) | (value << 8); +} +inline uint32_t get_spi_data_read(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->DATA >> 9) & 0x1; +} +inline void set_spi_data_read(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->DATA = (reg->DATA & ~(0x1U << 9)) | (value << 9); +} +inline uint32_t get_spi_data_kind(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->DATA >> 11) & 0x1; +} +inline void set_spi_data_kind(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->DATA = (reg->DATA & ~(0x1U << 11)) | (value << 11); +} +inline uint32_t get_spi_data_rx_data_invalid(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->DATA >> 31) & 0x1; +} +inline uint32_t get_spi_status_tx_free(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->STATUS >> 0) & 0x3f; +} +inline uint32_t get_spi_status_rx_avail(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->STATUS >> 16) & 0x3f; +} +inline uint32_t get_spi_config_kind(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->CONFIG >> 0) & 0x3; +} +inline void set_spi_config_kind(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->CONFIG = (reg->CONFIG & ~(0x3U << 0)) | (value << 0); +} +inline uint32_t get_spi_config_mode(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->CONFIG >> 4) & 0x7; +} +inline void set_spi_config_mode(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->CONFIG = (reg->CONFIG & ~(0x7U << 4)) | (value << 4); +} +inline uint32_t get_spi_intr_tx_ie(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->INTR >> 0) & 0x1; +} +inline void set_spi_intr_tx_ie(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->INTR = (reg->INTR & ~(0x1U << 0)) | (value << 0); +} +inline uint32_t get_spi_intr_rx_ie(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->INTR >> 1) & 0x1; +} +inline void set_spi_intr_rx_ie(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->INTR = (reg->INTR & ~(0x1U << 1)) | (value << 1); +} +inline uint32_t get_spi_intr_tx_ip(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->INTR >> 8) & 0x1; +} +inline uint32_t get_spi_intr_rx_ip(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->INTR >> 9) & 0x1; +} +inline uint32_t get_spi_intr_tx_active(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->INTR >> 16) & 0x1; +} +inline uint32_t get_spi_sclk_config(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->SCLK_CONFIG >> 0) & 0xfff; +} +inline void set_spi_sclk_config(volatile apb3spixdrmasterctrl_t *reg, uint16_t value){ + reg->SCLK_CONFIG = (reg->SCLK_CONFIG & ~(0xfffU << 0)) | (value << 0); +} +inline uint32_t get_spi_ssgen_setup(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->SSGEN_SETUP >> 0) & 0xfff; +} +inline void set_spi_ssgen_setup(volatile apb3spixdrmasterctrl_t *reg, uint16_t value){ + reg->SSGEN_SETUP = (reg->SSGEN_SETUP & ~(0xfffU << 0)) | (value << 0); +} +inline uint32_t get_spi_ssgen_hold(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->SSGEN_HOLD >> 0) & 0xfff; +} +inline void set_spi_ssgen_hold(volatile apb3spixdrmasterctrl_t *reg, uint16_t value){ + reg->SSGEN_HOLD = (reg->SSGEN_HOLD & ~(0xfffU << 0)) | (value << 0); +} +inline uint32_t get_spi_ssgen_disable(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->SSGEN_DISABLE >> 0) & 0xfff; +} +inline void set_spi_ssgen_disable(volatile apb3spixdrmasterctrl_t *reg, uint16_t value){ + reg->SSGEN_DISABLE = (reg->SSGEN_DISABLE & ~(0xfffU << 0)) | (value << 0); +} +inline uint32_t get_spi_ssgen_active_high(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->SSGEN_ACTIVE_HIGH >> 0) & 0x1; +} +inline void set_spi_ssgen_active_high(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->SSGEN_ACTIVE_HIGH = (reg->SSGEN_ACTIVE_HIGH & ~(0x1U << 0)) | (value << 0); +} +inline uint32_t get_spi_xip_enable(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_ENABLE >> 0) & 0x1; +} +inline void set_spi_xip_enable(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_ENABLE = (reg->XIP_ENABLE & ~(0x1U << 0)) | (value << 0); +} +inline uint32_t get_spi_xip_config(volatile apb3spixdrmasterctrl_t *reg){ + return reg->XIP_CONFIG; +} +inline void set_spi_xip_config(volatile apb3spixdrmasterctrl_t *reg, uint32_t value){ + reg->XIP_CONFIG = value; +} +inline uint32_t get_spi_xip_config_instruction(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_CONFIG >> 0) & 0xff; +} +inline void set_spi_xip_config_instruction(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_CONFIG = (reg->XIP_CONFIG & ~(0xffU << 0)) | (value << 0); +} +inline uint32_t get_spi_xip_config_enable(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_CONFIG >> 8) & 0x1; +} +inline void set_spi_xip_config_enable(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_CONFIG = (reg->XIP_CONFIG & ~(0x1U << 8)) | (value << 8); +} +inline uint32_t get_spi_xip_config_dummy_value(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_CONFIG >> 16) & 0xff; +} +inline void set_spi_xip_config_dummy_value(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_CONFIG = (reg->XIP_CONFIG & ~(0xffU << 16)) | (value << 16); +} +inline uint32_t get_spi_xip_config_dummy_count(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_CONFIG >> 24) & 0xf; +} +inline void set_spi_xip_config_dummy_count(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_CONFIG = (reg->XIP_CONFIG & ~(0xfU << 24)) | (value << 24); +} +inline uint32_t get_spi_xip_mode_instruction(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_MODE >> 0) & 0x7; +} +inline void set_spi_xip_mode_instruction(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_MODE = (reg->XIP_MODE & ~(0x7U << 0)) | (value << 0); +} +inline uint32_t get_spi_xip_mode_address(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_MODE >> 8) & 0x7; +} +inline void set_spi_xip_mode_address(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_MODE = (reg->XIP_MODE & ~(0x7U << 8)) | (value << 8); +} +inline uint32_t get_spi_xip_mode_dummy(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_MODE >> 16) & 0x7; +} +inline void set_spi_xip_mode_dummy(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_MODE = (reg->XIP_MODE & ~(0x7U << 16)) | (value << 16); +} +inline uint32_t get_spi_xip_mode_payload(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_MODE >> 24) & 0x7; +} +inline void set_spi_xip_mode_payload(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_MODE = (reg->XIP_MODE & ~(0x7U << 24)) | (value << 24); +} +inline void set_spi_xip_write(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_WRITE = (reg->XIP_WRITE & ~(0xffU << 0)) | (value << 0); +} +inline void set_spi_xip_read_write(volatile apb3spixdrmasterctrl_t *reg, uint8_t value){ + reg->XIP_READ_WRITE = (reg->XIP_READ_WRITE & ~(0xffU << 0)) | (value << 0); +} +inline uint32_t get_spi_xip_read(volatile apb3spixdrmasterctrl_t *reg){ + return (reg->XIP_READ >> 0) & 0xff; +} +#endif /* _BSP_APB3SPIXDRMASTERCTRL_H */ diff --git a/include/ehrenberg/devices/gen/Apb3Timer.h b/include/ehrenberg/devices/gen/Apb3Timer.h new file mode 100644 index 0000000..89fcb8b --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3Timer.h @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3TIMER_H +#define _BSP_APB3TIMER_H + +#include + +typedef struct __attribute((__packed__)) { + volatile uint32_t PRESCALER; + volatile uint32_t T0_CTRL; + volatile uint32_t T0_OVERFLOW; + volatile uint32_t T0_VALUE; + volatile uint32_t T1_CTRL; + volatile uint32_t T1_OVERFLOW; + volatile uint32_t T1_VALUE; +}apb3timer_t; + +inline uint32_t get_timer_prescaler(volatile apb3timer_t *reg){ + return (reg->PRESCALER >> 0) & 0xffff; +} +inline void set_timer_prescaler(volatile apb3timer_t *reg, uint16_t value){ + reg->PRESCALER = (reg->PRESCALER & ~(0xffffU << 0)) | (value << 0); +} +inline uint32_t get_timer_t0_ctrl_enable(volatile apb3timer_t *reg){ + return (reg->T0_CTRL >> 0) & 0x7; +} +inline void set_timer_t0_ctrl_enable(volatile apb3timer_t *reg, uint8_t value){ + reg->T0_CTRL = (reg->T0_CTRL & ~(0x7U << 0)) | (value << 0); +} +inline uint32_t get_timer_t0_ctrl_clear(volatile apb3timer_t *reg){ + return (reg->T0_CTRL >> 3) & 0x3; +} +inline void set_timer_t0_ctrl_clear(volatile apb3timer_t *reg, uint8_t value){ + reg->T0_CTRL = (reg->T0_CTRL & ~(0x3U << 3)) | (value << 3); +} +inline uint32_t get_timer_t0_overflow(volatile apb3timer_t *reg){ + return (reg->T0_OVERFLOW >> 0) & 0xffffffff; +} +inline void set_timer_t0_overflow(volatile apb3timer_t *reg, uint32_t value){ + reg->T0_OVERFLOW = (reg->T0_OVERFLOW & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_timer_t0_value(volatile apb3timer_t *reg){ + return (reg->T0_VALUE >> 0) & 0xffffffff; +} +inline uint32_t get_timer_t1_ctrl_enable(volatile apb3timer_t *reg){ + return (reg->T1_CTRL >> 0) & 0x7; +} +inline void set_timer_t1_ctrl_enable(volatile apb3timer_t *reg, uint8_t value){ + reg->T1_CTRL = (reg->T1_CTRL & ~(0x7U << 0)) | (value << 0); +} +inline uint32_t get_timer_t1_ctrl_clear(volatile apb3timer_t *reg){ + return (reg->T1_CTRL >> 3) & 0x3; +} +inline void set_timer_t1_ctrl_clear(volatile apb3timer_t *reg, uint8_t value){ + reg->T1_CTRL = (reg->T1_CTRL & ~(0x3U << 3)) | (value << 3); +} +inline uint32_t get_timer_t1_overflow(volatile apb3timer_t *reg){ + return (reg->T1_OVERFLOW >> 0) & 0xffffffff; +} +inline void set_timer_t1_overflow(volatile apb3timer_t *reg, uint32_t value){ + reg->T1_OVERFLOW = (reg->T1_OVERFLOW & ~(0xffffffffU << 0)) | (value << 0); +} +inline uint32_t get_timer_t1_value(volatile apb3timer_t *reg){ + return (reg->T1_VALUE >> 0) & 0xffffffff; +} +#endif /* _BSP_APB3TIMER_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gen/Apb3Uart.h b/include/ehrenberg/devices/gen/Apb3Uart.h new file mode 100644 index 0000000..e5d9bee --- /dev/null +++ b/include/ehrenberg/devices/gen/Apb3Uart.h @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2023 - 2024 MINRES Technologies GmbH +* +* SPDX-License-Identifier: Apache-2.0 +* +* Generated at 2024-02-19 14:24:37 UTC +* by peakrdl_mnrs version 1.2.2 +*/ + +#ifndef _BSP_APB3UART_H +#define _BSP_APB3UART_H + +#include + +typedef struct __attribute((__packed__)) { + 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; +}apb3uart_t; + +inline uint32_t get_uart_rx_tx_reg_data(volatile apb3uart_t *reg){ + return (reg->RX_TX_REG >> 0) & 0xff; +} +inline void set_uart_rx_tx_reg_data(volatile apb3uart_t *reg, uint8_t value){ + reg->RX_TX_REG = (reg->RX_TX_REG & ~(0xffU << 0)) | (value << 0); +} +inline uint32_t get_uart_rx_tx_reg_rx_avail(volatile apb3uart_t *reg){ + return (reg->RX_TX_REG >> 14) & 0x1; +} +inline uint32_t get_uart_rx_tx_reg_tx_free(volatile apb3uart_t *reg){ + return (reg->RX_TX_REG >> 15) & 0x1; +} +inline uint32_t get_uart_int_ctrl_reg_write_intr_enable(volatile apb3uart_t *reg){ + return (reg->INT_CTRL_REG >> 0) & 0x1; +} +inline void set_uart_int_ctrl_reg_write_intr_enable(volatile apb3uart_t *reg, uint8_t value){ + reg->INT_CTRL_REG = (reg->INT_CTRL_REG & ~(0x1U << 0)) | (value << 0); +} +inline uint32_t get_uart_int_ctrl_reg_read_intr_enable(volatile apb3uart_t *reg){ + return (reg->INT_CTRL_REG >> 1) & 0x1; +} +inline void set_uart_int_ctrl_reg_read_intr_enable(volatile apb3uart_t *reg, uint8_t value){ + reg->INT_CTRL_REG = (reg->INT_CTRL_REG & ~(0x1U << 1)) | (value << 1); +} +inline uint32_t get_uart_int_ctrl_reg_write_intr_pend(volatile apb3uart_t *reg){ + return (reg->INT_CTRL_REG >> 8) & 0x1; +} +inline uint32_t get_uart_int_ctrl_reg_read_intr_pend(volatile apb3uart_t *reg){ + return (reg->INT_CTRL_REG >> 9) & 0x1; +} +inline uint32_t get_uart_clk_divider_reg(volatile apb3uart_t *reg){ + return (reg->CLK_DIVIDER_REG >> 0) & 0xfffff; +} +inline void set_uart_clk_divider_reg(volatile apb3uart_t *reg, uint32_t value){ + reg->CLK_DIVIDER_REG = (reg->CLK_DIVIDER_REG & ~(0xfffffU << 0)) | (value << 0); +} +inline uint32_t get_uart_frame_config_reg_data_lenght(volatile apb3uart_t *reg){ + return (reg->FRAME_CONFIG_REG >> 0) & 0x7; +} +inline void set_uart_frame_config_reg_data_lenght(volatile apb3uart_t *reg, uint8_t value){ + reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x7U << 0)) | (value << 0); +} +inline uint32_t get_uart_frame_config_reg_parity(volatile apb3uart_t *reg){ + return (reg->FRAME_CONFIG_REG >> 3) & 0x3; +} +inline void set_uart_frame_config_reg_parity(volatile apb3uart_t *reg, uint8_t value){ + reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x3U << 3)) | (value << 3); +} +inline uint32_t get_uart_frame_config_reg_stop_bit(volatile apb3uart_t *reg){ + return (reg->FRAME_CONFIG_REG >> 5) & 0x1; +} +inline void set_uart_frame_config_reg_stop_bit(volatile apb3uart_t *reg, uint8_t value){ + reg->FRAME_CONFIG_REG = (reg->FRAME_CONFIG_REG & ~(0x1U << 5)) | (value << 5); +} +inline uint32_t get_uart_status_reg_read_error(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 0) & 0x1; +} +inline uint32_t get_uart_status_reg_stall(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 1) & 0x1; +} +inline uint32_t get_uart_status_reg_break(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 8) & 0x1; +} +inline uint32_t get_uart_status_reg_break_detected(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 9) & 0x1; +} +inline void set_uart_status_reg_break_detected(volatile apb3uart_t *reg, uint8_t value){ + reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 9)) | (value << 9); +} +inline uint32_t get_uart_status_reg_set_break(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 10) & 0x1; +} +inline void set_uart_status_reg_set_break(volatile apb3uart_t *reg, uint8_t value){ + reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 10)) | (value << 10); +} +inline uint32_t get_uart_status_reg_clear_break(volatile apb3uart_t *reg){ + return (reg->STATUS_REG >> 11) & 0x1; +} +inline void set_uart_status_reg_clear_break(volatile apb3uart_t *reg, uint8_t value){ + reg->STATUS_REG = (reg->STATUS_REG & ~(0x1U << 11)) | (value << 11); +} +#endif /* _BSP_APB3UART_H */ \ No newline at end of file diff --git a/include/ehrenberg/devices/gpio.h b/include/ehrenberg/devices/gpio.h index cabf657..26135da 100644 --- a/include/ehrenberg/devices/gpio.h +++ b/include/ehrenberg/devices/gpio.h @@ -2,16 +2,13 @@ #define _BSP_GPIO_H #include +#include "gen/Apb3Gpio.h" -typedef struct __attribute((__packed__)) { - volatile uint32_t pin_in; - volatile uint32_t pin_out; - volatile uint32_t out_en; -} gpio_t; +#define gpio_t apb3gpio_t inline void gpio_init(gpio_t* reg) { - reg->out_en=0; - reg->pin_out=0; + set_gpio_write(reg, 0); + set_gpio_writeEnable(reg, 0); } #endif /* _BSP_GPIO_H */ diff --git a/include/ehrenberg/devices/interrupt.h b/include/ehrenberg/devices/interrupt.h index b395f14..21e76db 100644 --- a/include/ehrenberg/devices/interrupt.h +++ b/include/ehrenberg/devices/interrupt.h @@ -2,15 +2,13 @@ #define _BSP_INTERRUPT_H #include +#include "gen/Apb3IrqCtrl.h" -typedef struct __attribute((__packed__)) { - volatile uint32_t ip; - volatile uint32_t ie; -} irq_t; +#define irq_t apb3irqctrl_t inline void irq_init(irq_t* reg){ - reg->ie = 0; - reg->ip = 0xFFFFFFFF; + set_irq_masksReg(reg, 0); + set_irq_pendingsReg(reg, 0xff); } #endif /* _BSP_INTERRUPT_H */ diff --git a/include/ehrenberg/devices/qspi.h b/include/ehrenberg/devices/qspi.h index f4f11bc..f651077 100644 --- a/include/ehrenberg/devices/qspi.h +++ b/include/ehrenberg/devices/qspi.h @@ -2,31 +2,9 @@ #define _BSP_QSPI_H #include +#include "gen/Apb3SpiXdrMasterCtrl.h" -#define __IO volatile - -typedef struct { - __IO uint32_t data; // 0x0/0: data, 8bits, 8:write, 9:read, 11:data/ctrl, 31:rxdata valid - __IO uint32_t status; // 0x4/0: txavail, 16: rxused - __IO uint32_t config; // 0x8/0:1 cpol/cpha, 4: transfer mode (0-FullDuplex) - __IO uint32_t intr; // 0xc/0: txien, 1: rxien, 8: txip, 9: rxip, 16: valid? - __IO uint32_t __fill0[4]; - __IO uint32_t clk_divider; // 0x20/0: sclkToogle - // ssGen config - __IO uint32_t ss_setup; // 0x24/0: setup - __IO uint32_t ss_hold; // 0x28/0: hold - __IO uint32_t ss_disable; // 0x2c/0: disable - __IO uint32_t ss_activeHigh; // 0x30/0: disable - __IO uint32_t __fill1[3]; - __IO uint32_t xip_enable; // 0x40/0: enable - __IO uint32_t xip_instr; // 0x44/0:7 data, 8: enable, 16:23 dummy data, 24:27 dummy count - __IO uint32_t xip_mode; // 0x48/0: instr transfer mode, 8: addr transfer mode, 16: dummy transfer mode, 24: data transfer mode - __IO uint32_t __fill2[2]; - __IO uint32_t xip_write32; // 0x50 - __IO uint32_t xip_readwrite32; // 0x54 - __IO uint32_t xip_read32; // 0x58 -} __attribute((__packed__)) qspi_t; - +#define qspi_t apb3spixdrmasterctrl_t typedef struct { uint32_t cpol; uint32_t cpha; @@ -49,11 +27,11 @@ typedef struct { #define SPI_STATUS_RSP_INT_FLAG = (1 << 9) static inline void spi_configure(volatile qspi_t* reg, spi_cfg *config){ - reg->config = (config->cpol << 0) | (config->cpha << 1) | (config->mode << 4); - reg->clk_divider = config->clkDivider; - reg->ss_setup = config->ssSetup; - reg->ss_hold = config->ssHold; - reg->ss_disable =config->ssDisable; + reg->CONFIG = (config->cpol << 0) | (config->cpha << 1) | (config->mode << 4); + reg->SCLK_CONFIG = config->clkDivider; + reg->SSGEN_SETUP = config->ssSetup; + reg->SSGEN_HOLD = config->ssHold; + reg->SSGEN_DISABLE = config->ssDisable; } static inline void spi_init(volatile qspi_t* spi){ @@ -69,41 +47,41 @@ static inline void spi_init(volatile qspi_t* spi){ } static inline uint32_t spi_cmd_avail(volatile qspi_t* reg){ - return reg->status & 0xFFFF; + return reg->STATUS & 0xFFFF; } static inline uint32_t spi_rsp_occupied(volatile qspi_t* reg){ - return reg->status >> 16; + return reg->STATUS >> 16; } static inline void spi_write(volatile qspi_t* reg, uint8_t data){ while(spi_cmd_avail(reg) == 0); - reg->data = data | SPI_CMD_WRITE; + reg->DATA = data | SPI_CMD_WRITE; } static inline uint8_t spi_write_read(volatile qspi_t* reg, uint8_t data){ while(spi_cmd_avail(reg) == 0); - reg->data = data | SPI_CMD_READ | SPI_CMD_WRITE; + reg->DATA = data | SPI_CMD_READ | SPI_CMD_WRITE; while(spi_rsp_occupied(reg) == 0); - return reg->data; + return reg->DATA; } static inline uint8_t spi_read(volatile qspi_t* reg){ while(spi_cmd_avail(reg) == 0); - reg->data = SPI_CMD_READ; + reg->DATA = SPI_CMD_READ; while(spi_rsp_occupied(reg) == 0); - while((reg->data & 0x80000000)==0); - return reg->data; + while((reg->DATA & 0x80000000)==0); + return reg->DATA; } static inline void spi_select(volatile qspi_t* reg, uint32_t slaveId){ while(spi_cmd_avail(reg) == 0); - reg->data = slaveId | 0x80 | SPI_CMD_SS; + reg->DATA = slaveId | 0x80 | SPI_CMD_SS; } static inline void spi_deselect(volatile qspi_t* reg, uint32_t slaveId){ while(spi_cmd_avail(reg) == 0); - reg->data = slaveId | SPI_CMD_SS; + reg->DATA = slaveId | SPI_CMD_SS; } static inline void spi_wait_tx_idle(volatile qspi_t* reg){ diff --git a/include/ehrenberg/devices/timer.h b/include/ehrenberg/devices/timer.h index 48024c4..57d2d0d 100644 --- a/include/ehrenberg/devices/timer.h +++ b/include/ehrenberg/devices/timer.h @@ -1,52 +1,19 @@ #ifndef _BSP_TIMER_H #define _BSP_TIMER_H +#include "gen/Apb3Timer.h" #include -typedef struct __attribute((__packed__)) { - volatile uint32_t mtime; // 0x0:0 - volatile uint32_t mtimeh; // 0x4:0 - volatile uint32_t mtimecmp; // 0x8:0 - volatile uint32_t mtimecmph; // 0xc:0 -} mtimer_t; - -#ifndef APB_BUS -typedef struct __attribute((__packed__)) { - volatile uint16_t count; -} prescaler_t; - -typedef struct __attribute((__packed__)) { - volatile uint16_t clk_en; // 0x0:0, 0->always, 1->prescaler - volatile uint16_t clr_en; // 0x2:0, 0->on overflow - volatile uint32_t limit; // 0x4:0, upper limit of counter - volatile uint32_t timer_value; // 0x8:0 current timer value -} timer_a_t; - -#else - -typedef struct __attribute((__packed__)) { - volatile uint32_t LIMIT; -} prescaler_t; - -typedef struct __attribute((__packed__)) { - volatile uint32_t CLEARS_TICKS; // 0x0/0:0->always, 1->prescaler; 16:0->on overflow - volatile uint32_t LIMIT; // 0x4/0 upper limit of counter - volatile uint32_t VALUE; // 0x8/0 current timer value -} timer_a_t; - -inline void prescaler_init(prescaler_t* reg){ - (void)reg; +inline void prescaler_init(apb3timer_t *reg, uint16_t value) { + set_timer_prescaler(reg, value); } -inline void timer_init(timer_a_t *reg){ - reg->CLEARS_TICKS = 0; - reg->VALUE = 0; +inline void timer_t0__init(apb3timer_t *reg) { + set_timer_t0_overflow(reg, 0xffffffff); } -inline void mtimer_init(mtimer_t *reg){ - reg->mtimecmph = UINT32_MAX; - reg->mtimecmp = UINT32_MAX; +inline void timer_t1__init(apb3timer_t *reg) { + set_timer_t1_overflow(reg, 0xffffffff); } -#endif #endif /* _BSP_TIMER_H */ diff --git a/include/ehrenberg/devices/uart.h b/include/ehrenberg/devices/uart.h index 3017062..e03b67f 100644 --- a/include/ehrenberg/devices/uart.h +++ b/include/ehrenberg/devices/uart.h @@ -2,66 +2,27 @@ #define _BSP_UART_H #include +#include "gen/Apb3Uart.h" -enum uart_parity_e {NONE = 0, EVEN = 1, ODD = 2}; -enum uart_stop_e {ONE = 0, TWO = 1}; - -#ifndef APB_BUS -typedef struct __attribute((__packed__)){ - // 0x0 - volatile uint16_t rx_tx_reg; // 8bit, 0x0 - volatile uint16_t rx_avail; // 1bit, 0x0:16 - // 0x4 - volatile uint16_t irq_ctrl; // 0->tx_ie, 1->rx_ie, 8->tx_ip, 9->rx_ip - volatile uint8_t num_tx_avail; // 8bit, 0x4:16 - volatile uint8_t num_rx_avail; // 8bit, 0x4:24 - volatile uint32_t dummy; - // 0xc - volatile uint8_t clock_div; // 3bit, 0xc:0 - volatile uint8_t frame; // 2bit, 0xc:8 - volatile uint8_t stop_bits; // 1bit, 0xc:16 - // 0x10 - volatile uint8_t status; // readError->0, readOverflowError->1, - volatile uint8_t active; // rx_active->0, tx_active-1, set_tx_active->2, clear_tx_active->3 -} uart_t; -#else -typedef struct __attribute((__packed__)) { - volatile uint32_t DATA; - volatile uint32_t STATUS; - volatile uint32_t CLOCK_DIVIDER; - volatile uint32_t FRAME_CONFIG; -} uart_t; - - -typedef struct __attribute((__packed__)) { - uint32_t data_length; - enum uart_parity_e parity; - enum uart_stop_e stop; - uint32_t clock_divider; -} uart_config_t; +#define uart_t apb3uart_t static inline uint32_t uart_get_tx_free(volatile uart_t *reg){ - return (reg->STATUS >> 16) & 0xFF; + return (reg->STATUS_REG >> 16) & 0xFF; } static inline uint32_t uart_get_rx_avail(volatile uart_t *reg){ - return reg->STATUS >> 24; + return reg->STATUS_REG >> 24; } -static void uart_write(volatile uart_t *reg, uint8_t data){ - while(uart_get_tx_free(reg) == 0); - reg->DATA = data; +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 = reg->DATA; - while((res&0x10000) == 0) res = reg->DATA; +static inline 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; } -static inline void uart_set_config(volatile uart_t *reg, uart_config_t *config){ - reg->CLOCK_DIVIDER = config->clock_divider; - reg->FRAME_CONFIG = ((config->data_length-1) << 0) | (config->parity << 8) | (config->stop << 16); -} -#endif #endif /* _BSP_UART_H */ diff --git a/libwrap/sys/puts.c b/libwrap/sys/puts.c index bb07468..cdba1c9 100644 --- a/libwrap/sys/puts.c +++ b/libwrap/sys/puts.c @@ -1,9 +1,9 @@ /* See LICENSE of license details. */ -#include #include -#include +#include #include +#include #include "../../include/tgc-vp/devices/uart.h" #include "../../env/tgc-vp/platform.h" @@ -12,26 +12,28 @@ #include "weak_under_alias.h" #include "semihosting.h" -int __wrap_puts(const char *s) -{ +int __wrap_puts(const char *s) { #if defined(SEMIHOSTING) sh_write0(s); return 0; #endif while (*s != '\0') { -#if defined(BOARD_ehrenberg) - while (uart_get_tx_free(uart)==0) ; +#if defined(BOARD_ehrenberg) || defined(BOARD_tgc_vp) + while (get_uart_rx_tx_reg_tx_free(uart) == 0) + ; uart_write(uart, *s); #elif defined(BOARD_iss) - *((uint32_t*) 0xFFFF0000) = *s; -#elif defined(BOARD_TGC5L) - //TODO: implement + *((uint32_t *)0xFFFF0000) = *s; +#elif defined(BOARD_TGCP) + // TODO: implement #else - while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) + ; UART0_REG(UART_REG_TXFIFO) = *s; if (*s == '\n') { - while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) + ; UART0_REG(UART_REG_TXFIFO) = '\r'; } #endif diff --git a/libwrap/sys/read.c b/libwrap/sys/read.c index 6fb9469..2f01ea7 100644 --- a/libwrap/sys/read.c +++ b/libwrap/sys/read.c @@ -14,53 +14,51 @@ #include "weak_under_alias.h" #include "semihosting.h" -ssize_t __wrap_read(int fd, void* ptr, size_t len) -{ +ssize_t __wrap_read(int fd, void* ptr, size_t len) { uint8_t * current = (uint8_t *)ptr; #if defined(SEMIHOSTING) sh_read(current, fd, len); return; #endif #if defined(BOARD_hifive1) - volatile uint32_t * uart_rx = (uint32_t *)(UART0_CTRL_ADDR + UART_REG_RXFIFO); - volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_CTRL_ADDR + UART_REG_RXCTRL + 2); + volatile uint32_t *uart_rx = (uint32_t *)(UART0_CTRL_ADDR + UART_REG_RXFIFO); + volatile uint8_t *uart_rx_cnt = + (uint8_t *)(UART0_CTRL_ADDR + UART_REG_RXCTRL + 2); #elif defined(BOARD_iss) - volatile uint32_t * uart_rx = (uint32_t*)0xFFFF0000; -#elif defined(BOARD_TGC5L) - //TODO: implement -#elif !defined(BOARD_ehrenberg) - volatile uint32_t * uart_rx = (uint32_t *)(UART0_BASE_ADDR + UART_REG_RXFIFO); - volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_BASE_ADDR + UART_REG_RXCTRL + 2); + volatile uint32_t *uart_rx = (uint32_t *)0xFFFF0000; +#elif defined(BOARD_TGCP) + // TODO: implement +#elif !defined(BOARD_ehrenberg) && !defined(BOARD_tgc_vp) + volatile uint32_t *uart_rx = (uint32_t *)(UART0_BASE_ADDR + UART_REG_RXFIFO); + volatile uint8_t *uart_rx_cnt = + (uint8_t *)(UART0_BASE_ADDR + UART_REG_RXCTRL + 2); #endif - ssize_t result = 0; - if (isatty(fd)) { -#if defined(BOARD_ehrenberg) - for (current = (uint8_t *)ptr; - (current < ((uint8_t *)ptr) + len) && (uart_get_rx_avail(uart) > 0); - current ++) { - *current = uart_read(uart); - result++; - } -#elif defined(BOARD_iss) - for (current = (uint8_t *)ptr; - (current < ((uint8_t *)ptr) + len); - current ++) { - *current = *uart_rx; - result++; - } -#elif defined(BOARD_TGC5L) - //TODO: implement -#else - for (current = (uint8_t *)ptr; - (current < ((uint8_t *)ptr) + len) && (*uart_rx_cnt > 0); - current ++) { - *current = *uart_rx; - result++; - } -#endif - return result; + ssize_t result = 0; + if (isatty(fd)) { +#if defined(BOARD_ehrenberg) || defined(BOARD_tgc_vp) + for (current = (uint8_t *)ptr; (current < ((uint8_t *)ptr) + len) && + (get_uart_rx_tx_reg_rx_avail(uart) > 0); + current++) { + *current = uart_read(uart); + result++; } - return _stub(EBADF); +#elif defined(BOARD_iss) + for (current = (uint8_t *)ptr; (current < ((uint8_t *)ptr) + len); + current++) { + *current = *uart_rx; + result++; + } +#elif defined(BOARD_TGCP) + // TODO: implement +#else + for (current = (uint8_t *)ptr; + (current < ((uint8_t *)ptr) + len) && (*uart_rx_cnt > 0); current++) { + *current = *uart_rx; + result++; + } +#endif + return result; + } + return _stub(EBADF); } weak_under_alias(read); - diff --git a/libwrap/sys/write.c b/libwrap/sys/write.c index 96b3013..b2af87d 100644 --- a/libwrap/sys/write.c +++ b/libwrap/sys/write.c @@ -1,9 +1,9 @@ /* See LICENSE of license details. */ -#include #include -#include +#include #include +#include #include "../../include/tgc-vp/devices/uart.h" #include "../../env/tgc-vp/platform.h" @@ -12,47 +12,50 @@ #include "weak_under_alias.h" #include "semihosting.h" -ssize_t __wrap_write(int fd, const void* ptr, size_t len) -{ - const uint8_t * current = (const uint8_t *)ptr; +ssize_t __wrap_write(int fd, const void* ptr, size_t len) { + const uint8_t * current = (const uint8_t *)ptr; #if defined(SEMIHOSTING) - if(isatty(fd)) { - for (size_t jj = 0; jj < len; jj++) { - sh_writec(current[jj]); - } - return len; - } else { - sh_write(current, fd); - return len; - } - //return len; + if(isatty(fd)) { + for (size_t jj = 0; jj < len; jj++) { + sh_writec(current[jj]); + } + return len; + } else { + sh_write(current, fd); + return len; + } + //return len; #endif - if (isatty(fd)) { - for (size_t jj = 0; jj < len; jj++) { -#if defined(BOARD_ehrenberg) - while (uart_get_tx_free(uart)==0) ; - uart_write(uart, current[jj]); - if (current[jj] == '\n') { - while (uart_get_tx_free(uart)==0) ; - uart_write(uart, '\r'); - } + if (isatty(fd)) { + for (size_t jj = 0; jj < len; jj++) { +#if defined(BOARD_ehrenberg) || defined(BOARD_tgc_vp) + while (get_uart_rx_tx_reg_tx_free(uart) == 0) + ; + uart_write(uart, current[jj]); + if (current[jj] == '\n') { + while (get_uart_rx_tx_reg_tx_free(uart) == 0) + ; + uart_write(uart, '\r'); + } #elif defined(BOARD_iss) - *((uint32_t*) 0xFFFF0000) = current[jj]; -#elif defined(BOARD_TGC5L) - //TODO: implement + *((uint32_t *)0xFFFF0000) = current[jj]; +#elif defined(BOARD_TGCP) + // TODO: implement #else - while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; - UART0_REG(UART_REG_TXFIFO) = current[jj]; + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) + ; + UART0_REG(UART_REG_TXFIFO) = current[jj]; - if (current[jj] == '\n') { - while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; - UART0_REG(UART_REG_TXFIFO) = '\r'; - } + if (current[jj] == '\n') { + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) + ; + UART0_REG(UART_REG_TXFIFO) = '\r'; + } #endif - } - return len; } + return len; + } - return _stub(EBADF); + return _stub(EBADF); } weak_under_alias(write); diff --git a/newlib-nano/lib.mk b/newlib-nano/lib.mk index 986132d..155142e 100644 --- a/newlib-nano/lib.mk +++ b/newlib-nano/lib.mk @@ -6,11 +6,17 @@ NANO_LIB_DIR := $(dir $(lastword $(MAKEFILE_LIST))) NANO_LIB_SYMS := read write syscalls +#NANO_LIB_SRCS := $(foreach s,$(NANO_LIB_SYMS),$(s).c) NANO_LIB_SRCS := $(foreach s,$(NANO_LIB_SYMS),$(NANO_LIB_DIR)/$(s).c) #NANO_LIB_SRCS := $(foreach f,$(LIB_SRCS),$(LIB_DIR)/$(f)) NANO_LIB_OBJS := $(NANO_LIB_SRCS:.c=.o) +NANO_LIB := libnano_cust.a CLEAN_OBJS += $(NANO_LIB_OBJS) $(NANO_LIB_OBJS): %.o: %.c $(HEADERS) $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +$(NANO_LIB): $(NANO_LIB_OBJS) + $(AR) rcs $@ $^ + \ No newline at end of file