Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d03ee7a
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4d754db
Choose a head ref
  • 5 commits
  • 16 files changed
  • 1 contributor

Commits on May 21, 2012

  1. tools/mkmmimg: remove LZMA option

    Sebastien Bourdeauducq committed May 21, 2012
    Copy the full SHA
    9958aab View commit details
  2. bios/ddrinit: use new padding scheme for address register

    Sebastien Bourdeauducq committed May 21, 2012
    Copy the full SHA
    e33399d View commit details
  3. bios: timer support

    Sebastien Bourdeauducq committed May 21, 2012
    Copy the full SHA
    275ed9c View commit details
  4. minimac: add tx start register

    Sebastien Bourdeauducq committed May 21, 2012
    Copy the full SHA
    5917048 View commit details
  5. bios: serial, network and flash boot support

    Sebastien Bourdeauducq committed May 21, 2012
    Copy the full SHA
    4d754db View commit details
5 changes: 3 additions & 2 deletions milkymist/minimac3/__init__.py
Original file line number Diff line number Diff line change
@@ -26,7 +26,8 @@ def __init__(self, address):
self._rx_count_0 = RegisterField("rx_count_0", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self._rx_count_1 = RegisterField("rx_count_1", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self._tx_count = RegisterField("tx_count", _count_width, access_dev=READ_WRITE)
regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count]
self._tx_start = RegisterField("tx_start", access_bus=WRITE_ONLY)
regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count, self._tx_start]

self._rx_event_0 = EventSourcePulse()
self._rx_event_1 = EventSourcePulse()
@@ -78,7 +79,7 @@ def get_fragment(self):
("rx_ready_0", rx_ready_0),
("rx_ready_1", rx_ready_1),

("tx_start", self._tx_count.re),
("tx_start", self._tx_start.re),
("tx_count", self._tx_count.field.r),

("wb_adr_i", self.membus.adr),
2 changes: 1 addition & 1 deletion software/bios/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
M2DIR=../..
include $(M2DIR)/software/include.mak

OBJECTS=crt0.o isr.o ddrinit.o main.o
OBJECTS=crt0.o isr.o ddrinit.o timer.o main.o microudp.o tftp.o boot-helper.o boot.o

all: bios.bin

10 changes: 10 additions & 0 deletions software/bios/boot-helper.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.section .text, "ax", @progbits
.global boot_helper
boot_helper:
/* Invalidate instruction cache */
wcsr ICC, r0
nop
nop
nop
nop
call r5
284 changes: 284 additions & 0 deletions software/bios/boot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/*
* Milkymist SoC (Software)
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <console.h>
#include <uart.h>
#include <system.h>
#include <board.h>
#include <extra/crc.h>
#include <sfl.h>
#include <string.h>
#include <irq.h>

#include <hw/flash.h>
#include <hw/mem.h>

#include "timer.h"
#include "microudp.h"
#include "tftp.h"
#include "boot.h"

extern int rescue;
extern void boot_helper(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr);

static void __attribute__((noreturn)) boot(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr)
{
printf("Executing booted program.\n");
uart_sync();
irq_setmask(0);
irq_setie(0);
boot_helper(r1, r2, r3, r4, addr);
while(1);
}

static int check_ack(void)
{
int recognized;
static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK;

timer_enable(0);
timer_set_reload(0);
timer_set_counter(get_system_frequency()/4);
timer_enable(1);
recognized = 0;
while(timer_get()) {
if(uart_read_nonblock()) {
char c;
c = uart_read();
if(c == str[recognized]) {
recognized++;
if(recognized == SFL_MAGIC_LEN)
return 1;
} else {
if(c == str[0])
recognized = 1;
else
recognized = 0;
}
}
}
return 0;
}

#define MAX_FAILED 5

void serialboot(void)
{
struct sfl_frame frame;
int failed;
unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
static const char str[SFL_MAGIC_LEN+1] = SFL_MAGIC_REQ;
const char *c;

printf("Booting from serial...\n");

c = str;
while(*c) {
uart_write(*c);
c++;
}
if(!check_ack()) {
printf("Timeout\n");
return;
}

failed = 0;
cmdline_adr = initrdstart_adr = initrdend_adr = 0;
while(1) {
int i;
int actualcrc;
int goodcrc;

/* Grab one frame */
frame.length = uart_read();
frame.crc[0] = uart_read();
frame.crc[1] = uart_read();
frame.cmd = uart_read();
for(i=0;i<frame.length;i++)
frame.payload[i] = uart_read();

/* Check CRC */
actualcrc = ((int)frame.crc[0] << 8)|(int)frame.crc[1];
goodcrc = crc16(&frame.cmd, frame.length+1);
if(actualcrc != goodcrc) {
failed++;
if(failed == MAX_FAILED) {
printf("Too many consecutive errors, aborting");
return;
}
uart_write(SFL_ACK_CRCERROR);
continue;
}

