Selaa lähdekoodia

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

Philippe G 3 vuotta sitten
vanhempi
commit
e8f8239ee3

+ 1 - 0
components/display/SH1106.c

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

+ 1 - 0
components/display/core/gds_private.h

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

+ 13 - 3
components/display/core/ifaces/default_if_spi.c

@@ -51,6 +51,9 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
     SPIDeviceConfig.spics_io_num = CSPin;
     SPIDeviceConfig.queue_size = 1;
 	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 );
 	
@@ -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 ) {
-    spi_transaction_t SPITransaction = { 0 };
+    spi_transaction_t SPITransaction = { };
 
     NullCheck( SPIHandle, return false );
     NullCheck( Data, return false );
 
     if ( DataLength > 0 ) {
 		gpio_set_level( DCPin, WriteMode );
-		
+
 		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)		
 		ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );

+ 16 - 17
components/services/gpio_exp.c

@@ -99,23 +99,23 @@ static const struct gpio_exp_model_s {
 	void      (*set_pull_mode)(gpio_exp_t* self);
 } registered[] = {
 	{ .model = "pca9535",
-	  .trigger = GPIO_INTR_NEGEDGE, 
+	  .trigger = GPIO_INTR_LOW_LEVEL,
 	  .set_direction = pca9535_set_direction,
 	  .read = pca9535_read,
 	  .write = pca9535_write, },
 	{ .model = "pca85xx",
-	  .trigger = GPIO_INTR_NEGEDGE, 
+	  .trigger = GPIO_INTR_LOW_LEVEL,
 	  .read = pca85xx_read,
 	  .write = pca85xx_write, },
 	{ .model = "mcp23017",
-	  .trigger = GPIO_INTR_NEGEDGE, 
+	  .trigger = GPIO_INTR_LOW_LEVEL,
 	  .init = mcp23017_init,
 	  .set_direction = mcp23017_set_direction,
 	  .set_pull_mode = mcp23017_set_pull_mode,
 	  .read = mcp23017_read,
 	  .write = mcp23017_write, },
 	{ .model = "mcp23s17",
-	  .trigger = GPIO_INTR_NEGEDGE, 
+	  .trigger = GPIO_INTR_LOW_LEVEL,
 	  .init = mcp23s17_init,
 	  .set_direction = mcp23s17_set_direction,
 	  .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;
 	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
 	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++) {
 				gpio_exp_t *expander = expanders + i;
 
-				// no interrupt for that gpio
-				if (expander->intr < 0) continue;
+				// no interrupt for that gpio or not pending (safe as interrupt is disabled)
+				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));
 
 				// read GPIOs and clear all pending status
 				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);
 				expander->shadow = value;
 				expander->pending = 0;
-				expander->age = xTaskGetTickCount();
 
 				xSemaphoreGive(expander->mutex);
 				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;
 					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);
-				}
+				}	
 			}
 		}