You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
8.9 KiB
328 lines
8.9 KiB
// This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
|
|
// This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
// This file is Copyright (c) 2015 Yann Sionneau <ys@m-labs.hk>
|
|
// This file is Copyright (c) 2015 whitequark <whitequark@whitequark.org>
|
|
// This file is Copyright (c) 2019 Ambroz Bizjak <ambrop7@gmail.com>
|
|
// This file is Copyright (c) 2019 Caleb Jamison <cbjamo@gmail.com>
|
|
// This file is Copyright (c) 2018 Dolu1990 <charles.papon.90@gmail.com>
|
|
// This file is Copyright (c) 2018 Felix Held <felix-github@felixheld.de>
|
|
// This file is Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
|
|
// This file is Copyright (c) 2018 Jean-François Nguyen <jf@lambdaconcept.fr>
|
|
// This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
|
|
// This file is Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
|
|
// This file is Copyright (c) 2020 Franck Jullien <franck.jullien@gmail.com>
|
|
// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
|
|
|
|
// License: BSD
|
|
|
|
#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 <generated/csr.h>
|
|
#include <generated/soc.h>
|
|
#include <generated/mem.h>
|
|
#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>
|
|
|
|
static void boot_sequence(void)
|
|
{
|
|
if(serialboot()) {
|
|
#ifdef FLASH_BOOT_ADDRESS
|
|
flashboot();
|
|
#endif
|
|
#ifdef ROM_BOOT_ADDRESS
|
|
romboot();
|
|
#endif
|
|
#if defined(CSR_SPISDCARD_BASE) || defined(CSR_SDCORE_BASE)
|
|
sdcardboot();
|
|
#endif
|
|
#ifdef CSR_ETHMAC_BASE
|
|
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
|
|
eth_mode();
|
|
#endif
|
|
netboot();
|
|
#endif
|
|
printf("No boot medium found\n");
|
|
}
|
|
}
|
|
|
|
//------------------- Illumination demo --------------------------------
|
|
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
|
|
#ifdef XXX
|
|
void enable_LEDS(int iEnable)
|
|
{
|
|
npe_b6NoOfTables_write(MAXTABLES)
|
|
npe_b9Len_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;
|
|
}
|
|
}
|
|
|
|
int illumination(void)
|
|
{
|
|
int32_t green = 0x040000;
|
|
int32_t red = 0x000400;
|
|
int32_t blue = 0x000004;
|
|
int iTable;
|
|
|
|
// 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);
|
|
|
|
#ifdef MAIN_ILLUMINATION_EXTENSIVE_DEMO
|
|
// 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 = 0x400000;
|
|
red = 0x004000;
|
|
blue = 0x000040;
|
|
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;
|
|
}
|
|
}
|
|
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);
|
|
#endif
|
|
enable_LEDS(0);
|
|
return 1;
|
|
}
|
|
#endif
|
|
//------------------- End of illumination demo --------------------------
|
|
|
|
int main(int i, char **c)
|
|
{
|
|
extern char kbhit(void);
|
|
extern void set_console(int non_blocking);
|
|
extern int get_console(void);
|
|
|
|
// Create our own start status indicator
|
|
// Read command: 'mr 0x403ffffc 4'
|
|
int32_t *statept = (int32_t *)(MAIN_RAM_BASE + MAIN_RAM_SIZE - sizeof(int32_t));
|
|
char buffer[CMD_LINE_BUFFER_SIZE];
|
|
char *params[MAX_PARAM];
|
|
char *command;
|
|
struct command_struct *cmd;
|
|
int nb_params;
|
|
int sdr_ok;
|
|
int non_blocking = 0;
|
|
|
|
#ifdef CONFIG_CPU_HAS_INTERRUPT
|
|
irq_setmask(0);
|
|
irq_setie(1);
|
|
#endif
|
|
uart_init();
|
|
|
|
#define CONSOLE_NON_BLOCKING 1
|
|
#ifdef CONSOLE_NON_BLOCKING
|
|
busy_wait(1000); // Permit remote (IP) terminal to connect ...
|
|
printf("Press any key for full boot messages within 2s ...\n");
|
|
non_blocking = 1; //<-- Test w/ 0! 1; // By default: show demo (=1)...
|
|
for(int i=1;i<20;i++) {
|
|
busy_wait(100);
|
|
if(kbhit()) { // Key pressed?
|
|
non_blocking = 0; // Yap! Switch to blocking/full boot screen
|
|
break;
|
|
}
|
|
}
|
|
set_console(non_blocking); // 1=Non-blocking (0=blocking)
|
|
*statept = get_console(); // Make sure, we know what was going on ...
|
|
if(non_blocking) printf("\e[1mBoot screen skipped, going straight to illumination ...\e[0m\n");
|
|
#endif
|
|
|
|
if(!non_blocking) {
|
|
printf("\n");
|
|
printf("\e[1m __ _ __ _ __\e[0m\n");
|
|
printf("\e[1m / / (_) /____ | |/_/\e[0m\n");
|
|
printf("\e[1m / /__/ / __/ -_)> <\e[0m\n");
|
|
printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n");
|
|
printf("\e[1m Build your hardware, easily!\e[0m\n");
|
|
printf("\n");
|
|
printf(" (c) Copyright 2012-2020 Enjoy-Digital\n");
|
|
printf(" (c) Copyright 2007-2015 M-Labs\n");
|
|
printf(" --- Copyleft 2020 KQ ---------\n");
|
|
printf("\n");
|
|
printf(" BIOS built on "__DATE__" "__TIME__"\n");
|
|
}
|
|
crcbios();
|
|
if(!non_blocking) {
|
|
printf("\n");
|
|
printf(" Migen git sha1: "MIGEN_GIT_SHA1"\n");
|
|
printf(" LiteX git sha1: "LITEX_GIT_SHA1"\n");
|
|
printf("\n");
|
|
printf("--=============== \e[1mSoC\e[0m ==================--\n");
|
|
printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n",
|
|
CONFIG_CPU_HUMAN_NAME,
|
|
CONFIG_CLOCK_FREQUENCY/1000000);
|
|
printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n",
|
|
CONFIG_BUS_STANDARD,
|
|
CONFIG_BUS_DATA_WIDTH,
|
|
(1 << (CONFIG_BUS_ADDRESS_WIDTH - 30)));
|
|
printf("\e[1mCSR\e[0m:\t\t%d-bit data\n",
|
|
CONFIG_CSR_DATA_WIDTH);
|
|
printf("\e[1mROM\e[0m:\t\t%dKiB\n", ROM_SIZE/1024);
|
|
printf("\e[1mSRAM\e[0m:\t\t%dKiB\n", SRAM_SIZE/1024);
|
|
#ifdef CONFIG_L2_SIZE
|
|
printf("\e[1mL2\e[0m:\t\t%dKiB\n", CONFIG_L2_SIZE/1024);
|
|
#endif
|
|
#ifdef MAIN_RAM_SIZE
|
|
#ifdef CSR_SDRAM_BASE
|
|
printf("\e[1mSDRAM\e[0m:\t\t%dKiB %d-bit @ %dMbps/pin\n",
|
|
MAIN_RAM_SIZE/1024,
|
|
sdrdatabits(),
|
|
sdrfreq()/1000000);
|
|
#else
|
|
printf("\e[1mMAIN-RAM\e[0m:\t%dKiB \n", MAIN_RAM_SIZE/1024);
|
|
#endif
|
|
#endif
|
|
printf("\n");
|
|
}
|
|
sdr_ok = 1;
|
|
#if defined(CSR_ETHMAC_BASE) || defined(CSR_SDRAM_BASE)
|
|
if(!non_blocking)
|
|
printf("--========== \e[1mInitialization\e[0m ============--\n");
|
|
#ifdef CSR_ETHMAC_BASE
|
|
printf("ETH init ...\n");
|
|
eth_init();
|
|
#endif
|
|
#ifdef CSR_SDRAM_BASE
|
|
sdr_ok = sdrinit();
|
|
#else
|
|
#ifdef MAIN_RAM_TEST
|
|
sdr_ok = memtest();
|
|
#endif
|
|
#endif
|
|
if (sdr_ok !=1)
|
|
printf("Memory initialization failed\n");
|
|
printf("\n");
|
|
#endif
|
|
#ifdef CSR_SPIFLASH_MMAP_BASE
|
|
printf("SPIFLASH init ...\n");
|
|
spiflash_init();
|
|
#endif
|
|
|
|
if(sdr_ok) {
|
|
printf("--============== \e[1mBoot\e[0m ==================--\n");
|
|
boot_sequence();
|
|
printf("\n");
|
|
}
|
|
|
|
printf("--============= \e[1mConsole\e[0m ================--\n");
|
|
#if !defined(TERM_MINI) && !defined(TERM_NO_HIST)
|
|
hist_init();
|
|
#endif
|
|
#ifdef XXX
|
|
if(illumination()) // Initial demo / up indication
|
|
printf("Initial demo finished.\n");
|
|
#endif
|
|
printf("\n%s", PROMPT);
|
|
#ifdef CONSOLE_NON_BLOCKING
|
|
if(!non_blocking)
|
|
set_console(1); // Allways non-blocking from now on ...
|
|
*statept = get_console(); // Make sure, we know what's going on ...
|
|
#endif
|
|
while(1) {
|
|
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?!\n");
|
|
}
|
|
*statept = get_console(); // Make sure, we know what's going on ...
|
|
printf("\n%s", PROMPT);
|
|
}
|
|
return 0;
|
|
}
|
|
|