mirror of https://github.com/g4klx/MMDVM.git
Use information from STM32Cube to update the I2C driver.
This commit is contained in:
parent
f033fea2fb
commit
2ae731e78c
115
I2CPort.cpp
115
I2CPort.cpp
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
|
const uint16_t MAX_NBYTES_SIZE = 255U;
|
||||||
|
|
||||||
CI2CPort::CI2CPort(uint8_t n) :
|
CI2CPort::CI2CPort(uint8_t n) :
|
||||||
m_port(NULL),
|
m_port(NULL),
|
||||||
|
@ -97,11 +98,11 @@ bool CI2CPort::init()
|
||||||
|
|
||||||
// Configure and Initialize the I2C
|
// Configure and Initialize the I2C
|
||||||
I2C_InitTypeDef I2C_InitStructure;
|
I2C_InitTypeDef I2C_InitStructure;
|
||||||
I2C_InitStructure.I2C_Timing = 50000U; //400kHz (Fast Mode)
|
I2C_InitStructure.I2C_Timing = 0x0010061AU; // 400kHz (Fast Mode)
|
||||||
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
|
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
|
||||||
I2C_InitStructure.I2C_DigitalFilter = 7U;
|
I2C_InitStructure.I2C_DigitalFilter = 0U; // No digital filter
|
||||||
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
||||||
I2C_InitStructure.I2C_OwnAddress1 = 0x00U; //We are the master. We don't need this
|
I2C_InitStructure.I2C_OwnAddress1 = 0x00U; // We are the master. We don't need this
|
||||||
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
|
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
|
||||||
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||||
|
|
||||||
|
@ -121,68 +122,49 @@ uint8_t CI2CPort::write(uint8_t addr, const uint8_t* data, uint16_t length)
|
||||||
if (!m_ok)
|
if (!m_ok)
|
||||||
return 6U;
|
return 6U;
|
||||||
|
|
||||||
// Generate a start condition. (As soon as the line becomes idle, a Start condition will be generated)
|
// Wait for the I2C transmitter to become free
|
||||||
m_port->CR2 |= I2C_CR2_START;
|
if (waitISRFlagsSet(I2C_ISR_BUSY))
|
||||||
|
return 6U;
|
||||||
|
|
||||||
// Set I2C device address if needed
|
// Configure the data transfer
|
||||||
if (addr != m_addr) {
|
uint16_t size;
|
||||||
bool ret = setAddr(addr, I2C_Direction_Transmitter);
|
if (length > MAX_NBYTES_SIZE)
|
||||||
if (!ret)
|
size = MAX_NBYTES_SIZE;
|
||||||
return 7U;
|
else
|
||||||
|
size = length;
|
||||||
m_addr = addr;
|
configureDataTransfer(size);
|
||||||
}
|
|
||||||
|
|
||||||
// Unstretch the clock by just reading ISR (Physically the clock is continued to be strectehed because we have not written anything to the TXDR yet.)
|
|
||||||
(void)m_port->ISR;
|
|
||||||
|
|
||||||
// Start Writing Data
|
// Start Writing Data
|
||||||
while (length--) {
|
while (length > 0U) {
|
||||||
bool ret = write(*data++);
|
// Wait for the TXIS flag to be set
|
||||||
if (!ret)
|
if (waitISRFlagsSet(I2C_ISR_TXIS))
|
||||||
return 7U;
|
return 6U;
|
||||||
|
|
||||||
|
// Write the byte to the TXDR
|
||||||
|
m_port->TXDR = *data++;
|
||||||
|
length--;
|
||||||
|
size--;
|
||||||
|
|
||||||
|
// Configure the data transfer
|
||||||
|
if (size == 0U && length > 0U) {
|
||||||
|
if (length > MAX_NBYTES_SIZE)
|
||||||
|
size = MAX_NBYTES_SIZE;
|
||||||
|
else
|
||||||
|
size = length;
|
||||||
|
configureDataTransfer(size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the data on the shift register to be transmitted completely
|
if (waitISRFlagsSet(I2C_ISR_STOPF))
|
||||||
bool ret = waitISRFlagsSet(I2C_ISR_TC);
|
return 6U;
|
||||||
if (!ret)
|
|
||||||
return 7U;
|
|
||||||
|
|
||||||
// Here TXE=BTF=1. Therefore the clock stretches again.
|
m_port->ISR &= ~I2C_ISR_STOPF;
|
||||||
|
|
||||||
// Order a stop condition at the end of the current tranmission (or if the clock is being streched, generate stop immediatelly)
|
m_port->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN));
|
||||||
m_port->CR2 |= I2C_CR2_STOP;
|
|
||||||
|
|
||||||
// Stop condition resets the TXE and BTF automatically.
|
|
||||||
|
|
||||||
// Wait to be sure that line is iddle
|
|
||||||
ret = waitLineIdle();
|
|
||||||
if (!ret)
|
|
||||||
return 7U;
|
|
||||||
|
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CI2CPort::write(uint8_t c)
|
|
||||||
{
|
|
||||||
// Write the byte to the TXDR
|
|
||||||
m_port->TXDR = c;
|
|
||||||
|
|
||||||
// Wait till the content of TXDR is transferred to the shift Register.
|
|
||||||
return waitISRFlagsSet(I2C_ISR_TXE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CI2CPort::setAddr(uint8_t addr, uint8_t dir)
|
|
||||||
{
|
|
||||||
// Write address to the TXDR (to the bus)
|
|
||||||
m_port->TXDR = (addr << 1) | dir;
|
|
||||||
|
|
||||||
// Wait till ADDR is set (ADDR is set when the slave sends ACK to the address).
|
|
||||||
// Clock streches till ADDR is Reset. To reset the hardware i)Read the SR1 ii)Wait till ADDR is Set iii)Read SR2
|
|
||||||
// Note1:Spec_p602 recommends the waiting operation
|
|
||||||
return waitISRFlagsSet(I2C_ISR_ADDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CI2CPort::waitISRFlagsSet(uint32_t flags)
|
bool CI2CPort::waitISRFlagsSet(uint32_t flags)
|
||||||
{
|
{
|
||||||
// Wait till the specified ISR Bits are set
|
// Wait till the specified ISR Bits are set
|
||||||
|
@ -197,20 +179,19 @@ bool CI2CPort::waitISRFlagsSet(uint32_t flags)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CI2CPort::waitLineIdle()
|
void CI2CPort::configureDataTransfer(uint8_t size)
|
||||||
{
|
{
|
||||||
// Wait till the Line becomes idle.
|
m_port->CR2 &= ~(I2C_CR2_SADD |
|
||||||
uint32_t timeOut = HSI_VALUE;
|
I2C_CR2_NBYTES |
|
||||||
|
I2C_CR2_RELOAD |
|
||||||
// Check to see if the Line is busy
|
I2C_CR2_AUTOEND |
|
||||||
// This bit is set automatically when a start condition is broadcast on the line (even from another master)
|
(I2C_CR2_RD_WRN & (uint32_t)(I2C_Generate_Start_Write >> (31U - I2C_CR2_RD_WRN_Pos))) |
|
||||||
// and is reset when stop condition is detected.
|
I2C_CR2_START |
|
||||||
while (m_port->ISR & I2C_ISR_BUSY) {
|
I2C_CR2_STOP);
|
||||||
if (!(timeOut--))
|
m_port->CR2 |= (uint32_t)(((uint32_t)m_addr & I2C_CR2_SADD) |
|
||||||
return false;
|
(((uint32_t)size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) |
|
||||||
}
|
(uint32_t)I2C_CR2_RELOAD |
|
||||||
|
(uint32_t)I2C_Generate_Start_Write);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,10 +52,8 @@ private:
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
uint8_t m_addr;
|
uint8_t m_addr;
|
||||||
|
|
||||||
bool setAddr(uint8_t addr, uint8_t dir);
|
|
||||||
bool write(uint8_t c);
|
|
||||||
bool waitISRFlagsSet(uint32_t flags);
|
bool waitISRFlagsSet(uint32_t flags);
|
||||||
bool waitLineIdle();
|
void configureDataTransfer(uint8_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6241f7c05eeb6cf1ecd16ca0274bf310efee853f
|
Subproject commit a06aca356cbfb4db847c66512e0a6ee52e58b116
|
Loading…
Reference in New Issue