GPIO expander intr fix + some display need post CS time when switching rate between SPI devices - release

This commit is contained in:
Philippe G
2021-12-31 18:25:59 -08:00
parent 9789bef653
commit e8f8239ee3
4 changed files with 31 additions and 20 deletions

View File

@@ -140,6 +140,7 @@ static const struct GDS_Device SH1106 = {
.SetLayout = SetLayout, .SetLayout = SetLayout,
.Update = Update, .Init = Init, .Update = Update, .Init = Init,
.Depth = 1, .Depth = 1,
.CS_post = 2,
#if !defined SHADOW_BUFFER && defined USE_IRAM #if !defined SHADOW_BUFFER && defined USE_IRAM
.Alloc = GDS_ALLOC_IRAM_SPI; .Alloc = GDS_ALLOC_IRAM_SPI;
#endif #endif

View File

@@ -86,6 +86,7 @@ struct GDS_Device {
struct { struct {
spi_device_handle_t SPIHandle; spi_device_handle_t SPIHandle;
int8_t CSPin; int8_t CSPin;
int8_t CS_pre, CS_post, SPI_mode;
}; };
}; };

View File

@@ -51,6 +51,9 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
SPIDeviceConfig.spics_io_num = CSPin; SPIDeviceConfig.spics_io_num = CSPin;
SPIDeviceConfig.queue_size = 1; SPIDeviceConfig.queue_size = 1;
SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY; SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY;
SPIDeviceConfig.cs_ena_pretrans = Device->CS_pre;
SPIDeviceConfig.cs_ena_posttrans = Device->CS_post;
SPIDeviceConfig.mode = Device->SPI_mode;
ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false ); ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false );
@@ -74,16 +77,23 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
} }
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) { static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
spi_transaction_t SPITransaction = { 0 }; spi_transaction_t SPITransaction = { };
NullCheck( SPIHandle, return false ); NullCheck( SPIHandle, return false );
NullCheck( Data, return false ); NullCheck( Data, return false );
if ( DataLength > 0 ) { if ( DataLength > 0 ) {
gpio_set_level( DCPin, WriteMode ); gpio_set_level( DCPin, WriteMode );
SPITransaction.length = DataLength * 8; SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = Data;
if (DataLength <= 4) {
SPITransaction.flags = SPI_TRANS_USE_TXDATA;
SPITransaction.tx_data[0] = *Data++; SPITransaction.tx_data[1] = *Data++;
SPITransaction.tx_data[2] = *Data++; SPITransaction.tx_data[3] = *Data;
} else {
SPITransaction.tx_buffer = Data;
}
// only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false ); ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );

View File

@@ -99,23 +99,23 @@ static const struct gpio_exp_model_s {
void (*set_pull_mode)(gpio_exp_t* self); void (*set_pull_mode)(gpio_exp_t* self);
} registered[] = { } registered[] = {
{ .model = "pca9535", { .model = "pca9535",
.trigger = GPIO_INTR_NEGEDGE, .trigger = GPIO_INTR_LOW_LEVEL,
.set_direction = pca9535_set_direction, .set_direction = pca9535_set_direction,
.read = pca9535_read, .read = pca9535_read,
.write = pca9535_write, }, .write = pca9535_write, },
{ .model = "pca85xx", { .model = "pca85xx",
.trigger = GPIO_INTR_NEGEDGE, .trigger = GPIO_INTR_LOW_LEVEL,
.read = pca85xx_read, .read = pca85xx_read,
.write = pca85xx_write, }, .write = pca85xx_write, },
{ .model = "mcp23017", { .model = "mcp23017",
.trigger = GPIO_INTR_NEGEDGE, .trigger = GPIO_INTR_LOW_LEVEL,
.init = mcp23017_init, .init = mcp23017_init,
.set_direction = mcp23017_set_direction, .set_direction = mcp23017_set_direction,
.set_pull_mode = mcp23017_set_pull_mode, .set_pull_mode = mcp23017_set_pull_mode,
.read = mcp23017_read, .read = mcp23017_read,
.write = mcp23017_write, }, .write = mcp23017_write, },
{ .model = "mcp23s17", { .model = "mcp23s17",
.trigger = GPIO_INTR_NEGEDGE, .trigger = GPIO_INTR_LOW_LEVEL,
.init = mcp23s17_init, .init = mcp23s17_init,
.set_direction = mcp23s17_set_direction, .set_direction = mcp23s17_set_direction,
.set_pull_mode = mcp23s17_set_pull_mode, .set_pull_mode = mcp23s17_set_pull_mode,
@@ -406,6 +406,9 @@ static void IRAM_ATTR intr_isr_handler(void* arg) {
gpio_exp_t *self = (gpio_exp_t*) arg; gpio_exp_t *self = (gpio_exp_t*) arg;
BaseType_t woken = pdFALSE; BaseType_t woken = pdFALSE;
// edge interrupts do not work because of read/clear = potential short pulse
gpio_intr_disable(self->intr);
// activate all, including ourselves // activate all, including ourselves
for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true; for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true;
@@ -439,26 +442,22 @@ void service_handler(void *arg) {
for (int i = 0; i < n_expanders; i++) { for (int i = 0; i < n_expanders; i++) {
gpio_exp_t *expander = expanders + i; gpio_exp_t *expander = expanders + i;
// no interrupt for that gpio // no interrupt for that gpio or not pending (safe as interrupt is disabled)
if (expander->intr < 0) continue; if (expander->intr < 0 || !expander->intr_pending) continue;
// only check expander with pending interrupts
gpio_intr_disable(expander->intr);
if (!expander->intr_pending) {
gpio_intr_enable(expander->intr);
continue;
}
expander->intr_pending = false;
gpio_intr_enable(expander->intr);
xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)); xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50));
// read GPIOs and clear all pending status // read GPIOs and clear all pending status
uint32_t value = expander->model->read(expander); uint32_t value = expander->model->read(expander);
expander->age = xTaskGetTickCount();
// re-enable interrupt now that it has been cleared
expander->intr_pending = false;
gpio_intr_enable(expander->intr);
uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask); uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask);
expander->shadow = value; expander->shadow = value;
expander->pending = 0; expander->pending = 0;
expander->age = xTaskGetTickCount();
xSemaphoreGive(expander->mutex); xSemaphoreGive(expander->mutex);
ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending); ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending);
@@ -468,7 +467,7 @@ void service_handler(void *arg) {
gpio -= clz; gpio -= clz;
if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0 if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0
else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg); else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg);
} }
} }
} }