Page 1 of 1

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

Posted: Mon Aug 12, 2019 7:45 pm
by bzgec_
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:
  1. static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
  2. {
  3.     spi_transaction_t *trans_desc = trans_buf->trans;
  4.     if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] &&
  5.         trans_buf->buffer_to_send != trans_desc->tx_buffer) {
  6.         free((void *)trans_buf->buffer_to_send); //force free, ignore const  
  7.     }
  8.     //copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
  9.     if ((void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] &&
  10.         trans_buf->buffer_to_rcv != trans_desc->rx_buffer) {
  11.         if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
  12.             memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
  13.         } else {
  14.             memcpy(trans_desc->rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
  15.         }
  16.         free(trans_buf->buffer_to_rcv);
  17.     }
  18. }

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:
  1. // Here is main code
  2. ...
  3. // THIS ONE DOES WORK
  4. while(1) {
  5.   spi_transaction_t SPITransaction;
  6.     memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
  7.     SPITransaction.length = DISPLAY_BUFFER_SIZE * 8;
  8.     SPITransaction.tx_buffer = (const void *)&dev._dispBuff;
  9.  
  10.   bTransmissionDone = ST7789_spi_check_poll_transmit(dev._SPIHandle, &espErr);
  11.   if(espErr == ESP_OK && bTransmissionDone == TRUE) {
  12.     if(bFirstTime == TRUE) {
  13.         espErr = spi_device_polling_start(dev._SPIHandle, &SPITransaction, portMAX_DELAY);
  14.         bFirstTime = FALSE;
  15.       } else {
  16.             espErr = spi_device_polling_end(dev._SPIHandle, portMAX_DELAY);
  17.           if(espErr == ESP_OK) {
  18.             espErr = spi_device_polling_start(dev._SPIHandle, &SPITransaction, portMAX_DELAY);
  19.           }
  20.       }
  21.   }
  22. }
  23.  
  24. // BUT THIS ONE DOES NOT
  25. while(1) {
  26.   bTransmissionDone = ST7789_spi_check_poll_transmit(dev._SPIHandle, &espErr);
  27.   if(espErr == ESP_OK && bTransmissionDone == TRUE) {
  28.     if(bFirstTime == TRUE) {
  29.         ST7789_sendBuffer_pollStart(&dev, &espErr);
  30.         bFirstTime = FALSE;
  31.       } else {
  32.             ST7789_sendBuffer_pollEnd(&dev, &espErr);
  33.           if(espErr == ESP_OK) {
  34.             ST7789_sendBuffer_pollStart(&dev, &espErr);
  35.           }
  36.       }
  37.   }
  38. }
  39. ...
