Uart interrupt problems when writing SPIFFS

MikeMyhre
Posts: 54
Joined: Sat Nov 05, 2022 3:32 am

Uart interrupt problems when writing SPIFFS

Postby MikeMyhre » Sun Aug 20, 2023 5:11 pm

I have tried putting the UART interrupt function in IRAM (with DRAM variables and ESP_INTR_FLAG_IRAM) and removing the flag so this interrupt is paused (I don't care if it is paused while writing. It isn't critical). Neither one works.
When I don't use the IRAM flag so it is paused, I get this panic message and reboot. Other than the CORRUPTED flag, I don't think it is a IRAM/Flash Cache issue):

Code: Select all

assert failed: xQueueSemaphoreTake queue.c:1554 (!( ( xTaskGetSchedulerState() == ( ( BaseType_t ) 0 ) ) && ( xTicksToWait != 0 ) ))


Backtrace: 0x40375d72:0x3fc99050 0x4037e0c9:0x3fc99070 0x40385c4d:0x3fc99090 0x4037f041:0x3fc991b0 0x42024774:0x3fc991f0 0x40377787:0x3fc99220 0x40376f49:0x3fc99240 0x400559dd:0x3fccaf30 |<-CORRUPTED
0x40375d72: panic_abort at C:/Espressif/frameworks/esp-idf-v4.4.3/components/esp_system/panic.c:402

0x4037e0c9: esp_system_abort at C:/Espressif/frameworks/esp-idf-v4.4.3/components/esp_system/esp_system.c:128

0x40385c4d: __assert_func at C:/Espressif/frameworks/esp-idf-v4.4.3/components/newlib/assert.c:85

0x4037f041: xQueueSemaphoreTake at C:/Espressif/frameworks/esp-idf-v4.4.3/components/freertos/queue.c:1554 (discriminator 2)

0x42024774: uart_tx_chars at C:/Espressif/frameworks/esp-idf-v4.4.3/components/driver/uart.c:1182

0x40377787: dmp_prg_isr at C:/Projects/ESP32/DC-102-PoE_R1/main/dmp.c:78

0x40376f49: _xt_medint2 at C:/Espressif/frameworks/esp-idf-v4.4.3/components/freertos/port/xtensa/xtensa_vectors.S:1200





ELF file SHA256: 2492b49c582102dd

