firmware: Import of the boot code
This is what gets embedded in the bitstream and loads the main software from flash. Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
parent
c85dc29b06
commit
f4ee67209b
|
@ -0,0 +1,24 @@
|
||||||
|
CROSS ?= riscv-none-embed-
|
||||||
|
|
||||||
|
CC := $(CROSS)gcc
|
||||||
|
OBJCOPY := $(CROSS)objcopy
|
||||||
|
|
||||||
|
CFLAGS=-Wall -Os -march=rv32i -mabi=ilp32 -ffreestanding -flto -nostartfiles -fomit-frame-pointer -Wl,--gc-section --specs=nano.specs
|
||||||
|
|
||||||
|
|
||||||
|
all: boot.hex
|
||||||
|
|
||||||
|
|
||||||
|
boot.elf: lnk-boot.lds boot.S
|
||||||
|
$(CC) $(CFLAGS) -Wl,-Bstatic,-T,lnk-boot.lds,--strip-debug -DAPP_FLASH_ADDR=0x000a0000 -o $@ boot.S
|
||||||
|
|
||||||
|
%.bin: %.elf
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
%.hex: %.bin
|
||||||
|
hexdump boot.bin -ve '1/4 "%08x\n"' $< > $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.bin *.hex *.elf *.o
|
||||||
|
|
||||||
|
.PHONY: clean
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* boot.S
|
||||||
|
*
|
||||||
|
* SPI boot code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020-2023 Sylvain Munaut <tnt@246tNt.com>
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APP_FLASH_ADDR
|
||||||
|
#define APP_FLASH_ADDR 0x000a0000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef APP_SRAM_ADDR
|
||||||
|
#define APP_SRAM_ADDR 0x00020000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef APP_SIZE
|
||||||
|
#define APP_SIZE 0x00010000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.section .text.start
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
|
||||||
|
// SPI init
|
||||||
|
jal spi_init
|
||||||
|
jal spi_wakeup
|
||||||
|
|
||||||
|
// Read from flash to SRAM
|
||||||
|
li a0, APP_SRAM_ADDR
|
||||||
|
li a1, APP_SIZE
|
||||||
|
li a2, APP_FLASH_ADDR
|
||||||
|
jal spi_flash_read
|
||||||
|
|
||||||
|
// Setup reboot code
|
||||||
|
li t0, 0x0002006f
|
||||||
|
sw t0, 0(zero)
|
||||||
|
|
||||||
|
// Jump to main code
|
||||||
|
j APP_SRAM_ADDR
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// SB_SPI driver code
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Register definitions
|
||||||
|
|
||||||
|
.equ SPI_BASE, 0x81000000
|
||||||
|
|
||||||
|
.equ SPICR0, 4 * 0x08
|
||||||
|
.equ SPICR1, 4 * 0x09
|
||||||
|
.equ SPICR2, 4 * 0x0a
|
||||||
|
.equ SPIBR, 4 * 0x0b
|
||||||
|
.equ SPISR, 4 * 0x0c
|
||||||
|
.equ SPITXDR, 4 * 0x0d
|
||||||
|
.equ SPIRXDR, 4 * 0x0e
|
||||||
|
.equ SPICSR, 4 * 0x0f
|
||||||
|
|
||||||
|
|
||||||
|
// Initializes te SPI hardware
|
||||||
|
//
|
||||||
|
// Clobbers a0, a1
|
||||||
|
|
||||||
|
spi_init:
|
||||||
|
li a0, SPI_BASE
|
||||||
|
|
||||||
|
li a1, 0xff
|
||||||
|
sw a1, SPICR0(a0)
|
||||||
|
|
||||||
|
li a1, 0x80
|
||||||
|
sw a1, SPICR1(a0)
|
||||||
|
|
||||||
|
li a1, 0xc0
|
||||||
|
sw a1, SPICR2(a0)
|
||||||
|
|
||||||
|
li a1, 0x03
|
||||||
|
sw a1, SPIBR(a0)
|
||||||
|
|
||||||
|
li a1, 0x0f
|
||||||
|
sw a1, SPICSR(a0)
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wake up flash
|
||||||
|
//
|
||||||
|
spi_wakeup:
|
||||||
|
|
||||||
|
mv s2, ra
|
||||||
|
|
||||||
|
// Setup CS
|
||||||
|
li t0, SPI_BASE
|
||||||
|
li t1, 0x0e
|
||||||
|
sw t1, SPICSR(t0)
|
||||||
|
|
||||||
|
// Send command
|
||||||
|
li a0, 0xAB
|
||||||
|
jal _spi_do_one
|
||||||
|
|
||||||
|
// Release CS
|
||||||
|
li t0, SPI_BASE
|
||||||
|
li t1, 0x0f
|
||||||
|
sw t1, SPICSR(t0)
|
||||||
|
|
||||||
|
// Wait a bit
|
||||||
|
li s1, 0x10000
|
||||||
|
1:
|
||||||
|
addi s1, s1, -1
|
||||||
|
bne s1, zero, 1b
|
||||||
|
|
||||||
|
// Done
|
||||||
|
jr s2
|
||||||
|
|
||||||
|
|
||||||
|
// Reads a block of memory from SPI flash
|
||||||
|
//
|
||||||
|
// Params:
|
||||||
|
// a0 - destination pointer
|
||||||
|
// a1 - length (bytes)
|
||||||
|
// a2 - flash offset
|
||||||
|
// Clobbers t0, t1, s0, s1, s2
|
||||||
|
|
||||||
|
spi_flash_read:
|
||||||
|
// Save params
|
||||||
|
mv s0, a0
|
||||||
|
mv s1, a1
|
||||||
|
mv s2, ra
|
||||||
|
|
||||||
|
// Setup CS
|
||||||
|
li t0, SPI_BASE
|
||||||
|
li t1, 0x0e
|
||||||
|
sw t1, SPICSR(t0)
|
||||||
|
|
||||||
|
// Send command
|
||||||
|
li a0, 0x03
|
||||||
|
jal _spi_do_one
|
||||||
|
|
||||||
|
srli a0, a2, 16
|
||||||
|
and a0, a0, 0xff
|
||||||
|
jal _spi_do_one
|
||||||
|
|
||||||
|
srli a0, a2, 8
|
||||||
|
and a0, a0, 0xff
|
||||||
|
jal _spi_do_one
|
||||||
|
|
||||||
|
and a0, a2, 0xff
|
||||||
|
jal _spi_do_one
|
||||||
|
|
||||||
|
// Read loop
|
||||||
|
_spi_loop:
|
||||||
|
li a0, 0x00
|
||||||
|
jal _spi_do_one
|
||||||
|
sb a0, 0(s0)
|
||||||
|
addi s0, s0, 1
|
||||||
|
addi s1, s1, -1
|
||||||
|
bne s1, zero, _spi_loop
|
||||||
|
|
||||||
|
// Release CS
|
||||||
|
li t0, SPI_BASE
|
||||||
|
li t1, 0x0f
|
||||||
|
sw t1, SPICSR(t0)
|
||||||
|
|
||||||
|
// Done
|
||||||
|
jr s2
|
||||||
|
|
||||||
|
|
||||||
|
// Performs a single 8 bit SPI xfer
|
||||||
|
//
|
||||||
|
// Params: a0 - Data to TX
|
||||||
|
// Returns: a0 - RX data
|
||||||
|
// Clobbers t0, t1
|
||||||
|
|
||||||
|
_spi_do_one:
|
||||||
|
li t0, SPI_BASE
|
||||||
|
li t1, 0x08
|
||||||
|
|
||||||
|
// Write TX data
|
||||||
|
sw a0, SPITXDR(t0)
|
||||||
|
|
||||||
|
// Wait for RXRDY
|
||||||
|
1:
|
||||||
|
lw a0, SPISR(t0)
|
||||||
|
and a0, a0, t1
|
||||||
|
bne a0, t1, 1b
|
||||||
|
|
||||||
|
// Read RX data
|
||||||
|
lw a0, SPIRXDR(t0)
|
||||||
|
|
||||||
|
// Done
|
||||||
|
ret
|
|
@ -0,0 +1,14 @@
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x0400
|
||||||
|
}
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS {
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text.start)
|
||||||
|
*(.text)
|
||||||
|
*(.text*)
|
||||||
|
} >ROM
|
||||||
|
}
|
Loading…
Reference in New Issue