version of the spi boot for 24-bit SPI memory. Hoever, it compiles and I'm fairly certain I made the necessary changes correctly. The prototype for C is:
One note though: any code/data to be loaded should not cross 64kB boundaries, because the next record address is calculated with a 16-bit addition. You can fix this by adding addc d1,null,d1 to the two places. We'll, perhaps I'll add them for you... But you can save 2 words by taking them out.
Code: Select all
#ifndef ASM
#define ASM
#endif/*!ASM*/
#include <vs1000.h>
#define SPI_WREN 0x06
#define SPI_WRDI 0x04
#define SPI_RDSR 0x05
#define SPI_WRSR 0x01
#define SPI_READ 0x03
#define SPI_WRITE 0x02
//u_int16 SpiSendReceive(register __a0 u_int16 data);
//void SpiDelay(register __a0 u_int16 wait);
.import _SpiSendReceive //A0, uses i7
.import _SpiDelay
// void SpiLoad24(register __d u_int32 startAddr); //never returns
.sect code,SpiLoad24
.export _SpiLoad24
_SpiLoad24:
call _SpiDelay
ldc 40/4,a0 // wait 40 cycles = 2.44us
ldc SPI_CF_MASTER | SPI_CF_DLEN8 | SPI_CF_FSIDLE0,b0
ldc SPI0_CONFIG,i4
STP b0,(i4) /* assert /CS (drop FSYNC) */
call _SpiSendReceive
ldc SPI_READ,a0 // Send READ
call _SpiSendReceive
add d1,null,a0 // d1 = high 8 bits of 24-bit address
ldc SPI_CF_MASTER | SPI_CF_DLEN16 | SPI_CF_FSIDLE0,b0
call _SpiSendReceive
add d0,null,a0 ; STP b0,(i4) // d0 = low 16 bits of 24-bit address
ldc SPI_CF_MASTER | SPI_CF_DLEN8 | SPI_CF_FSIDLE0,b0 // 8-bit mode
call _SpiSendReceive
and null,null,a0 ; STP b0,(i4) // Receive byte: type -> c0
call _SpiReceiveWord2
add a0,null,c0 //type->c0
call _SpiReceiveWord2 //addr -> b0
mv b0,i4 //length -> i4
// advance to next record d = d + 5
ldc 5,a0
add d0,a0,d0
addc d1,null,d1 // advance to next 64kB if needed
mv b0,i4 ; mv i4,b0
// i4=addr, c0=type, b0=length
ldc 0x00ff,a0 // POj: 20050502
and c0,a0,c0 // mask upper bits, do not require pull-down on MISO
// advance to next record d = d + b0
add d0,b0,d0
addc d1,null,d1 // advance to next 64kB if needed
lsr b0,a0 // a0: length in words
add c0,null,c0
ldc 0x01,a1
jzs spii //0->Imem
sub a1,c0,a1
ldc 0x02,a1
jzs spix //1->Xmem
sub a1,c0,a1
ldc 0x03,a1
jzs spiy //2->Ymem
sub a1,c0,a1
nop
jzs spiexec //3->exec
nop
// unknown -> Skip record
end: ldc SPI_CF_MASTER | SPI_CF_DLEN8 | SPI_CF_FSIDLE1,b0
ldc SPI0_CONFIG,i4
j _SpiLoad24
STP b0,(i4) /* de-assert /CS (raise FSYNC) */
.export spiexec
spiexec:
ldc SPI_CF_MASTER | SPI_CF_DLEN8 | SPI_CF_FSIDLE1,b0
mv i4,lr0 //address is execute address
ldc SPI0_CONFIG,i4
jr
STP b0,(i4) /* de-assert /CS (raise FSYNC) */
spix: add a0,ones,a0 // length in 16-bit words -1
// addr: i4, len: a0
loop a0,$0-1
nop
call _SpiReceiveWord2
nop
stx b0,(i4)+1
$0:
jmpi end
.export spiy
spiy: add a0,ones,a0 // length in 16-bit words -1
// addr: i4, len: a0
loop a0,$0-1
nop
call _SpiReceiveWord2
nop
sty b0,(i4)+1
$0:
jmpi end
spii: lsr a0,a0 // length in 32-bit words
add a0,ones,a0
loop a0,$0-1
nop
call _SpiReceiveWord2
nop
call _SpiReceiveWord2
mv b0,b1
add b0,null,b1 ; mv b1,b0
sti b,(i4)+1
nop // NOP so that call or jmpi is not the next instruction
$0:
jmpi end
.sect code,SpiReceiveWord2
//register __b0 u_int16 SpiReceiveWord2(void);
.export _SpiReceiveWord2
_SpiReceiveWord2:
ldx (i6)+1,null
stx lr0,(i6)+1 ; sty a0,(i6)
call _SpiSendReceive //receive low -> b0
and null,null,a0 ; sty a1,(i6)
call _SpiSendReceive
and null,null,a0 ; mv a0,b0 //receive high -> a0
ldc 8,a1
ashl a0,a1,a0 ; ldy (i6)-1,a1
ldx (i6),lr0
jr
or a0,b0,b0 ; ldy (i6)-1,a0
.end