Closed surabibio closed 1 year ago
Hi,
1 MOSI + 1 MISO => datawidth = 2 with full duplex :)
Do all good i would say.
Hi Charles, The xdr which is new to me, I couldn't get it to work. On the other hand good old SPI works great. Your comments on this piece of code, please. Am I doing something redundant that can be easily accomplished with xdr?
class BmbSpiGenerator2(apbOffset : Handle[BigInt] = Unset) // Good Old MoSi, MiSo wihtout xdr
(implicit interconnect: BmbInterconnectGenerator, decoder : BmbImplicitPeripheralDecoder = null) extends Area {
val parameter = Handle[SpiMasterCtrlMemoryMappedConfig]
val spi = Handle(logic.io.spi.toIo)
val ctrl : Handle[Bmb] = Handle(logic.io.ctrl)
val interrupt = Handle(logic.io.interrupt)
val accessSource = Handle[BmbAccessCapabilities]
val accessRequirements = Handle[BmbAccessParameter]
val logic = Handle(BmbSpiMasterCtrl(parameter, accessRequirements.toBmbParameter()))
val bmbRequirements = Handle[BmbParameter]
val bmb = Handle[Bmb]
@dontName var interruptCtrl : InterruptCtrlGeneratorI = null
var interruptId = 0
def connectInterrupt(ctrl : InterruptCtrlGeneratorI, id : Int): Unit = {
ctrl.addInterrupt(interrupt, id)
interruptCtrl = ctrl
interruptId = id
}
interconnect.addSlave(
accessSource = accessSource,
accessCapabilities = accessSource.derivate(BmbGpio2.getBmbCapabilities),
accessRequirements = accessRequirements,
bus = ctrl,
mapping = apbOffset.derivate(SizeMapping(_, 1 << Gpio.addressWidth))
)
if(decoder != null) interconnect.addConnection(decoder.bus, ctrl)
}
--
case class BmbSpiMasterCtrl(p : SpiMasterCtrlMemoryMappedConfig, ctrlParameter : BmbParameter) extends Component{
val io = new Bundle {
val ctrl = slave(Bmb(ctrlParameter))
val spi = master(SpiMaster(p.ctrlGenerics.ssWidth))
val interrupt = out Bool()
}
val spiCtrl = SpiMasterCtrl(p.ctrlGenerics)
io.spi <> spiCtrl.io.spi
val busCtrl = BmbSlaveFactory(io.ctrl)
val bridge = spiCtrl.io.driveFrom(busCtrl)(p)
io.interrupt <> bridge.interruptCtrl.interrupt
}
And the driver...
#ifndef SPI_H_
#define SPI_H_
#include "type.h"
#include "io.h"
#define SPI_DATA 0x00
#define SPI_STATUS 0x04
#define SPI_CONFIG 0x08
#define SPI_CLK_DIVIDER 0x0C
#define SPI_SS_SETUP 0x10
#define SPI_SS_HOLD 0x14
#define SPI_SS_DISABLE 0x18
typedef struct {
u32 cpol;
u32 cpha;
u32 mode;
u32 clkDivider;
u32 ssSetup;
u32 ssHold;
u32 ssDisable;
} Spi_Config;
#define SPI_MISO_READ 0x01000000
#define SPI_RX_VALID 0x80000000
#define SPI_CMD_SS_EN 0x11000000
#define SPI_CMD_SS_DIS 0x10000000
#define SPI_RSP_VALID (1 << 31)
#define SPI_STATUS_CMD_INT_ENABLE (1 << 0)
#define SPI_STATUS_RSP_INT_ENABLE (1 << 1)
#define SPI_STATUS_CMD_INT_FLAG (1 << 8)
#define SPI_STATUS_RSP_INT_FLAG (1 << 9)
#define SPI_MODE_CPOL (1 << 0)
#define SPI_MODE_CPHA (1 << 1)
static u32 spi_cmdAvailability(u32 reg){
return read_u32(reg + SPI_STATUS) >> 16;
}
static u32 spi_rspOccupancy(u32 reg){
return read_u32(reg + SPI_STATUS) & SPI_STATUS_RSP_INT_FLAG;
}
static void spi_write(u32 reg, u8 data){
while(spi_cmdAvailability(reg) == 0); // wait for Tx Buffer to be available
write_u32((u32)data, reg + SPI_DATA); // just zero extend and write
}
static u8 spi_writeRead(u32 reg, u8 data){
u32 u;
while(spi_cmdAvailability(reg) == 0); // wait for Tx Buffer to be available
write_u32(SPI_MISO_READ | data, reg + SPI_DATA); // que transfer on SPI bus
while (1) {
u = read_u32(reg + SPI_DATA);
if (u & SPI_RX_VALID)
return u;
}
}
static u8 spi_read(u32 reg){
u32 u;
while(spi_cmdAvailability(reg) == 0); // wait for Tx Buffer to be available
write_u32(SPI_MISO_READ, reg + SPI_DATA); // que transfer on SPI bus
while (1) {
u = read_u32(reg + SPI_DATA);
if (u & SPI_RX_VALID)
return u;
}
}
static void spi_select(u32 reg, u32 slaveId){
while(spi_cmdAvailability(reg) == 0);
write_u32(SPI_CMD_SS_EN | slaveId, reg + SPI_DATA);
}
static void spi_deselect(u32 reg, u32 slaveId){
while(spi_cmdAvailability(reg) == 0);
write_u32(SPI_CMD_SS_DIS | slaveId, reg + SPI_DATA);
}
static void spi_applyConfig(u32 reg, Spi_Config *config){
write_u32((config->cpol << 0) | (config->cpha << 1) | (config->mode << 4), reg + SPI_CONFIG);
write_u32(config->clkDivider, reg + SPI_CLK_DIVIDER);
write_u32(config->ssSetup, reg + SPI_SS_SETUP);
write_u32(config->ssHold, reg + SPI_SS_HOLD);
write_u32(config->ssDisable, reg + SPI_SS_DISABLE);
}
#endif /* SPI_H_ */
As long as it works for you ^^
So, the idea of the XDR is to support DDR data rate, faster SPI phy, multiple data width, half / full duplex all at once.
How did you parametrized / instancied the ctrl / phy for the Xdr controller ?
This way
` val spiA = new BmbSpiGenerator2(0x100) (interconnect,periphDecoder) spiA.parameter load SpiMasterCtrlMemoryMappedConfig ( ctrlGenerics = SpiMasterCtrlGenerics( ssWidth = 1, dataWidth = 8, timerWidth = 12 ), cmdFifoDepth = 16, rspFifoDepth = 16 )
`
Oh, for the XDR this is the one..
`
val spiB = new BmbSpiGenerator(0x200) (interconnect, periphDecoder) {
val decoder = SpiPhyDecoderGenerator(phy)
val wifiSpi = decoder.spiMasterNone()
}
spiB.parameter load SpiXdrMasterCtrl.MemoryMappingParameters(
SpiXdrMasterCtrl.Parameters(
dataWidth = 8,
timerWidth = 12,
spi = SpiXdrParameter(
dataWidth = 1, // 2
ioRate = 1,
ssWidth = 1
)
//) .addFullDuplex(id = 0).addHalfDuplex(id = 1, rate = 1, ddr = false, spiWidth = 1, lateSampling = false),
) .addHalfDuplex(id = 1, rate = 1, ddr = false, spiWidth = 1, lateSampling = false),
cmdFifoDepth = 16,
rspFifoDepth = 16
)
`
Ahhh, so dataWidth need to be 2, and addFullDuplex(id = 0) need to remain i would say.
Hi Charles, I decided to go with the BmbSpiGenerator2 mentioned above, because it was within my comprehension.
Hi, How do I set up a standard SPI with data-width as 1 (i.e 1 MOSI and 1 MISO signal) BmbSpiGenerator() seems to work only when SpiXdrParameter.dataWidth is 2 or more...