SPI, prblem with 'spi_device_polling_end' ("free() target pointer is outside heap areas")

bzgec_
Posts: 2
Joined: Sat Mar 02, 2019 1:39 pm

SPI, prblem with 'spi_device_polling_end' ("free() target pointer is outside heap areas")

Postby bzgec_ » Mon Aug 12, 2019 7:45 pm

Hello,

i have a problem, that when i call spi_device_polling_start, and than later spi_device_polling_end i get this assertion (it happens when i call spi_device_polling_end):

assertion "heap != NULL && "free() target pointer is outside heap areas"" failed: file "/home/bzgec/esp/esp-idf/components/heap/heap_caps.c", line 267, function: heap_caps_free
abort() was called at PC 0x400d2cdf on core 0
0x400d2cdf: __assert_func at /builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/newlib/newlib/libc/stdlib/assert.c:62 (discriminator 8)

So i debugged that problem is in this function:

Code: spi_master.c Select all

static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
{
spi_transaction_t *trans_desc = trans_buf->trans;
if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] &&
trans_buf->buffer_to_send != trans_desc->tx_buffer) {
free((void *)trans_buf->buffer_to_send); //force free, ignore const
}
//copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
if ((void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] &&
trans_buf->buffer_to_rcv != trans_desc->rx_buffer) {
if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
} else {
memcpy(trans_desc->rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
}
free(trans_buf->buffer_to_rcv);
}
}

Funny thing is that i don't have problem when calling spi_device_polling_transmit.
Does any one have an idea what am i doing wrong?

Here is some code:

Code: Untitled.c Select all


// Here is main code
...
// THIS ONE DOES WORK
while(1) {
spi_transaction_t SPITransaction;
memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
SPITransaction.length = DISPLAY_BUFFER_SIZE * 8;
SPITransaction.tx_buffer = (const void *)&dev._dispBuff;

bTransmissionDone = ST7789_spi_check_poll_transmit(dev._SPIHandle, &espErr);
if(espErr == ESP_OK && bTransmissionDone == TRUE) {
if(bFirstTime == TRUE) {
espErr = spi_device_polling_start(dev._SPIHandle, &SPITransaction, portMAX_DELAY);
bFirstTime = FALSE;
} else {
espErr = spi_device_polling_end(dev._SPIHandle, portMAX_DELAY);
if(espErr == ESP_OK) {
espErr = spi_device_polling_start(dev._SPIHandle, &SPITransaction, portMAX_DELAY);
}
}
}
}

// BUT THIS ONE DOES NOT
while(1) {
bTransmissionDone = ST7789_spi_check_poll_transmit(dev._SPIHandle, &espErr);
if(espErr == ESP_OK && bTransmissionDone == TRUE) {
if(bFirstTime == TRUE) {
ST7789_sendBuffer_pollStart(&dev, &espErr);
bFirstTime = FALSE;
} else {
ST7789_sendBuffer_pollEnd(&dev, &espErr);
if(espErr == ESP_OK) {
ST7789_sendBuffer_pollStart(&dev, &espErr);
}
}
}
}
...
Here are some used functions:

Code: Untitled.c Select all


// send display's buffer
void ST7789_sendBuffer_pollStart(TFT_t *dev, esp_err_t *outErr) {
esp_err_t errLocal;
if(dev != NULL && outErr != NULL) {
ST7789_spi_send_command(dev, ST7789_COMMAND_CASET, &errLocal); // set column(x) address
if(errLocal == ESP_OK) {
ST7789_spi_write_addr(dev, dev->_offsetx, dev->_offsetx + dev->_width - 1, &errLocal);
}
if(errLocal == ESP_OK) {
ST7789_spi_send_command(dev, ST7789_COMMAND_RASET, &errLocal); // set Page(y) address
}
if(errLocal == ESP_OK) {
ST7789_spi_write_addr(dev, dev->_offsety, dev->_offsety + dev->_height - 1, &errLocal);
}
if(errLocal == ESP_OK) {
ST7789_spi_send_command(dev, ST7789_COMMAND_RAMWR, &errLocal); // Memory Write
}
if(errLocal == ESP_OK) {
gpio_set_level(dev->_pin_DC, ST7789_SPI_Data_Mode);
ST7789_spi_send_bytes_poll_st(dev->_SPIHandle, dev->_dispBuff, (size_t)(DISPLAY_BUFFER_SIZE), &errLocal);
}
} else {
errLocal = ESP_ERR_INVALID_ARG; // null pointer
}

if(outErr != NULL) {
*outErr = errLocal;
}

return;
}