Rebooting...
�ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x2b (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375a10
0x40375a10: esp_restart_noos at C:/Espressif/frameworks/esp-idf-v4.4.3/components/esp_system/port/soc/esp32s3/system_internal.c:151 (discriminator 1)
My Interrupt handler:

Code: Select all

DRAM_ATTR uint8_t prgDisplay[2][32] =  { "                ", "                "};
DRAM_ATTR uint8_t prgDispTxLine = 0;
DRAM_ATTR uint8_t prgDispTxIdx = 0;
DRAM_ATTR uint8_t prgTxPkt[10];

DRAM_ATTR uint8_t prgRxKeyBuf[100];
DRAM_ATTR uint8_t prgRxKeyIdx = 0;
DRAM_ATTR uint8_t lastPrgPktByte = 0x40;
DRAM_ATTR uint8_t prgPktBuf[RX_BUF_SIZE+1];

DRAM_ATTR uint8_t prgRxIdx = 0;

DRAM_ATTR uint8_t prgKpdNum = 1;

static void IRAM_ATTR dmp_prg_isr( void *arg )
{
	if( UART_PRG.int_st.txfifo_empty_int_st ) {
		if( prgDispTxIdx >= 16 ) {
			prgDispTxLine++;
			prgDispTxIdx = 0;
		}
		if( prgDispTxLine > 1 )
			prgDispTxLine = 0;

		prgTxPkt[0] = 0x80 + prgKpdNum + (prgDispTxLine * 0x20);
		prgTxPkt[1] = 0x40 + prgDispTxIdx;

		prgTxPkt[2] = prgDisplay[prgDispTxLine][prgDispTxIdx++];
		prgTxPkt[3] = prgDisplay[prgDispTxLine][prgDispTxIdx++];
		prgTxPkt[4] = prgDisplay[prgDispTxLine][prgDispTxIdx++];
		prgTxPkt[5] = prgDisplay[prgDispTxLine][prgDispTxIdx++];
		prgTxPkt[6] = 0;	// audibles

		if( lastPrgPktByte != prgPktBuf[0] ) {
			lastPrgPktByte = prgPktBuf[0];	// look for change
			if( lastPrgPktByte != 0x40 ) { //|| prgPktBuf[1] != 0 ) {
				// have non idle, new key press
				prgRxKeyBuf[prgRxKeyIdx++] = lastPrgPktByte;
			}
		}
//		uart_tx_chars(UART_PRG_NUM,(const char *)prgTxPkt,7);
		uart_tx_chars(UART_PRG_NUM,(const char *)prgTxPkt,7);
		uart_clear_intr_status(UART_PRG_NUM, UART_TXFIFO_EMPTY_INT_CLR);
		return;
	}
	if( UART_PRG.int_st.tx_done_int_st ) {
		uart_clear_intr_status(UART_PRG_NUM, UART_TXFIFO_EMPTY_INT_CLR);
		return;
	}
	if( UART_PRG.int_st.parity_err_int_st ) {
		uart_clear_intr_status(UART_PRG_NUM, UART_PARITY_ERR_INT_CLR);
		return;
	}
	if( UART_PRG.int_st.frm_err_int_st ) {
		uart_clear_intr_status(UART_PRG_NUM, UART_FRM_ERR_INT_CLR);
		return;
	}
	if( UART_PRG.int_st.rxfifo_ovf_int_st ) {
		uart_clear_intr_status(UART_PRG_NUM, UART_RXFIFO_OVF_INT_CLR);
		return;
	}
	if( UART_PRG.int_st.brk_det_int_st ) {
		uart_clear_intr_status(UART_PRG_NUM, UART_BRK_DET_INT_CLR);
		return;
	}

	if( UART_PRG.status.rxfifo_cnt ) {
		kpd_reply_cnt++;
		while(UART_PRG.status.rxfifo_cnt) {
			char cc = UART_PRG.fifo.rxfifo_rd_byte;
			if( cc == 0 )
				prgRxIdx = 1;
			else
				prgRxIdx = 0;
			prgPktBuf[prgRxIdx] = cc;
		}
		uart_clear_intr_status(UART_PRG_NUM, UART_RXFIFO_FULL_INT_CLR);
	}
}
My INIT code:

Code: Select all

	const uart_config_t uart_config = {
			.baud_rate = 4800,
			.data_bits = UART_DATA_8_BITS,
			.parity = UART_PARITY_EVEN,
			.stop_bits = UART_STOP_BITS_1,
			.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
			.source_clk = UART_SCLK_APB,
	};

	uart_isr_handle_t isr_handle;
	ESP_ERROR_CHECK(uart_driver_install(UART_PRG_NUM, RX_BUF_SIZE * 2, 0, 0, NULL, 0));
	ESP_ERROR_CHECK(uart_param_config(UART_PRG_NUM, &uart_config ));
	ESP_ERROR_CHECK(uart_set_pin(UART_PRG_NUM, PROG_KPD_TXD_PIN, PROG_KPD_RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
	ESP_ERROR_CHECK(uart_set_line_inverse(UART_PRG_NUM,UART_SIGNAL_TXD_INV));

	ESP_ERROR_CHECK(uart_isr_free(UART_PRG_NUM));
	ESP_ERROR_CHECK(uart_isr_register(UART_PRG_NUM,dmp_prg_isr,(void *)NULL,NULL,&isr_handle));
	//ESP_ERROR_CHECK(uart_isr_register(UART_PRG_NUM,dmp_prg_isr,NULL,ESP_INTR_FLAG_IRAM,&isr_handle));
	// add tx interrupt
	uart_intr_config_t uintr_cfg = {
			.rxfifo_full_thresh = 1,
			.intr_enable_mask = (UART_RXFIFO_FULL_INT_ENA_M)
	};

	uintr_cfg.txfifo_empty_intr_thresh = 1;
	uintr_cfg.intr_enable_mask = (UART_RXFIFO_FULL_INT_ENA_M | UART_TXFIFO_EMPTY_INT_ENA_M);
	ESP_ERROR_CHECK(uart_intr_config(UART_PRG_NUM,&uintr_cfg));
None of my other interrupts (Ethernet, timer) have this problem.
Can someone help me figure this out. It is my last serious bug before I can release a beta version. I have been trying to figure this out for a couple months now.
ESP-IDF version 4.4.3 and ESP32-S3

MicroController
Posts: 1708
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Uart interrupt problems when writing SPIFFS

Postby MicroController » Sun Aug 20, 2023 10:26 pm

The problem is calling uart_tx_chars(...) in an ISR. uart_tx_chars(...) tries to acquire a semaphore, which is generally not allowed from within an ISR context; and even more so while the task scheduler is disabled during flash writes.

Skipping synchronization, you can try uart_hal_write_txfifo(...) instead.

MikeMyhre
Posts: 54
Joined: Sat Nov 05, 2022 3:32 am

Re: Uart interrupt problems when writing SPIFFS

Postby MikeMyhre » Mon Aug 21, 2023 1:23 pm

MicroController wrote:
Sun Aug 20, 2023 10:26 pm
The problem is calling uart_tx_chars(...) in an ISR. uart_tx_chars(...) tries to acquire a semaphore, which is generally not allowed from within an ISR context; and even more so while the task scheduler is disabled during flash writes.

Skipping synchronization, you can try uart_hal_write_txfifo(...) instead.
Thank you so much for the help! You really made my day/week/month!
I ended up using this function instead and it worked:
uart_ll_write_txfifo(&UART_PRG, prgTxPkt,7);
Not HAL, but direct to the FIFO.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 63 guests