Im trying to stream bus data from another microcontroller to the esp32 per I2C.
The ESP32 is the I2C master.
Problem is, there appear delays in longer telegrams in the I2C stream, the esp32 seems to have issues with it.
Im not exactly sure why that is, but the issue seems to be on ESP32 side. Maybe Interrupt priority issues? I didnt manage to force the i2c to use an higher priority yet. My tasks mainly use Task priority 1 and 2.
here is the interrupt allocation routine.
Code: Select all
esp_err_t I2C_MASTER_MODB_init(void)
{
int i2c_master_port = I2C_MASTER_MODB_NUM;
ESP_ERROR_CHECK(gpio_set_direction(I2C_MASTER_MODB_SCL_IO, GPIO_MODE_INPUT_OUTPUT_OD));
ESP_ERROR_CHECK(gpio_set_direction(I2C_MASTER_MODB_SDA_IO, GPIO_MODE_INPUT_OUTPUT_OD));
ESP_ERROR_CHECK(gpio_set_pull_mode(I2C_MASTER_MODB_SCL_IO, GPIO_PULLUP_ONLY));
ESP_ERROR_CHECK(gpio_set_pull_mode(I2C_MASTER_MODB_SDA_IO, GPIO_PULLUP_ONLY));
ESP_ERROR_CHECK(gpio_set_direction(I2C_MASTER_MODB_ADDCS_IO, GPIO_MODE_INPUT));
ESP_ERROR_CHECK(gpio_set_pull_mode(I2C_MASTER_MODB_ADDCS_IO, GPIO_PULLUP_ONLY));
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_MODB_SDA_IO,
.scl_io_num = I2C_MASTER_MODB_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
// raised interrupt priority - TBD test
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM);
}
Code: Select all
unsigned char glob_i2c_iLastModbusReadSize = 0;
unsigned char arr_i2c_ucLastModbusReadBuf[256];
void IRAM_ATTR i2c_PIC24_UART485_read(unsigned char* getc, short size_getc, unsigned short* sI2CModbusResponse)
{
i2c_port_t i2c_num = I2C_MASTER_MODB_NUM;
unsigned char i2c_writecount_or_read = 2;
unsigned short i2c_ResponseSize = 3;
unsigned char i2c_writecount_buffer_response = size_getc + 2;
unsigned char i2c_reg = I2C_REG_MODBUS_READ;
unsigned short i2c_response = I2C_MODBUS_Negative_Acknowledge;
if(((size_getc + i2c_ResponseSize) < 256) && (size_getc > 0) )
{
if(size_getc >= 9)
{
volatile short TBDBreakpoint = 5; // In diesem Fall Problem
TBDBreakpoint = 6;
}
TaskHandle_t taskHandle = xGetCurrentTaskHandle();
UBaseType_t taskPrior = uxTaskPriorityGet(taskHandle);
vTaskDelay(20 / portTICK_PERIOD_MS);
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (IO_EXP_BOARD_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, i2c_writecount_or_read, ACK_CHECK_EN);
i2c_master_write_byte(cmd, i2c_reg, ACK_CHECK_EN);
i2c_master_write_byte(cmd, i2c_writecount_buffer_response, ACK_CHECK_EN);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 3000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
*sI2CModbusResponse = I2C_MODBUS_Negative_Acknowledge;
vTaskDelay(100 / portTICK_PERIOD_MS);
return;
}
vTaskDelay(30 / portTICK_PERIOD_MS);
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (IO_EXP_BOARD_ADDR << 1) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, (unsigned char*) &glob_i2c_iLastModbusReadSize, ACK_VAL);
//i2c_master_read(cmd, (unsigned char*)&i2c_response, 2, ACK_VAL);
i2c_master_read_byte(cmd, (unsigned char*)&i2c_response, ACK_VAL);
i2c_master_read_byte(cmd, (unsigned char*)(((unsigned char*)&i2c_response) +1), ACK_VAL);
// anscheinend kann Read nur einmal pro command verwendet werden
// size_getc verwenden
if (size_getc > 1) {
i2c_master_read(cmd, (unsigned char*)arr_i2c_ucLastModbusReadBuf, size_getc-1, ACK_VAL);
}
i2c_master_read_byte(cmd, &(((unsigned char*)arr_i2c_ucLastModbusReadBuf)[size_getc-1]), NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 5000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
vTaskDelay(50 / portTICK_PERIOD_MS); // stattdessen pollen, könnte länger dauern... dynamische Zeit
if (ret != ESP_OK) {
*sI2CModbusResponse = I2C_MODBUS_Negative_Acknowledge;
vTaskDelay(100 / portTICK_PERIOD_MS);
return;
}
*sI2CModbusResponse = i2c_response;
memcpy( getc, arr_i2c_ucLastModbusReadBuf, min(size_getc, glob_i2c_iLastModbusReadSize));
vTaskDelay(10 / portTICK_PERIOD_MS);
return;
}
else
{
// error overflow
*sI2CModbusResponse = I2C_MODBUS_Negative_Acknowledge;
return;
}
}
My settings are
Code: Select all
#define I2C_MASTER_FREQ_HZ 50000 // 100000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_MODB_SCL_IO 16 /*CONFIG_I2C_MASTER_SCL*/ /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_MODB_SDA_IO 32 /*CONFIG_I2C_MASTER_SDA*/ /*!< GPIO number used for I2C master data */
#define I2C_MASTER_MODB_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_MODB_TIMEOUT_MS 1000
#define I2C_MASTER_MODB_ADDCS_IO 4 /*!< GPIO number used for I2C additional CS */
#define ESP_I2C_ADDR 0x11 // Address of this ESP32
#define IO_EXP_BOARD_ADDR 0x12 // Address of IO_EXP
#define REGISTER_IDENTIFICATION_ADDR 0x1 // Address of Identification Register
#define REGISTER_PWR_MGMT_1_REG_ADDR 0xA // Address of the power managment register
#define REGISTER_PWR_MGMT_1_RESET_BIT 7
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */