Now w/ RAM load stuff included ...

master
kaqu 2 years ago
parent 88064133e3
commit 8bb4a4d5e2
  1. 2
      .gitignore
  2. 69
      helpers/prepare_firmware.py
  3. 154
      software/illumination.c
  4. 8
      software/illumination.h
  5. 85
      software/linker/linker.ld
  6. 1
      software/linker/output_format.ld
  7. 80
      software/ramcreate.sh
  8. 94
      software/ramtest.c

2
.gitignore vendored

@ -1,4 +1,4 @@
build/*
__pycache__/*
backup/*
software/*
software/build/*

@ -4,7 +4,7 @@
# prepare_firmware.py
#
# Utility to temporarily move project local resources to LiteX path
# (w/ backing up of original data of nec.)
# (w/ backing up of original data if nec.)
#
# History:
# --------
@ -18,53 +18,40 @@ import litex.soc
relpath = "" # Path relativity helper ...
def copyjob():
""" Helper to copy project local source to generator tree
Assumes current path (PWD) to be set to project root
- standard with IDEs
If run solely from helpers directory will work as well ...
"""
path2firmware = os.path.dirname(litex.soc.__file__) + "/software/bios/"
localpath = os.environ["PWD"] + relpath + "/firmware/"
originalfilename = "main.c"
backupfilename = "main.c.bak"
backupfilename2 = "main.c.original"
if os.path.isfile(path2firmware + backupfilename): # Check for existing backup
print("Backup already exists")
else: # Ok, no backup. Let's create one in-place & one to our local project directory ...
print("Preparing backup first ...")
shutil.copy2(path2firmware + originalfilename, path2firmware + backupfilename)
shutil.copy2(path2firmware + originalfilename, localpath + backupfilename2)
print("Backups in-place & to local project path finished.")
print("Copying project firmware to target path ...")
shutil.copy2(localpath + originalfilename, path2firmware + originalfilename)
originalfilename = "boot.c"
backupfilename = "boot.c.bak"
backupfilename2 = "boot.c.original"
def copyjob_actual(path2firmware, localpath, originalfilename):
backupfilename = originalfilename + ".bak"
backupfilename2 = originalfilename + ".original"
if os.path.isfile(path2firmware + backupfilename): # Check for existing backup
print("Backup already exists")
print("Backup already exists ({0})".format(originalfilename))
else: # Ok, no backup. Let's create one in-place & one to our local project directory ...
print("Preparing backup first ...")
print("Preparing backup ({0}) first ...".format(originalfilename))
shutil.copy2(path2firmware + originalfilename, path2firmware + backupfilename)
shutil.copy2(path2firmware + originalfilename, localpath + backupfilename2)
print("Backups in-place & to local project path finished.")
print("Copying project firmware to target path ...")
print("Copying project firmware ({0}) to target path ...".format(originalfilename))
shutil.copy2(localpath + originalfilename, path2firmware + originalfilename)
path2firmware = os.path.dirname(litex.soc.__file__) + "/software/bios/cmds/"
originalfilename = "cmd_mem.c"
backupfilename = "cmd_mem.c.bak"
backupfilename2 = "cmd_mem.c.original"
if os.path.isfile(path2firmware + backupfilename): # Check for existing backup
print("Backup already exists")
else: # Ok, no backup. Let's create one in-place & one to our local project directory ...
print("Preparing backup first ...")
shutil.copy2(path2firmware + originalfilename, path2firmware + backupfilename)
shutil.copy2(path2firmware + originalfilename, localpath + backupfilename2)
print("Backups in-place & to local project path finished.")
print("Copying project firmware to target path ...")
shutil.copy2(localpath + originalfilename, path2firmware + originalfilename)
def copyjob():
""" Helper to copy project local source to generator tree
Assumes current path (PWD) to be set to project root
- standard with IDEs
If run solely from helpers directory will work as well ...
"""
copyjob_actual(
os.path.dirname(litex.soc.__file__) + "/software/bios/",
os.environ["PWD"] + relpath + "/firmware/",
"main.c"
)
copyjob_actual(
os.path.dirname(litex.soc.__file__) + "/software/bios/",
os.environ["PWD"] + relpath + "/firmware/",
"boot.c"
)
copyjob_actual(
os.path.dirname(litex.soc.__file__) + "/software/bios/cmds/",
os.environ["PWD"] + relpath + "/firmware/",
"cmd_mem.c"
)
if __name__ == "__main__":
_, tail = os.path.split(os.getcwd())

@ -0,0 +1,154 @@
//
// illumination.c
// The Neopixel-Engine demonstration
//
// History:
// --------
// 07.10.20/KQ Initial version
// 18.10.20/KQ RAM version w/ command interpreter loop ready
//
#include <stdio.h>
#include <stdlib.h>
#include <console.h>
#include <string.h>
#include <uart.h>
#include <system.h>
#include <id.h>
#include <irq.h>
#include <crc.h>
#include "boot.h"
#include "readline.h"
#include "helpers.h"
#include "command.h"
#include "../build/colorlight_5a_75b/software/include/generated/csr.h"
#include "../build/colorlight_5a_75b/software/include/generated/soc.h"
#include "../build/colorlight_5a_75b/software/include/generated/mem.h"
#include "../build/colorlight_5a_75b/software/include/generated/git.h"
#include <spiflash.h>
#include <liblitedram/sdram.h>
#include <libliteeth/udp.h>
#include <libliteeth/mdio.h>
#include <liblitespi/spiflash.h>
#include <liblitesdcard/sdcard.h>
#include "illumination.h"
extern void busy_wait(unsigned int ms); // Worx!
#define MAXTABLES 3 // 1..16 MUST match h/w!
#define MAXLEDS 27 // 1..256 MUST match h/w!
static int32_t arLEDBuffer[MAXTABLES][MAXLEDS]; // GRB values
void enable_LEDS(int iEnable)
{
npe_b8Len_write(MAXLEDS); // Prepare length
npe_bEnable_write(iEnable ? 1 : 0); // Enable/disable
}
void send_LEDs(void)
{
for(int j=0;j<MAXTABLES;j++) {
npe_b4LoadTable_write(j); // Select table
for(int i=0;i<MAXLEDS;i++) {
npe_b8LoadOffset_write(i); // and offset
npe_b24Data2Load_write(arLEDBuffer[j][i]); // store 32(24) bit value @Table/Offset
}
}
busy_wait(25); // Minimum that meets the eye ;)
}
void clear_LEDs(int iTable)
{
for(int i=0;i<MAXLEDS;i++)
arLEDBuffer[iTable][i] = 0;
}
void load_triple_LEDs(int iTable, int32_t green, int32_t red, int32_t blue)
{
for(int i=0;i<MAXLEDS;i+=3) {
arLEDBuffer[iTable][i] = green;
arLEDBuffer[iTable][i+1] = red;
arLEDBuffer[iTable][i+2] = blue;
}
}
void illumination(void)
{
int32_t green = 0x040000;
int32_t red = 0x000400;
int32_t blue = 0x000004;
int iTable;
printf("Illumination demo starting ...\n");
// Prepare first output
iTable = 0;
load_triple_LEDs(iTable, green, red, blue); // 1st load
iTable = 1;
load_triple_LEDs(iTable, red, blue, green);
iTable = 2;
load_triple_LEDs(iTable, blue, green, red);
send_LEDs();
enable_LEDS(1);
busy_wait(2000);
// Let them flicker ...
for(int i=0;i<MAXLEDS;i++) {
int32_t temp = green;
green = red;
red = blue;
blue = temp;
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, green, red, blue);
send_LEDs();
busy_wait(80); // Slow down a bit
}
// Make 3 run along ...
green = 0x404000;
red = 0x004040;
blue = 0x400040;
for(iTable=0;iTable<MAXTABLES;iTable++) {
clear_LEDs(iTable); // Reset buffers
arLEDBuffer[iTable][0] = green;
arLEDBuffer[iTable][1] = red;
arLEDBuffer[iTable][2] = blue;
}
int max_LED = MAXLEDS-1; // 0..26
for(int i=0;i<MAXLEDS-3;i++) { // Forward shift 3
send_LEDs();
busy_wait(100);
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
arLEDBuffer[iTable][max_LED - j] = arLEDBuffer[iTable][(max_LED - 1) - j];
arLEDBuffer[iTable][i] = 0;
}
}
printf("Halfway thru ...\n");
for(int i=0;i<MAXLEDS-1;i++) { // Backward shift 3
send_LEDs();
busy_wait(100);
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
arLEDBuffer[iTable][j] = arLEDBuffer[iTable][j+1];
arLEDBuffer[iTable][max_LED-i] = 0;
}
}
busy_wait(400);
// Prepare final output
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, 0x010000, 0x000100, 0x000001); // 1st load
send_LEDs();
busy_wait(500);
enable_LEDS(0);
printf("Finished!\n");
busy_wait(1000);
uart_init(); // Clear buffers ...
}

@ -0,0 +1,8 @@
#ifndef ILLUMINATION_H
#define ILLUMINATION_H
extern void enable_LEDS(int iEnable);
extern void send_LEDs(void);
extern void clear_LEDs(int iTable);
extern void load_triple_LEDs(int iTable, int32_t green, int32_t red, int32_t blue);
extern void illumination(void);
#endif

@ -0,0 +1,85 @@
INCLUDE linker/output_format.ld
/* ENTRY(_start) */
ENTRY(illumination)
INCLUDE ../build/colorlight_5a_75b/software/include/generated/regions.ld
SECTIONS
{
.text :
{
_ftext = .;
/* Make sure crt0 files come first, and they, and the isr */
/* don't get disposed of by greedy optimisation */
*crt0*(.text)
KEEP(*crt0*(.text))
KEEP(*(.text.isr))
*(.text .stub .text.* .gnu.linkonce.t.*)
_etext = .;
} > main_ram
.rodata :
{
. = ALIGN(8);
_frodata = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
*(.got .got.*)
*(.toc .toc.*)
/* Make sure the file is aligned on disk as well
as in memory; CRC calculation requires that. */
FILL(0);
. = ALIGN(8);
_erodata = .;
} > main_ram
.commands :
{
PROVIDE_HIDDEN (__bios_cmd_start = .);
KEEP(*(.bios_cmd))
PROVIDE_HIDDEN (__bios_cmd_end = .);
} > main_ram
.data :
{
. = ALIGN(8);
_fdata = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.sdata .sdata.* .gnu.linkonce.s.*)
/* Make sure the file is aligned on disk as well
as in memory; CRC calculation requires that. */
FILL(0);
. = ALIGN(8);
_edata = .;
} > sram AT > main_ram
.bss :
{
. = ALIGN(8);
_fbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(8);
_ebss = .;
_end = .;
} > sram AT > main_ram
/DISCARD/ :
{
*(.eh_frame)
*(.comment)
}
}
PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 8);
PROVIDE(_fdata_rom = LOADADDR(.data));
PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data));