void ST7789_sendBuffer_pollEnd(TFT_t *dev, esp_err_t *outErr) {
esp_err_t errLocal;
if(dev != NULL && outErr != NULL) {
ST7789_spi_send_bytes_poll_end(dev->_SPIHandle, &errLocal);
} else {
errLocal = ESP_ERR_INVALID_ARG; // null pointer
}

if(outErr != NULL) {
*outErr = errLocal;
}

return;
}

void ST7789_spi_send_bytes_poll_st(spi_device_handle_t SPIHandle, uint8_t *Data, size_t DataLength, esp_err_t *outErr) {
spi_transaction_t SPITransaction;
esp_err_t errLocal = ESP_OK;

if(SPIHandle != NULL && outErr != NULL) {
if(DataLength > 0) {
memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = (const void *)Data;
spi_device_acquire_bus(SPIHandle, portMAX_DELAY);
errLocal = spi_device_polling_start(SPIHandle, &SPITransaction, portMAX_DELAY);
}
} else {
errLocal = ESP_ERR_INVALID_ARG; // null pointer
}

if(outErr != NULL) {
*outErr = errLocal;
}

return;
}

void ST7789_spi_send_bytes_poll_end(spi_device_handle_t SPIHandle, esp_err_t *outErr) {
esp_err_t errLocal = ESP_OK;

if(SPIHandle != NULL && outErr != NULL) {
errLocal = spi_device_polling_end(SPIHandle, portMAX_DELAY);
spi_device_release_bus(SPIHandle);
} else {
errLocal = ESP_ERR_INVALID_ARG; // null pointer
}

if(outErr != NULL) {
*outErr = errLocal;
}

return;
}

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI, prblem with 'spi_device_polling_end' ("free() target pointer is outside heap areas")

Postby Sprite » Thu Aug 15, 2019 2:22 am

Your transaction is a stack variable that disappears when you exit the function. The SPI driver needs the transaction memory to be available during the entire time the transaction is in progress.

bzgec_
Posts: 2
Joined: Sat Mar 02, 2019 1:39 pm

Re: SPI, prblem with 'spi_device_polling_end' ("free() target pointer is outside heap areas")

Postby bzgec_ » Sat Aug 17, 2019 12:25 pm

Thank you!

Making variable:

Code: Untitled.c Select all

spi_transaction_t SPITransaction;
static solved my problem.


So i changed this function

Code: Untitled.c Select all

void ST7789_spi_send_bytes_poll_st(spi_device_handle_t SPIHandle, uint8_t *Data, size_t DataLength, esp_err_t *outErr) {
static spi_transaction_t SPITransaction;
esp_err_t errLocal = ESP_OK;

if(SPIHandle != NULL && outErr != NULL) {
if(DataLength > 0) {
memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = (const void *)Data;
spi_device_acquire_bus(SPIHandle, portMAX_DELAY);
errLocal = spi_device_polling_start(SPIHandle, &SPITransaction, portMAX_DELAY);
}
} else {
errLocal = ESP_ERR_INVALID_ARG; // null pointer
}

if(outErr != NULL) {
*outErr = errLocal;
}

return;
}

Who is online

Users browsing this forum: meta-externalagent, Semrush [Bot] and 2 guests