read and write both working

sipo
Ondřej Hruška 7 years ago
parent f917427be4
commit cdd54cc550
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 109
      units/i2c/unit_i2c.c

@ -231,7 +231,7 @@ static bool UI2C_init(Unit *unit)
priv->dnf); priv->dnf);
LL_I2C_SetTiming(priv->periph, timing); LL_I2C_SetTiming(priv->periph, timing);
LL_I2C_DisableClockStretching(priv->periph); //LL_I2C_DisableClockStretching(priv->periph);
LL_I2C_Enable(priv->periph); LL_I2C_Enable(priv->periph);
LL_I2C_DisableOwnAddress1(priv->periph); // OA not used LL_I2C_DisableOwnAddress1(priv->periph); // OA not used
@ -272,6 +272,8 @@ static void UI2C_deInit(Unit *unit)
enum PinCmd_ { enum PinCmd_ {
CMD_WRITE = 0, CMD_WRITE = 0,
CMD_READ = 1, CMD_READ = 1,
CMD_WRITE_ADDR = 2,
CMD_READ_ADDR = 3,
}; };
static void i2c_reset(struct priv *priv) static void i2c_reset(struct priv *priv)
@ -281,8 +283,7 @@ static void i2c_reset(struct priv *priv)
LL_I2C_Enable(priv->periph); LL_I2C_Enable(priv->periph);
} }
static bool i2c_wait_until_flag(struct priv *priv, TF_ID frame_id, uint32_t flag, static bool i2c_wait_until_flag(struct priv *priv, TF_ID frame_id, uint32_t flag, bool stop_state, const char *msg)
bool stop_state, const char *msg)
{ {
uint32_t t_start = HAL_GetTick(); uint32_t t_start = HAL_GetTick();
while (((priv->periph->ISR & flag)!=0) != stop_state) { while (((priv->periph->ISR & flag)!=0) != stop_state) {
@ -292,6 +293,7 @@ static bool i2c_wait_until_flag(struct priv *priv, TF_ID frame_id, uint32_t flag
return false; return false;
} }
} }
return true;
} }
/** Handle a request message */ /** Handle a request message */
@ -304,89 +306,74 @@ static bool UI2C_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Payl
uint32_t len; uint32_t len;
uint32_t t_start; uint32_t t_start;
switch (command) { addr = pp_u16(pp); // 10-bit address has the highest bit set to 1 to indicate this
case CMD_WRITE:; addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10);
addrsize = pp_u8(pp); // 7 or 10 addr &= 0x3FF;
addr = pp_u16(pp);
t_start = HAL_GetTick(); uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT;
while (LL_I2C_IsActiveFlag_BUSY(priv->periph)) {
if (HAL_GetTick() - t_start > 10) { // 7-bit address must be shifted to left for LL to use it correctly
com_respond_err(frame_id, "BUSY TIMEOUT"); if (addrsize == 7) addr <<= 1;
i2c_reset(priv);
return false; if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_BUSY, 0, "BUSY TIMEOUT")) return false;
}
}
// if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_BUSY, 0, "BUSY TIMEOUT")) return false;
uint32_t chunk_remain; uint32_t chunk_remain;
bool first;
switch (command) {
case CMD_WRITE:;
// u16 address - already read
first = true;
while (pp_length(pp) > 0) { while (pp_length(pp) > 0) {
len = pp_length(pp); len = pp_length(pp);
chunk_remain = (uint8_t) ((len > 255) ? 255 : len), // if more than 255, first chunk is 255 chunk_remain = (uint8_t) ((len > 255) ? 255 : len); // if more than 255, first chunk is 255
LL_I2C_HandleTransfer(priv->periph, LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain,
(addrsize == 7) ? addr << 1 : addr, // Address must be shifted to left by one if 7-bit mode is used. Bit 0 serves for R/W flag
(addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT, // translate to LL bitfields
(uint32_t) chunk_remain,
(len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk (len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk
LL_I2C_GENERATE_START_WRITE); first ? LL_I2C_GENERATE_START_WRITE : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing
first = false;
for (; chunk_remain > 0; chunk_remain--) { for (; chunk_remain > 0; chunk_remain--) {
t_start = HAL_GetTick(); if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_TXIS, 1, "TXIS TIMEOUT")) return false;
while (!LL_I2C_IsActiveFlag_TXIS(priv->periph)) {
if (HAL_GetTick() - t_start > 10) {
com_respond_err(frame_id, "TXIS TIMEOUT");
i2c_reset(priv);
return false;
}
}
uint8_t byte = pp_u8(pp); uint8_t byte = pp_u8(pp);
LL_I2C_TransmitData8(priv->periph, byte); LL_I2C_TransmitData8(priv->periph, byte);
} }
} }
t_start = HAL_GetTick(); if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_STOPF, 1, "STOPF TIMEOUT")) return false;
while (!LL_I2C_IsActiveFlag_STOP(priv->periph)) { LL_I2C_ClearFlag_STOP(priv->periph);
if (HAL_GetTick() - t_start > 10) {
com_respond_err(frame_id, "STOPF TIMEOUT");
i2c_reset(priv);
return false;
}
}
break; break;
case CMD_READ: case CMD_READ:
addrsize = pp_u8(pp); // 7 or 10 // u16 address - already read
addr = pp_u16(pp);
len = pp_u16(pp); len = pp_u16(pp);
// TODO support > 255? first = true;
if (len > 256) { uint32_t n = 0;
com_respond_err(frame_id, "TOO LONG"); while (len > 0) {
return false; if (!first) {
if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_TCR, 1, "TCR TIMEOUT")) return false;
} }
LL_I2C_HandleTransfer(priv->periph, chunk_remain = (uint8_t) ((len > 255) ? 255 : len); // if more than 255, first chunk is 255
(addrsize == 7) ? addr << 1 : addr, LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain,
addrsize == 7 ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT, (len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk
(uint32_t) pp_length(pp), first ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing
LL_I2C_MODE_AUTOEND, // ? first = false;
LL_I2C_GENERATE_START_READ); len -= chunk_remain;
for (uint32_t i = 0; i < len; i++) { for (; chunk_remain > 0; chunk_remain--) {
t_start = HAL_GetTick(); if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_RXNE, 1, "RXNE TIMEOUT")) return false;
while (!LL_I2C_IsActiveFlag_RXNE(priv->periph)) {
// wait for RXNE uint8_t byte = LL_I2C_ReceiveData8(priv->periph);
if (HAL_GetTick() - t_start > 10) { unit_tmp512[n++] = byte;
com_respond_err(frame_id, "RX TIMEOUT");
return false;
} }
} }
uint8_t b = LL_I2C_ReceiveData8(priv->periph); if (!i2c_wait_until_flag(priv, frame_id, I2C_ISR_STOPF, 1, "STOPF TIMEOUT")) return false;
unit_tmp512[i] = b; LL_I2C_ClearFlag_STOP(priv->periph);
}
com_respond_buf(frame_id, MSG_SUCCESS, (uint8_t *) unit_tmp512, len); com_respond_buf(frame_id, MSG_SUCCESS, (uint8_t *) unit_tmp512, len);
break; break;

Loading…
Cancel
Save