@ -0,0 +1 @@
OUTPUT_FORMAT("elf32-littleriscv")

@ -0,0 +1,80 @@
#!/bin/bash
#
# ramcreate.sh
# A rather obbscure RAM s/w builder (needs transformation to actual makefile setup ;)
#
# History:
# --------
# 10.10.20/KQ Initial (running) version
#
# Test for missing ('zero length') basefilename
if [[ -z $1 || -z $2 ]]; then
echo "usage: ./ramcreate.sh <mainfile_w/o_extension> <jobfile_w/o_extension>"
exit
fi
# Adjust these paths according to your local installation !!!
MY_LOCAL_LITEX_PATH=$HOME"/fpga/litex"
MY_LOCAL_FOMU_PATH=$HOME"/Fomu"
# If you don't use a virtual environment, comment out next line ...
source $HOME/fpga/bin/activate
# Make sure, we use the right compiler version ...
export PATH=$PATH:$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/
TRIPLE="riscv64-unknown-elf"
CPU="vexriscv"
CPUFLAGS="-march=rv32i -mabi=ilp32 -D__vexriscv__"
CPUENDIANNESS="little"
CPU_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/cores/cpu/vexriscv"
COMPILER_RT_DIRECTORY="$MY_LOCAL_LITEX_PATH/pythondata-software-compiler_rt/pythondata_software_compiler_rt/data"
SOC_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc"
#export BUILDINC_DIRECTORY
BUILDINC_DIRECTORY="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/neopixelar/build/colorlight_5a_75b/software/include"
LIBCOMPILER_RT_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/libcompiler_rt"
LIBBASE_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/libbase"
LIBLITEDRAM_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitedram"
LIBLITEETH_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/libliteeth"
LIBLITESPI_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitespi"
LIBLITESDCARD_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitesdcard"
BIOS_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/bios"
BIOSPATH="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/neopixelar/build/colorlight_5a_75b/software/bios"
OBJECTS="$BIOSPATH/isr.o $BIOSPATH/boot-helper.o $BIOSPATH/boot.o $BIOSPATH/helpers.o $BIOSPATH/cmd_bios.o $BIOSPATH/cmd_mem.o $BIOSPATH/cmd_boot.o $BIOSPATH/cmd_i2c.o $BIOSPATH/cmd_spiflash.o $BIOSPATH/cmd_litedram.o $BIOSPATH/cmd_liteeth.o $BIOSPATH/cmd_litesdcard.o $BIOSPATH/complete.o $BIOSPATH/readline.o"
LXP="../build/colorlight_5a_75b/software"
CRT0="$LXP/libbase/crt0.o"
LXR="-L$LXP/libcompiler_rt -L$LXP/libbase -L$LXP/liblitedram -L$LXP/libliteeth -L$LXP/liblitespi -L$LXP/liblitesdcard -llitedram -lliteeth -llitespi -llitesdcard -lbase-nofloat -lcompiler_rt"
INCLUDES="-I$SOC_DIRECTORY/software/include/base -I$SOC_DIRECTORY/software/include -I$SOC_DIRECTORY/software -I$BUILDINC_DIRECTORY -I$CPU_DIRECTORY -I$BIOS_DIRECTORY"
# -Os optimize for size
#COMMONFLAGS="-Os $CPUFLAGS -g3 -fomit-frame-pointer -Wall -fno-builtin -nostdinc $INCLUDES"
COMMONFLAGS="-O0 $CPUFLAGS -g3 -fomit-frame-pointer -Wall -fno-builtin -nostdinc $INCLUDES"
CFLAGS="-fexceptions -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes"
LDFLAGS="-nostdlib -nodefaultlibs -L$BUILDINC_DIRECTORY"
echo "--"
echo "calling gcc with: -c $COMMONFLAGS $CFLAGS -Wa,-fPIC"
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -O0 -S -nostdinc $COMMONFLAGS $INCLUDES -Wa,-fPIC $1.c
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC $2.c -o build/$2.o
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC $1.c -o build/$1.o
echo "--"
echo "calling ld with: $LDFLAGS $OBJECTS build/$2.o build/$1.o -o build/$1.bin"
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/linker.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o -o build/$1.elf
echo "--"
echo "creating raw binary from elf-file"
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/riscv64-unknown-elf/bin/objcopy -O binary -S --image-base 0x40000000 build/$1.elf build/$1.bin
#echo "--"
#echo "creating disassembly dump build/$1.dis"
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-objdump -D -b binary build/$1.bin -m riscv >build/$1.dis
echo "--"
echo "loading build/$1.bin to RAM base via wishbone-tool"
$MY_LOCAL_FOMU_PATH/fomu-toolchain-linux_x86_64-v1.5.6/bin/wishbone-tool --ethernet-host 192.168.1.20 --server load-file --csr-csv ../build/csr.csv --load-address 0x40000000 --load-name build/$1.bin
#echo "--"
#echo "Connecting to remote terminal w/ wishbone-tool (press ESC to terminate ...)"
#$MY_LOCAL_FOMU_PATH/fomu-toolchain-linux_x86_64-v1.5.6/bin/wishbone-tool --ethernet-host 192.168.1.20 --server terminal --csr-csv ../build/csr.csv
# alternatively use:
# screen /dev/ttyUSB0 115200
# Press 'Ctrl-A k' to terminate ...
echo "Done (don't worry about the download 'error' in red!)."

