mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
[Squash] Move I2C to IRQ based for big txn
Squash DMA attempt out .
This commit is contained in:
@@ -7,17 +7,80 @@
|
||||
#include "BSP.h"
|
||||
#include "IRQ.h"
|
||||
#include "Setup.h"
|
||||
#include "bl_mcu_sdk/drivers/bl702_driver/std_drv/inc/bl702_dma.h"
|
||||
extern "C" {
|
||||
#include "bflb_platform.h"
|
||||
#include "bl702_dma.h"
|
||||
#include "bl702_glb.h"
|
||||
#include "bl702_i2c.h"
|
||||
}
|
||||
#include <I2C_Wrapper.hpp>
|
||||
|
||||
// Semaphore for locking users of I2C
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
|
||||
#define I2C_TIME_OUT (uint16_t)(12000)
|
||||
void FRToSI2C::CpltCallback() {} // Not used
|
||||
#define I2C_TIME_OUT (uint16_t)(12000)
|
||||
#define I2C_TX_FIFO_ADDR (0x4000A300 + 0x88)
|
||||
|
||||
// Used by the irq handler
|
||||
|
||||
volatile uint8_t *irq_data_ptr;
|
||||
volatile uint8_t irq_data_size_left;
|
||||
|
||||
/****** IRQ Handlers ******/
|
||||
void i2c_irq_tx_fifo_low() {
|
||||
// Filling tx fifo
|
||||
// Fifo is 32 bit, LSB sent first
|
||||
// FiFo can store up to 2, 32-bit words
|
||||
// So we fill it until it has no free room (or we run out of data)
|
||||
|
||||
while (irq_data_size_left > 0 && I2C_GetTXFIFOAvailable() > 0) {
|
||||
// Can put in at least 1 byte
|
||||
|
||||
// Build a 32-bit word from bytes
|
||||
uint32_t value = 0;
|
||||
for (int i = 0; i < 4 && irq_data_size_left > 0; i++) {
|
||||
value >>= 8;
|
||||
value |= (*irq_data_ptr) << 24; // Shift to the left, adding new data to the higher byte
|
||||
irq_data_ptr++; // Shift to next byte
|
||||
irq_data_size_left--;
|
||||
}
|
||||
|
||||
// Push the new value to the fifo
|
||||
*((volatile uint32_t *)I2C_TX_FIFO_ADDR) = value;
|
||||
}
|
||||
if (irq_data_size_left == 0) {
|
||||
// Disable IRQ, were done
|
||||
I2C_IntMask(I2C0_ID, I2C_TX_FIFO_READY_INT, MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_irq_done() {
|
||||
|
||||
// Mask IRQ's back off
|
||||
I2C_IntMask(I2C0_ID, I2C_TRANS_END_INT, MASK);
|
||||
I2C_IntMask(I2C0_ID, I2C_NACK_RECV_INT, MASK);
|
||||
FRToSI2C::CpltCallback(); // Causes the lock to be released
|
||||
}
|
||||
void i2c_irq_nack() {
|
||||
|
||||
// Mask IRQ's back off
|
||||
I2C_IntMask(I2C0_ID, I2C_TRANS_END_INT, MASK);
|
||||
I2C_IntMask(I2C0_ID, I2C_NACK_RECV_INT, MASK);
|
||||
FRToSI2C::CpltCallback(); // Causes the lock to be released
|
||||
}
|
||||
|
||||
/****** END IRQ Handlers ******/
|
||||
void FRToSI2C::CpltCallback() {
|
||||
// This is only triggered from IRQ context
|
||||
|
||||
I2C_Disable(I2C0_ID); // Disable I2C to tidy up
|
||||
|
||||
// Unlock the semaphore && allow task switch if desired by RTOS
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xSemaphoreGiveFromISR(I2CSemaphore, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); }
|
||||
|
||||
@@ -56,6 +119,7 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_bu
|
||||
if (!lock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_Transfer_Cfg i2cCfg = {0, DISABLE, 0, 0, 0, 0};
|
||||
BL_Err_Type err = ERROR;
|
||||
i2cCfg.slaveAddr = DevAddress >> 1;
|
||||
@@ -65,16 +129,36 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_bu
|
||||
i2cCfg.data = p_buffer;
|
||||
i2cCfg.subAddrSize = 1; // one byte address
|
||||
|
||||
vTaskSuspendAll();
|
||||
/* --------------- */
|
||||
err = I2C_MasterSendBlocking(I2C0_ID, &i2cCfg);
|
||||
xTaskResumeAll();
|
||||
bool res = err == SUCCESS;
|
||||
if (!res) {
|
||||
I2C_Unstick();
|
||||
if (number_of_byte <= 32) {
|
||||
vTaskSuspendAll();
|
||||
/* --------------- */
|
||||
err = I2C_MasterSendBlocking(I2C0_ID, &i2cCfg);
|
||||
xTaskResumeAll();
|
||||
bool res = err == SUCCESS;
|
||||
if (!res) {
|
||||
I2C_Unstick();
|
||||
}
|
||||
unlock();
|
||||
return res;
|
||||
} else {
|
||||
// Store handles for IRQ
|
||||
irq_data_ptr = p_buffer;
|
||||
irq_data_size_left = number_of_byte;
|
||||
|
||||
// Setup and run
|
||||
I2C_Init(I2C0_ID, I2C_WRITE, &i2cCfg); // Setup hardware for the I2C init header with the device address
|
||||
I2C_IntMask(I2C0_ID, I2C_TRANS_END_INT, UNMASK);
|
||||
I2C_IntMask(I2C0_ID, I2C_NACK_RECV_INT, UNMASK);
|
||||
I2C_IntMask(I2C0_ID, I2C_TX_FIFO_READY_INT, UNMASK);
|
||||
I2C_Int_Callback_Install(I2C0_ID, I2C_TRANS_END_INT, i2c_irq_done);
|
||||
I2C_Int_Callback_Install(I2C0_ID, I2C_NACK_RECV_INT, i2c_irq_nack);
|
||||
I2C_Int_Callback_Install(I2C0_ID, I2C_TX_FIFO_READY_INT, i2c_irq_tx_fifo_low);
|
||||
i2c_irq_tx_fifo_low(); // Pre-fill fifo
|
||||
// Start
|
||||
I2C_Enable(I2C0_ID);
|
||||
// Dont unlock as tx is still ongoing, will be cleared in irq of i2c finishing
|
||||
return true;
|
||||
}
|
||||
unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); }
|
||||
|
||||
Reference in New Issue
Block a user