Add the TX FIFO the I2C driver.

This commit is contained in:
Jonathan Naylor 2020-11-19 16:50:21 +00:00
parent 7f7ce2072a
commit a119311d93
3 changed files with 50 additions and 31 deletions

View File

@ -35,7 +35,10 @@ const uint16_t I2C_ADDR = 0U; // XXX FIXME
CI2CPort::CI2CPort(uint8_t n) :
m_n(n),
m_ok(false)
m_ok(false),
m_fifo(),
m_fifoHead(0U),
m_fifoTail(0U)
{
}
@ -69,14 +72,14 @@ bool CI2CPort::init()
NVIC_InitTypeDef NVIC_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB1PeriphClockCmd(i2CClock, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_AHB1PeriphClockCmd(i2CClock, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_AFIO, ENABLE);
// Configure I2C GPIOs
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Configure the I2C event interrupt
@ -107,25 +110,48 @@ bool CI2CPort::init()
I2C_ITConfig(i2CPort, I2C_IT_BUF, ENABLE);
I2C_ITConfig(i2CPort, I2C_IT_ERR, ENABLE);
m_fifoHead = 0U;
m_fifoTail = 0U;
m_ok = true;
return true;
}
uint8_t CI2CPort::writeCommand(const uint8_t* data, uint8_t length)
uint8_t CI2CPort::write(const uint8_t* data, uint8_t length)
{
if (!m_ok)
return 6U;
return 6U;
for (uint16_t i = 0U; i < length; i++)
fifoPut(data[i]);
return 0U;
}
uint8_t CI2CPort::writeData(const uint8_t* data, uint8_t length)
uint16_t CI2CPort::fifoLevel()
{
if (!m_ok)
return 6U;
uint32_t tail = m_fifoTail;
uint32_t head = m_fifoHead;
return 6U;
if (tail > head)
return I2C_TX_FIFO_SIZE + head - tail;
else
return head - tail;
}
bool CI2CPort::fifoPut(uint8_t next)
{
if (fifoLevel() >= I2C_TX_FIFO_SIZE)
return false;
m_fifo[m_fifoHead] = next;
m_fifoHead++;
if (m_fifoHead >= I2C_TX_FIFO_SIZE)
m_fifoHead = 0U;
return true;
}
#endif

View File

@ -25,6 +25,8 @@
#include <cstdint>
const uint16_t I2C_TX_FIFO_SIZE = 512U;
class CI2CPort {
public:
@ -32,13 +34,17 @@ public:
bool init();
uint8_t writeCommand(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint8_t length);
private:
uint8_t m_n;
bool m_ok;
volatile uint8_t m_fifo[I2C_TX_FIFO_SIZE];
volatile uint16_t m_fifoHead;
volatile uint16_t m_fifoTail;
uint16_t fifoLevel();
bool fifoPut(uint8_t next);
};
#endif

View File

@ -127,9 +127,6 @@ const uint8_t PROTOCOL_VERSION = 2U;
const int MAX_SERIAL_DATA = 250;
const uint16_t MAX_SERIAL_COUNT = 100U;
// I2C types
const uint8_t I2C_COMMAND = 0x00U;
const uint8_t I2C_DATA = 0x40U;
CSerialPort::CSerialPort() :
m_buffer(),
@ -1316,22 +1313,12 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
#if defined(I2C_REPEATER)
case MMDVM_I2C_DATA: {
uint8_t type = buffer[0U];
switch (type) {
case I2C_COMMAND:
err = i2c1.writeCommand(buffer + 1U, length - 1U);
break;
case I2C_DATA:
err = i2c1.writeData(buffer + 1U, length - 1U);
break;
default:
DEBUG2("Received invalid I2C type", type);
err = 4U;
break;
}
if (err != 0U)
err = i2c1.write(buffer, length);
if (err != 0U) {
DEBUG2("Received invalid I2C data", err);
sendNAK(err);
}
}
break;
#endif