@ -0,0 +1,94 @@
//
// ramtest.c
// RAM loadable (& executable!) object
//
// History:
// --------
// 07.10.20/KQ Initial version
// 18.10.20/KQ RAM version w/ command interpreter loop ready
//
#include <stdio.h>
#include <stdlib.h>
#include <console.h>
#include <string.h>
#include <uart.h>
#include <system.h>
#include <id.h>
#include <irq.h>
#include <crc.h>
#include "boot.h"
#include "readline.h"
#include "helpers.h"
#include "command.h"
#include "../build/colorlight_5a_75b/software/include/generated/csr.h"
#include "../build/colorlight_5a_75b/software/include/generated/soc.h"
#include "../build/colorlight_5a_75b/software/include/generated/mem.h"
#include "../build/colorlight_5a_75b/software/include/generated/git.h"
#include <spiflash.h>
#include <liblitedram/sdram.h>
#include <libliteeth/udp.h>
#include <libliteeth/mdio.h>
#include <liblitespi/spiflash.h>
#include <liblitesdcard/sdcard.h>
#include "illumination.h"
extern void busy_wait(unsigned int ms); // Worx!
int32_t cpc; // Current PC storage
int main(int i, char **c)
{
char buffer[CMD_LINE_BUFFER_SIZE];
char *params[MAX_PARAM];
char *command;
struct command_struct *cmd;
int nb_params;
#ifdef CONFIG_CPU_HAS_INTERRUPT
irq_setmask(0);
irq_setie(1);
#endif
uart_init();
printf("\n");
// Verify we're executing within RAM ...
__asm__ __volatile__ ("\
lui t0,%hi(cpc) # Load t0 w/ high adress of cpc \n\
addi t0,t0,%lo(cpc) # Add immediate t0=t0 + low adress cpc \n\
# t0 now loaded with pointer to cpc \n\
auipc t1,0 # Load current pc \n\
sw t1,0(t0) # Store current PC \n\
");
if((cpc >= MAIN_RAM_BASE) && (cpc <= (MAIN_RAM_BASE + MAIN_RAM_SIZE))) {
printf("\e[1mExecuting within RAM ...\e[0m\n");
while(1)
illumination(); // The DEMO !
while(1) {
printf("\n%s", PROMPT);
readline(buffer, CMD_LINE_BUFFER_SIZE);
if (buffer[0] != 0) {
printf("\n");
nb_params = get_param(buffer, &command, params);
cmd = command_dispatcher(command, nb_params, params);
if (!cmd) {
printf("Command not found?! Executing illumination demo instead ...\n");
illumination(); // more DEMO ...
}
}
}
}
else
printf("Non-RAM execution @%08Xh, no action ...\n", cpc);
while(1);
return 0;
}
Loading…
Cancel
Save