Here are some used functions:
  1. // send display's buffer
  2. void ST7789_sendBuffer_pollStart(TFT_t *dev, esp_err_t *outErr) {
  3.     esp_err_t errLocal;
  4.     if(dev != NULL && outErr != NULL) {
  5.         ST7789_spi_send_command(dev, ST7789_COMMAND_CASET, &errLocal);  // set column(x) address
  6.         if(errLocal == ESP_OK) {
  7.             ST7789_spi_write_addr(dev, dev->_offsetx, dev->_offsetx + dev->_width - 1, &errLocal);
  8.         }
  9.         if(errLocal == ESP_OK) {
  10.             ST7789_spi_send_command(dev, ST7789_COMMAND_RASET, &errLocal);  // set Page(y) address
  11.         }
  12.         if(errLocal == ESP_OK) {
  13.             ST7789_spi_write_addr(dev, dev->_offsety, dev->_offsety + dev->_height - 1, &errLocal);
  14.         }
  15.         if(errLocal == ESP_OK) {
  16.             ST7789_spi_send_command(dev, ST7789_COMMAND_RAMWR, &errLocal);  //  Memory Write
  17.         }
  18.         if(errLocal == ESP_OK) {
  19.             gpio_set_level(dev->_pin_DC, ST7789_SPI_Data_Mode);
  20.             ST7789_spi_send_bytes_poll_st(dev->_SPIHandle, dev->_dispBuff, (size_t)(DISPLAY_BUFFER_SIZE), &errLocal);
  21.         }
  22.     }   else {
  23.         errLocal = ESP_ERR_INVALID_ARG;  // null pointer
  24.     }
  25.  
  26.     if(outErr != NULL) {
  27.         *outErr = errLocal;
  28.     }
  29.  
  30.     return;
  31. }
  32.  
  33. void ST7789_sendBuffer_pollEnd(TFT_t *dev, esp_err_t *outErr) {
  34.     esp_err_t errLocal;
  35.     if(dev != NULL && outErr != NULL) {
  36.             ST7789_spi_send_bytes_poll_end(dev->_SPIHandle, &errLocal);
  37.     }   else {
  38.         errLocal = ESP_ERR_INVALID_ARG;  // null pointer
  39.     }
  40.  
  41.     if(outErr != NULL) {
  42.         *outErr = errLocal;
  43.     }
  44.  
  45.     return;
  46. }
  47.  
  48. void ST7789_spi_send_bytes_poll_st(spi_device_handle_t SPIHandle, uint8_t *Data, size_t DataLength, esp_err_t *outErr) {
  49.     spi_transaction_t SPITransaction;
  50.     esp_err_t errLocal = ESP_OK;
  51.  
  52.     if(SPIHandle != NULL && outErr != NULL) {
  53.         if(DataLength > 0) {
  54.             memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
  55.             SPITransaction.length = DataLength * 8;
  56.             SPITransaction.tx_buffer = (const void *)Data;
  57.             spi_device_acquire_bus(SPIHandle, portMAX_DELAY);
  58.             errLocal = spi_device_polling_start(SPIHandle, &SPITransaction, portMAX_DELAY);
  59.         }
  60.     }   else {
  61.         errLocal = ESP_ERR_INVALID_ARG;  // null pointer
  62.     }
  63.  
  64.     if(outErr != NULL) {
  65.         *outErr = errLocal;
  66.     }
  67.  
  68.     return;
  69. }
  70.  
  71. void ST7789_spi_send_bytes_poll_end(spi_device_handle_t SPIHandle, esp_err_t *outErr) {
  72.     esp_err_t errLocal = ESP_OK;
  73.  
  74.     if(SPIHandle != NULL && outErr != NULL) {
  75.         errLocal = spi_device_polling_end(SPIHandle, portMAX_DELAY);
  76.         spi_device_release_bus(SPIHandle);
  77.     }   else {
  78.         errLocal = ESP_ERR_INVALID_ARG;  // null pointer
  79.     }
  80.  
  81.     if(outErr != NULL) {
  82.         *outErr = errLocal;
  83.     }
  84.  
  85.     return;
  86. }

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

Posted: Thu Aug 15, 2019 2:22 am
by ESP_Sprite
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.

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

Posted: Sat Aug 17, 2019 12:25 pm
by bzgec_
Thank you!

Making variable:
  1. spi_transaction_t SPITransaction;
static solved my problem.


So i changed this function
  1. void ST7789_spi_send_bytes_poll_st(spi_device_handle_t SPIHandle, uint8_t *Data, size_t DataLength, esp_err_t *outErr) {
  2.     static spi_transaction_t SPITransaction;
  3.     esp_err_t errLocal = ESP_OK;
  4.  
  5.     if(SPIHandle != NULL && outErr != NULL) {
  6.         if(DataLength > 0) {
  7.             memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
  8.             SPITransaction.length = DataLength * 8;
  9.             SPITransaction.tx_buffer = (const void *)Data;
  10.             spi_device_acquire_bus(SPIHandle, portMAX_DELAY);
  11.             errLocal = spi_device_polling_start(SPIHandle, &SPITransaction, portMAX_DELAY);
  12.         }
  13.     }   else {
  14.         errLocal = ESP_ERR_INVALID_ARG;  // null pointer
  15.     }
  16.  
  17.     if(outErr != NULL) {
  18.         *outErr = errLocal;
  19.     }
  20.  
  21.     return;
  22. }