100 lines
2.7 KiB
ArmAsm
100 lines
2.7 KiB
ArmAsm
#define SPIFLASH_READ_STATUS 0x05 // Read Status Register
|
|
#define SPIFLASH_BSY_BIT 0x00000001 // WIP Bit of SPI SR on SMI SR
|
|
|
|
// Register offsets
|
|
#define FESPI_REG_FMT 0x40
|
|
#define FESPI_REG_TXFIFO 0x48
|
|
#define FESPI_REG_RXFIFO 0x4c
|
|
#define FESPI_REG_IP 0x74
|
|
|
|
// Fields
|
|
#define FESPI_IP_TXWM 0x1
|
|
#define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
|
|
|
|
// To enter, jump to the start of command_table (ie. offset 0).
|
|
// a0 - FESPI base address
|
|
// a1 - start address of buffer
|
|
|
|
// The buffer contains a "program" in byte sequences. The first byte in a
|
|
// sequence determines the operation. Some operation will read more data from
|
|
// the program, while some will not. The operation byte is the offset into
|
|
// command_table, so eg. 4 means exit, 8 means transmit, and so on.
|
|
|
|
.global _start
|
|
_start:
|
|
command_table:
|
|
j main // 0
|
|
ebreak // 4
|
|
j tx // 8
|
|
j txwm_wait // 12
|
|
j write_reg // 16
|
|
j wip_wait // 20
|
|
j set_dir // 24
|
|
|
|
// Execute the program.
|
|
main:
|
|
lbu t0, 0(a1)
|
|
addi a1, a1, 1
|
|
la t1, command_table
|
|
add t0, t0, t1
|
|
jr t0
|
|
|
|
// Read 1 byte the contains the number of bytes to transmit. Then read those
|
|
// bytes from the program and transmit them one by one.
|
|
tx:
|
|
lbu t1, 0(a1) // read number of bytes to transmit
|
|
addi a1, a1, 1
|
|
1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
|
bltz t0, 1b
|
|
lbu t0, 0(a1) // Load byte to write
|
|
sw t0, FESPI_REG_TXFIFO(a0)
|
|
addi a1, a1, 1
|
|
addi t1, t1, -1
|
|
bgtz t1, 1b
|
|
j main
|
|
|
|
// Wait until TXWM is set.
|
|
txwm_wait:
|
|
1: lw t0, FESPI_REG_IP(a0)
|
|
andi t0, t0, FESPI_IP_TXWM
|
|
beqz t0, 1b
|
|
j main
|
|
|
|
// Read 1 byte that contains the offset of the register to write, and 1 byte
|
|
// that contains the data to write.
|
|
write_reg:
|
|
lbu t0, 0(a1) // read register to write
|
|
add t0, t0, a0
|
|
lbu t1, 1(a1) // read value to write
|
|
addi a1, a1, 2
|
|
sw t1, 0(t0)
|
|
j main
|
|
|
|
wip_wait:
|
|
li a2, SPIFLASH_READ_STATUS
|
|
jal txrx_byte
|
|
// discard first result
|
|
1: li a2, 0
|
|
jal txrx_byte
|
|
andi t0, a2, SPIFLASH_BSY_BIT
|
|
bnez t0, 1b
|
|
j main
|
|
|
|
txrx_byte: // transmit the byte in a2, receive a bit into a2
|
|
lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
|
bltz t0, txrx_byte
|
|
sw a2, FESPI_REG_TXFIFO(a0)
|
|
1: lw a2, FESPI_REG_RXFIFO(a0)
|
|
bltz a2, 1b
|
|
ret
|
|
|
|
set_dir:
|
|
lw t0, FESPI_REG_FMT(a0)
|
|
li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
|
|
and t0, t0, t1
|
|
lbu t1, 0(a1) // read value to OR in
|
|
addi a1, a1, 1
|
|
or t0, t0, t1
|
|
sw t0, FESPI_REG_FMT(a0)
|
|
j main
|