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) : CI2CPort::CI2CPort(uint8_t n) :
m_n(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; NVIC_InitTypeDef NVIC_InitStructure;
I2C_InitTypeDef I2C_InitStructure; I2C_InitTypeDef I2C_InitStructure;
RCC_APB1PeriphClockCmd(i2CClock, ENABLE); RCC_AHB1PeriphClockCmd(i2CClock, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_AFIO, ENABLE);
// Configure I2C GPIOs // Configure I2C GPIOs
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 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); GPIO_Init(GPIOB, &GPIO_InitStructure);
// Configure the I2C event interrupt // Configure the I2C event interrupt
@ -107,25 +110,48 @@ bool CI2CPort::init()
I2C_ITConfig(i2CPort, I2C_IT_BUF, ENABLE); I2C_ITConfig(i2CPort, I2C_IT_BUF, ENABLE);
I2C_ITConfig(i2CPort, I2C_IT_ERR, ENABLE); I2C_ITConfig(i2CPort, I2C_IT_ERR, ENABLE);
m_fifoHead = 0U;
m_fifoTail = 0U;
m_ok = true; m_ok = true;
return 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) if (!m_ok)
return 6U; 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) uint32_t tail = m_fifoTail;
return 6U; 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 #endif

View File

@ -25,6 +25,8 @@
#include <cstdint> #include <cstdint>
const uint16_t I2C_TX_FIFO_SIZE = 512U;
class CI2CPort { class CI2CPort {
public: public:
@ -32,13 +34,17 @@ public:
bool init(); bool init();
uint8_t writeCommand(const uint8_t* data, uint8_t length); uint8_t write(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
private: private:
uint8_t m_n; uint8_t m_n;
bool m_ok; 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 #endif

View File

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