Skip to content

Commit

Permalink
soapy: AXI IIC driver changes
Browse files Browse the repository at this point in the history
soapy: Only change what's needed

Signed-off-by: João Silva <[email protected]>
  • Loading branch information
vankxr committed Nov 10, 2024
1 parent 65c253e commit ac60c49
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
46 changes: 31 additions & 15 deletions software/soapy/src/AXIIIC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,29 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
if((this->readReg(AXI_IIC_REG_SR) & AXI_IIC_REG_SR_BB) && !(this->readReg(AXI_IIC_REG_ISR) & AXI_IIC_REG_IxR_INT2_TX_EMPTY)) // Bus busy and not owner
throw std::runtime_error("AXI IIC: Bus busy");

uint32_t cr = this->readReg(AXI_IIC_REG_CR);

if(!(cr & AXI_IIC_REG_CR_EN))
throw std::runtime_error("AXI IIC: Peripheral not enabled");

if(!(this->readReg(AXI_IIC_REG_SR) & AXI_IIC_REG_SR_TX_FIFO_EMPTY)) // Clear TX FIFO
{
uint32_t reg = this->readReg(AXI_IIC_REG_CR);

this->writeReg(AXI_IIC_REG_CR, reg | AXI_IIC_REG_CR_TXFIFO_RESET);
this->writeReg(AXI_IIC_REG_CR, reg & ~AXI_IIC_REG_CR_TXFIFO_RESET);
this->writeReg(AXI_IIC_REG_CR, cr | AXI_IIC_REG_CR_TXFIFO_RESET);
this->writeReg(AXI_IIC_REG_CR, cr & ~AXI_IIC_REG_CR_TXFIFO_RESET);
}

while(!(this->readReg(AXI_IIC_REG_SR) & AXI_IIC_REG_SR_RX_FIFO_EMPTY)) // Clear RX FIFO
uint32_t timeout = 50;

while(--timeout && !(this->readReg(AXI_IIC_REG_SR) & AXI_IIC_REG_SR_RX_FIFO_EMPTY)) // Clear RX FIFO
(void)this->readReg(AXI_IIC_REG_RX_FIFO);

if(!timeout)
{
this->reinit();

throw std::runtime_error("AXI IIC: Timeout while clearing RX FIFO");
}

this->writeReg(AXI_IIC_REG_ISR, this->readReg(AXI_IIC_REG_ISR)); // Clear IRQs
this->writeReg(AXI_IIC_REG_TX_FIFO, ((stop == AXIIIC::Stop::STOP && !count) ? AXI_IIC_REG_TX_FIFO_STOP : 0) | AXI_IIC_REG_TX_FIFO_START | address);

Expand All @@ -142,17 +154,23 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
{
this->writeReg(AXI_IIC_REG_TX_FIFO, (stop == AXIIIC::Stop::STOP ? AXI_IIC_REG_TX_FIFO_STOP : 0) | count);
}
else
else // Write
{
uint32_t timeout = 50;
timeout = 50;

flags = this->readReg(AXI_IIC_REG_ISR);

while(--timeout && (flags & AXI_IIC_REG_IxR_INT4_BUS_NOT_BUSY))
while(--timeout)
{
this->writeReg(AXI_IIC_REG_ISR, flags & AXI_IIC_REG_IxR_INT4_BUS_NOT_BUSY);
flags = this->readReg(AXI_IIC_REG_ISR);

if(!(flags & AXI_IIC_REG_IxR_INT4_BUS_NOT_BUSY))
break; // Bus busy, START + ADDR sent, good to go!

if(flags & (AXI_IIC_REG_IxR_INT1_TERR_STC | AXI_IIC_REG_IxR_INT0_ARB_LOST))
break; // Some kind of error occured, will be handled later, but the START + ADDR was sent, good to go!

std::this_thread::sleep_for(std::chrono::microseconds(1));
}

Expand All @@ -170,7 +188,7 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
{
if(address & 1) // Read
{
uint32_t timeout = 500;
timeout = 500;

while(--timeout)
{
Expand Down Expand Up @@ -202,7 +220,7 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
}
else // Write
{
uint32_t timeout = 500;
timeout = 500;

while(--timeout)
{
Expand Down Expand Up @@ -239,7 +257,7 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
this->writeReg(AXI_IIC_REG_ISR, this->readReg(AXI_IIC_REG_ISR) & AXI_IIC_REG_IxR_INT4_BUS_NOT_BUSY); // Clear NOT_BUSY IRQ, so that if we encounter it set again it is really not busy
}

uint32_t timeout = 500;
timeout = 500;

while(--timeout)
{
Expand All @@ -262,15 +280,13 @@ void AXIIIC::transmit(uint8_t address, uint8_t *buf, uint8_t count, AXIIIC::Stop
if(stop == AXIIIC::Stop::STOP && (flags & AXI_IIC_REG_IxR_INT4_BUS_NOT_BUSY))
break; // Stop was requested and bus is free, we are done!

if(stop == AXIIIC::Stop::RESTART && !(address & 1) && (flags & AXI_IIC_REG_IxR_INT2_TX_EMPTY))
if(stop != AXIIIC::Stop::STOP && !(address & 1) && (flags & AXI_IIC_REG_IxR_INT2_TX_EMPTY))
break; // No stop was requested and bus is throttled by the master, waiting for another transaction, we are done!

if(stop == AXIIIC::Stop::RESTART && (address & 1))
if(stop != AXIIIC::Stop::STOP && (address & 1))
break; // No stop was requested and we already read all the bytes we wanted, no need to wait for the bus to be free, we are done!

std::this_thread::sleep_for(std::chrono::microseconds(1));

flags = this->readReg(AXI_IIC_REG_ISR);
}

if(!timeout)
Expand Down
24 changes: 19 additions & 5 deletions software/soapy/src/SPIFlash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,25 @@ SPIFlash::SPIFlash(SPIFlash::SPIConfig spi)

this->resetContinuousRead();

this->writeEnable();
this->writeStatus2(BIT(1)); // Set the QE bit
this->writeEnable();
this->writeStatus3(0x00); // Set maximum drive strength
this->writeDisable(); // Needed in case device does not support status 3 register, otherwise the WE bit may be left set
// Set the QE bit
uint8_t sr2 = this->readStatus2();

if(!(sr2 & BIT(1)))
{
this->writeEnable();
this->writeStatus2(sr2 | BIT(1));
this->writeDisable(); // Needed in case device does not support status 2 register, otherwise the WE bit may be left set
}

// Set drive strength (0 = 100%, 1 = 75%, 2 = 50%, 3 = 25%)
uint8_t sr3 = this->readStatus3();

if(sr3 != 0xFF && (sr3 & 0x60) != 0x00)
{
this->writeEnable();
this->writeStatus3(0x00);
this->writeDisable(); // Needed in case device does not support status 3 register, otherwise the WE bit may be left set
}

this->detectDevice();
}
Expand Down

0 comments on commit ac60c49

Please sign in to comment.