/* CRC OK */
switch(frame.cmd) {
case SFL_CMD_ABORT:
failed = 0;
uart_write(SFL_ACK_SUCCESS);
return;
case SFL_CMD_LOAD: {
char *writepointer;

failed = 0;
writepointer = (char *)(
((unsigned int)frame.payload[0] << 24)
|((unsigned int)frame.payload[1] << 16)
|((unsigned int)frame.payload[2] << 8)
|((unsigned int)frame.payload[3] << 0));
for(i=4;i<frame.length;i++)
*(writepointer++) = frame.payload[i];
uart_write(SFL_ACK_SUCCESS);
break;
}
case SFL_CMD_JUMP: {
unsigned int addr;

failed = 0;
addr = ((unsigned int)frame.payload[0] << 24)
|((unsigned int)frame.payload[1] << 16)
|((unsigned int)frame.payload[2] << 8)
|((unsigned int)frame.payload[3] << 0);
uart_write(SFL_ACK_SUCCESS);
boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, addr);
break;
}
case SFL_CMD_CMDLINE:
failed = 0;
cmdline_adr = ((unsigned int)frame.payload[0] << 24)
|((unsigned int)frame.payload[1] << 16)
|((unsigned int)frame.payload[2] << 8)
|((unsigned int)frame.payload[3] << 0);
uart_write(SFL_ACK_SUCCESS);
break;
case SFL_CMD_INITRDSTART:
failed = 0;
initrdstart_adr = ((unsigned int)frame.payload[0] << 24)
|((unsigned int)frame.payload[1] << 16)
|((unsigned int)frame.payload[2] << 8)
|((unsigned int)frame.payload[3] << 0);
uart_write(SFL_ACK_SUCCESS);
break;
case SFL_CMD_INITRDEND:
failed = 0;
initrdend_adr = ((unsigned int)frame.payload[0] << 24)
|((unsigned int)frame.payload[1] << 16)
|((unsigned int)frame.payload[2] << 8)
|((unsigned int)frame.payload[3] << 0);
uart_write(SFL_ACK_SUCCESS);
break;
default:
failed++;
if(failed == MAX_FAILED) {
printf("Too many consecutive errors, aborting");
return;
}
uart_write(SFL_ACK_UNKNOWN);
break;
}
}
}

#define LOCALIP1 192
#define LOCALIP2 168
#define LOCALIP3 0
#define LOCALIP4 42
#define REMOTEIP1 192
#define REMOTEIP2 168
#define REMOTEIP3 0
#define REMOTEIP4 14

static int tftp_get_v(unsigned int ip, const char *filename, char *buffer)
{
int r;

r = tftp_get(ip, filename, buffer);
if(r > 0)
printf("Successfully downloaded %d bytes from %s over TFTP\n", r, filename);
else
printf("Unable to download %s over TFTP\n", filename);
return r;
}

void netboot(void)
{
int size;
unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
unsigned int ip;
unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;

printf("Booting from network...\n");
printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);

ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);

microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));

if(tftp_get_v(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) {
printf("Network boot failed\n");
return;
}

cmdline_adr = SDRAM_BASE+0x1000000;
size = tftp_get_v(ip, "cmdline.txt", (void *)cmdline_adr);
if(size <= 0) {
printf("No command line parameters found\n");
cmdline_adr = 0;
} else
*((char *)(cmdline_adr+size)) = 0x00;

initrdstart_adr = SDRAM_BASE+0x1002000;
size = tftp_get_v(ip, "initrd.bin", (void *)initrdstart_adr);
if(size <= 0) {
printf("No initial ramdisk found\n");
initrdstart_adr = 0;
initrdend_adr = 0;
} else
initrdend_adr = initrdstart_adr + size;

boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, SDRAM_BASE);
}

void flashboot(void)
{
unsigned int *flashbase;
unsigned int length;
unsigned int crc;
unsigned int got_crc;

printf("Booting from flash...\n");
if(rescue)
flashbase = (unsigned int *)FLASH_OFFSET_RESCUE_APP;
else
flashbase = (unsigned int *)FLASH_OFFSET_REGULAR_APP;
length = *flashbase++;
crc = *flashbase++;
if((length < 32) || (length > 4*1024*1024)) {
printf("Error: Invalid flash boot image length\n");
return;
}

printf("Loading %d bytes from flash...\n", length);
memcpy((void *)SDRAM_BASE, flashbase, length);
got_crc = crc32((unsigned char *)SDRAM_BASE, length);
if(crc != got_crc) {
printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc);
return;
}
boot(0, 0, 0, rescue, SDRAM_BASE);
}
25 changes: 25 additions & 0 deletions software/bios/boot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Milkymist SoC (Software)
* Copyright (C) 2007, 2008, 2009, 2010, 2012 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BOOT_H
#define __BOOT_H

void serialboot(void);
void netboot(void);
void flashboot(void);

#endif /* __BOOT_H */
8 changes: 4 additions & 4 deletions software/bios/ddrinit.c
Original file line number Diff line number Diff line change
@@ -33,10 +33,10 @@ static void cdelay(int i)

static void setaddr(int a)
{
CSR_DFII_AH_P0 = (a & 0x1fe0) >> 5;
CSR_DFII_AL_P0 = a & 0x001f;
CSR_DFII_AH_P1 = (a & 0x1fe0) >> 5;
CSR_DFII_AL_P1 = a & 0x001f;
CSR_DFII_AH_P0 = (a & 0xff00) >> 8;
CSR_DFII_AL_P0 = a & 0x00ff;
CSR_DFII_AH_P1 = (a & 0xff00) >> 8;
CSR_DFII_AL_P1 = a & 0x00ff;
}

static void init_sequence(void)
Loading