From 88bd754dd6864fe38373a619b09efa484c4fcb3c Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 10 Dec 2020 17:14:30 +0100 Subject: [PATCH] software: add minimal baremetal demo app. Used to demonstrates how to easily create baremetal apps, boot to it with LiteX and also ease litex_term testing. To build it: export BUILD_DIR=xxyy/litex/litex/boards/targets/build/arty && make To load it: lxterm /dev/ttyUSB1 --kernel=demo.bin --============== Boot ==================-- Booting from serial... Press Q or ESC to abort boot completely. sL5DdSMmkekro [LXTERM] Received firmware download request from the device. [LXTERM] Uploading demo.bin to 0x40000000 (9264 bytes)... [LXTERM] Upload complete (9.8KB/s). [LXTERM] Booting the device. [LXTERM] Done. Executing booted program at 0x40000000 --============= Liftoff! ===============-- LiteX minimal demo app built Dec 10 2020 17:13:02 Available commands: help - Show this command reboot - Reboot CPU led - Led demo donut - Spinning Donut demo litex-demo-app> led Led demo... Counter mode... Shift mode... Dance mode... litex-demo-app> donut Donut demo... $$$$$@@@@@ $##########$$$$$$$$ ###*!!!!!!!!!***##$$$$$$ ***!!====;;;;===!!**###$$$$# **!===;;;:::::;:===!!**####$## !*!!==;;:~-,,.,-~::;;=!!**#######! !!!!=;:~-,.......-~::==!!***#####* !!!!==;~~-.........,-:;==!!***###**! !**!!=;:~-... ..-:;=!!!********! ;!*#####*!!;. ~:;==!!!******!!= :!*###$$$$#*! :;==!!!!!****!!!=; ~=!*#$$$@@@$$##!!!!!!!!!!!!****!!!!=; ;=!*#$$$@@@@$$#*******!*!!*!!!!!==;~ -;!*###$$$$$$$###******!!!!!!!===;~ -;!!*####$#####******!!!!!!==;;:- ,:=!!!!**#**#***!!!!!!!====;:~, -:==!!!*!!*!!!!!!!===;;;:~- .~:;;========;=;;:::~-, .--~~::::~:~~--,. litex-demo-app> --- litex/soc/software/demo/Makefile | 42 +++++++ litex/soc/software/demo/donut.c | 67 ++++++++++++ litex/soc/software/demo/isr.c | 29 +++++ litex/soc/software/demo/linker.ld | 56 ++++++++++ litex/soc/software/demo/main.c | 176 ++++++++++++++++++++++++++++++ 5 files changed, 370 insertions(+) create mode 100644 litex/soc/software/demo/Makefile create mode 100644 litex/soc/software/demo/donut.c create mode 100644 litex/soc/software/demo/isr.c create mode 100644 litex/soc/software/demo/linker.ld create mode 100644 litex/soc/software/demo/main.c diff --git a/litex/soc/software/demo/Makefile b/litex/soc/software/demo/Makefile new file mode 100644 index 000000000..fa236d2fe --- /dev/null +++ b/litex/soc/software/demo/Makefile @@ -0,0 +1,42 @@ +BUILD_DIR?=../build/ + +include $(BUILD_DIR)/software/include/generated/variables.mak +include $(SOC_DIRECTORY)/software/common.mak + +OBJECTS=isr.o donut.o main.o + +all: demo.bin + +# pull in dependency info for *existing* .o files +-include $(OBJECTS:.o=.d) + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ + chmod -x $@ + +demo.elf: $(OBJECTS) + $(LD) $(LDFLAGS) \ + -T linker.ld \ + -N -o $@ \ + $(BUILD_DIR)/software/libbase/crt0.o \ + $(OBJECTS) \ + -L$(BUILD_DIR)/software/libbase \ + -L$(BUILD_DIR)/software/libcompiler_rt \ + -lbase-nofloat -lcompiler_rt + chmod -x $@ + +main.o: main.c + $(compile) + +donut.o: CFLAGS += -w + +%.o: %.c + $(compile) + +%.o: %.S + $(assemble) + +clean: + $(RM) $(OBJECTS) $(OBJECTS:.o=.d) demo.elf demo.bin .*~ *~ + +.PHONY: all main.o clean load diff --git a/litex/soc/software/demo/donut.c b/litex/soc/software/demo/donut.c new file mode 100644 index 000000000..956c38040 --- /dev/null +++ b/litex/soc/software/demo/donut.c @@ -0,0 +1,67 @@ +// The donut code with fixed-point arithmetic; no sines, cosines, square roots, or anything. +// a1k0n 2020 +// Code from: https://gist.github.com/a1k0n/80f48aa8911fffd805316b8ba8f48e83 +// For more info: +// - https://www.a1k0n.net/2011/07/20/donut-math.html +// - https://www.youtube.com/watch?v=DEqXNfs_HhY + +#include +#include +#include + +#include + +#define R(mul,shift,x,y) \ + _=x; \ + x -= mul*y>>shift; \ + y += mul*_>>shift; \ + _ = 3145728-x*x-y*y>>11; \ + x = x*_>>10; \ + y = y*_>>10; + +signed char b[1760], z[1760]; + +void donut(void) { + int sA=1024,cA=0,sB=1024,cB=0,_; + for (;;) { + memset(b, 32, 1760); // text buffer + memset(z, 127, 1760); // z buffer + int sj=0, cj=1024; + for (int j = 0; j < 90; j++) { + int si = 0, ci = 1024; // sine and cosine of angle i + for (int i = 0; i < 324; i++) { + int R1 = 1, R2 = 2048, K2 = 5120*1024; + + int x0 = R1*cj + R2, + x1 = ci*x0 >> 10, + x2 = cA*sj >> 10, + x3 = si*x0 >> 10, + x4 = R1*x2 - (sA*x3 >> 10), + x5 = sA*sj >> 10, + x6 = K2 + R1*1024*x5 + cA*x3, + x7 = cj*si >> 10, + x = 40 + 30*(cB*x1 - sB*x4)/x6, + y = 12 + 15*(cB*x4 + sB*x1)/x6, + N = (-cA*x7 - cB*((-sA*x7>>10) + x2) - ci*(cj*sB >> 10) >> 10) - x5 >> 7; + + int o = x + 80 * y; + signed char zz = (x6-K2)>>15; + if (22 > y && y > 0 && x > 0 && 80 > x && zz < z[o]) { + z[o] = zz; + b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0]; + } + R(5, 8, ci, si) // rotate i + } + R(9, 7, cj, sj) // rotate j + } + for (int k = 0; 1761 > k; k++) + putchar(k % 80 ? b[k] : 10); + R(5, 7, cA, sA); + R(5, 8, cB, sB); + if (readchar_nonblock()) { + readchar(); + break; + } + putsnonl("\x1b[23A"); + } +} \ No newline at end of file diff --git a/litex/soc/software/demo/isr.c b/litex/soc/software/demo/isr.c new file mode 100644 index 000000000..8bdbd84c2 --- /dev/null +++ b/litex/soc/software/demo/isr.c @@ -0,0 +1,29 @@ +// This file is Copyright (c) 2020 Florent Kermarrec +// License: BSD + +#include +#include +#include +#include + +void isr(void); + +#ifdef CONFIG_CPU_HAS_INTERRUPT + +void isr(void) +{ + __attribute__((unused)) unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + +#ifndef UART_POLLING + if(irqs & (1 << UART_INTERRUPT)) + uart_isr(); +#endif +} + +#else + +void isr(void){}; + +#endif diff --git a/litex/soc/software/demo/linker.ld b/litex/soc/software/demo/linker.ld new file mode 100644 index 000000000..36af68283 --- /dev/null +++ b/litex/soc/software/demo/linker.ld @@ -0,0 +1,56 @@ +INCLUDE generated/output_format.ld +ENTRY(_start) + +__DYNAMIC = 0; + +INCLUDE generated/regions.ld + +SECTIONS +{ + .text : + { + _ftext = .; + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > main_ram + + .rodata : + { + . = ALIGN(4); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + _erodata = .; + } > main_ram + + .data : + { + . = ALIGN(4); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + _gp = ALIGN(16); + *(.sdata .sdata.* .gnu.linkonce.s.*) + _edata = .; + } > main_ram + + .bss : + { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + } > sram +} + +PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4); + +PROVIDE(_fdata_rom = LOADADDR(.data)); +PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data)); diff --git a/litex/soc/software/demo/main.c b/litex/soc/software/demo/main.c new file mode 100644 index 000000000..89f369cc5 --- /dev/null +++ b/litex/soc/software/demo/main.c @@ -0,0 +1,176 @@ +// This file is Copyright (c) 2020 Florent Kermarrec +// License: BSD + +#include +#include +#include + +#include +#include +#include +#include + +/*-----------------------------------------------------------------------*/ +/* Uart */ +/*-----------------------------------------------------------------------*/ + +static char *readstr(void) +{ + char c[2]; + static char s[64]; + static int ptr = 0; + + if(readchar_nonblock()) { + c[0] = readchar(); + c[1] = 0; + switch(c[0]) { + case 0x7f: + case 0x08: + if(ptr > 0) { + ptr--; + putsnonl("\x08 \x08"); + } + break; + case 0x07: + break; + case '\r': + case '\n': + s[ptr] = 0x00; + putsnonl("\n"); + ptr = 0; + return s; + default: + if(ptr >= (sizeof(s) - 1)) + break; + putsnonl(c); + s[ptr] = c[0]; + ptr++; + break; + } + } + + return NULL; +} + +static char *get_token(char **str) +{ + char *c, *d; + + c = (char *)strchr(*str, ' '); + if(c == NULL) { + d = *str; + *str = *str+strlen(*str); + return d; + } + *c = 0; + d = *str; + *str = c+1; + return d; +} + +static void prompt(void) +{ + printf("\e[92;1mlitex-demo-app\e[0m> "); +} + +/*-----------------------------------------------------------------------*/ +/* Help */ +/*-----------------------------------------------------------------------*/ + +static void help(void) +{ + puts("\nLiteX minimal demo app built "__DATE__" "__TIME__"\n"); + puts("Available commands:"); + puts("help - Show this command"); + puts("reboot - Reboot CPU"); + puts("led - Led demo"); + puts("donut - Spinning Donut demo"); +} + +/*-----------------------------------------------------------------------*/ +/* Commands */ +/*-----------------------------------------------------------------------*/ + +static void reboot_cmd(void) +{ + ctrl_reset_write(1); +} + +static void led_cmd(void) +{ + int i; + printf("Led demo...\n"); + + printf("Counter mode...\n"); + for(i=0; i<32; i++) { + leds_out_write(i); + busy_wait(100); + } + + printf("Shift mode...\n"); + for(i=0; i<4; i++) { + leds_out_write(1<