mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 03:27:01 +03:00
http_download needs a bigger stack for cspot which required to move it to EXTRAM
This commit is contained in:
@@ -948,7 +948,7 @@ CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
|||||||
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
||||||
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
||||||
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
||||||
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
|
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2
|
||||||
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
||||||
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
||||||
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
||||||
|
|||||||
@@ -907,7 +907,7 @@ CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
|||||||
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
||||||
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
||||||
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
||||||
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
|
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2
|
||||||
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
||||||
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
||||||
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
||||||
|
|||||||
@@ -918,7 +918,7 @@ CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
|||||||
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
||||||
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
|
||||||
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
|
||||||
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
|
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2
|
||||||
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set
|
||||||
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
||||||
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
CONFIG_FREERTOS_ISR_STACKSIZE=2096
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#define PSEUDO_IDLE_STACK_SIZE (8*1024)
|
#define PSEUDO_IDLE_STACK_SIZE (6*1024)
|
||||||
|
|
||||||
#define MONITOR_TIMER (10*1000)
|
#define MONITOR_TIMER (10*1000)
|
||||||
#define SCRATCH_SIZE 256
|
#define SCRATCH_SIZE 256
|
||||||
|
|||||||
@@ -136,10 +136,8 @@ static bool cmd_handler(cspot_event_t event, ...) {
|
|||||||
displayer_timer(DISPLAYER_ELAPSED, va_arg(args, int), -1);
|
displayer_timer(DISPLAYER_ELAPSED, va_arg(args, int), -1);
|
||||||
break;
|
break;
|
||||||
case CSPOT_TRACK_INFO: {
|
case CSPOT_TRACK_INFO: {
|
||||||
uint32_t duration = va_arg(args, int);
|
uint32_t duration = va_arg(args, int), offset = va_arg(args, int);
|
||||||
uint32_t offset = va_arg(args, int);
|
char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*), *artwork = va_arg(args, char*);
|
||||||
char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*);
|
|
||||||
char *artwork = va_arg(args, char*);
|
|
||||||
if (artwork && displayer_can_artwork()) {
|
if (artwork && displayer_can_artwork()) {
|
||||||
ESP_LOGI(TAG, "requesting artwork %s", artwork);
|
ESP_LOGI(TAG, "requesting artwork %s", artwork);
|
||||||
http_download(artwork, 128*1024, got_artwork, NULL);
|
http_download(artwork, 128*1024, got_artwork, NULL);
|
||||||
|
|||||||
@@ -742,6 +742,7 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst) {
|
|||||||
register u16_t aux;
|
register u16_t aux;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// we assume frame == 0 as well...
|
||||||
if (!src) {
|
if (!src) {
|
||||||
count = 192;
|
count = 192;
|
||||||
vu = VUCP24[0];
|
vu = VUCP24[0];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* (c) Philippe G. 20201, philippe_44@outlook.com
|
* (c) Philippe G. 20201, philippe_44@outlook.com
|
||||||
* see other copyrights below
|
* see other copyrights below
|
||||||
*
|
*
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
|
#if CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS < 2
|
||||||
|
#error CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS must be at least 2
|
||||||
|
#endif
|
||||||
|
|
||||||
const static char TAG[] = "tools";
|
const static char TAG[] = "tools";
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
@@ -104,11 +108,11 @@ static uint8_t UNICODEtoCP1252(uint16_t chr) {
|
|||||||
void utf8_decode(char *src) {
|
void utf8_decode(char *src) {
|
||||||
uint32_t codep = 0, state = UTF8_ACCEPT;
|
uint32_t codep = 0, state = UTF8_ACCEPT;
|
||||||
char *dst = src;
|
char *dst = src;
|
||||||
|
|
||||||
while (src && *src) {
|
while (src && *src) {
|
||||||
if (!decode(&state, &codep, *src++)) *dst++ = UNICODEtoCP1252(codep);
|
if (!decode(&state, &codep, *src++)) *dst++ = UNICODEtoCP1252(codep);
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,12 +182,61 @@ char * strdup_psram(const char * source){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* URL download
|
* Task manager
|
||||||
*/
|
*/
|
||||||
|
#define TASK_TLS_INDEX 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
StaticTask_t *xTaskBuffer;
|
||||||
|
StackType_t *xStack;
|
||||||
|
} task_context_t;
|
||||||
|
|
||||||
|
static void task_cleanup(int index, task_context_t *context) {
|
||||||
|
free(context->xTaskBuffer);
|
||||||
|
free(context->xStack);
|
||||||
|
free(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xTaskCreateEXTRAM( TaskFunction_t pvTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
configSTACK_DEPTH_TYPE usStackDepth,
|
||||||
|
void *pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t *pxCreatedTask) {
|
||||||
|
// create the worker task as a static
|
||||||
|
task_context_t *context = calloc(1, sizeof(task_context_t));
|
||||||
|
context->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||||
|
context->xStack = heap_caps_malloc(usStackDepth,(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT));
|
||||||
|
TaskHandle_t handle = xTaskCreateStatic(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, context->xStack, context->xTaskBuffer);
|
||||||
|
|
||||||
|
// store context in TCB or free everything in case of failure
|
||||||
|
if (!handle) {
|
||||||
|
free(context->xTaskBuffer);
|
||||||
|
free(context->xStack);
|
||||||
|
free(context);
|
||||||
|
} else {
|
||||||
|
vTaskSetThreadLocalStoragePointerAndDelCallback( handle, TASK_TLS_INDEX, context, (TlsDeleteCallbackFunction_t) task_cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pxCreatedTask) *pxCreatedTask = handle;
|
||||||
|
return handle != NULL ? pdPASS : pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vTaskDeleteEXTRAM(TaskHandle_t xTask) {
|
||||||
|
/* At this point we leverage FreeRTOS extension to have callbacks on task deletion.
|
||||||
|
* If not, we need to have here our own deletion implementation that include delayed
|
||||||
|
* free for when this is called with NULL (self-deletion)
|
||||||
|
*/
|
||||||
|
vTaskDelete(xTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* URL download
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *user_context;
|
void *user_context;
|
||||||
http_download_cb_t callback;
|
http_download_cb_t callback;
|
||||||
size_t max, bytes;
|
size_t max, bytes;
|
||||||
bool abort;
|
bool abort;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
@@ -192,22 +245,22 @@ typedef struct {
|
|||||||
|
|
||||||
static void http_downloader(void *arg);
|
static void http_downloader(void *arg);
|
||||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt);
|
static esp_err_t http_event_handler(esp_http_client_event_t *evt);
|
||||||
|
|
||||||
void http_download(char *url, size_t max, http_download_cb_t callback, void *context) {
|
void http_download(char *url, size_t max, http_download_cb_t callback, void *context) {
|
||||||
http_context_t *http_context = (http_context_t*) heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM);
|
http_context_t *http_context = (http_context_t*) heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM);
|
||||||
|
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
.url = url,
|
.url = url,
|
||||||
.event_handler = http_event_handler,
|
.event_handler = http_event_handler,
|
||||||
.user_data = http_context,
|
.user_data = http_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
http_context->callback = callback;
|
http_context->callback = callback;
|
||||||
http_context->user_context = context;
|
http_context->user_context = context;
|
||||||
http_context->max = max;
|
http_context->max = max;
|
||||||
http_context->client = esp_http_client_init(&config);
|
http_context->client = esp_http_client_init(&config);
|
||||||
|
|
||||||
xTaskCreate(http_downloader, "downloader", 4*1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL);
|
xTaskCreateEXTRAM(http_downloader, "downloader", 8*1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_downloader(void *arg) {
|
static void http_downloader(void *arg) {
|
||||||
@@ -215,14 +268,14 @@ static void http_downloader(void *arg) {
|
|||||||
|
|
||||||
esp_http_client_perform(http_context->client);
|
esp_http_client_perform(http_context->client);
|
||||||
esp_http_client_cleanup(http_context->client);
|
esp_http_client_cleanup(http_context->client);
|
||||||
|
|
||||||
free(http_context);
|
free(http_context);
|
||||||
vTaskDelete(NULL);
|
vTaskDeleteEXTRAM(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
|
static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
|
||||||
http_context_t *http_context = (http_context_t*) evt->user_data;
|
http_context_t *http_context = (http_context_t*) evt->user_data;
|
||||||
|
|
||||||
if (http_context->abort) return ESP_FAIL;
|
if (http_context->abort) return ESP_FAIL;
|
||||||
|
|
||||||
switch(evt->event_id) {
|
switch(evt->event_id) {
|
||||||
@@ -234,42 +287,42 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
|
|||||||
if (!strcasecmp(evt->header_key, "Content-Length")) {
|
if (!strcasecmp(evt->header_key, "Content-Length")) {
|
||||||
size_t len = atoi(evt->header_value);
|
size_t len = atoi(evt->header_value);
|
||||||
if (!len || len > http_context->max) {
|
if (!len || len > http_context->max) {
|
||||||
ESP_LOGI(TAG, "content-length null or too large %zu / %zu", len, http_context->max);
|
ESP_LOGI(TAG, "content-length null or too large %zu / %zu", len, http_context->max);
|
||||||
http_context->abort = true;
|
http_context->abort = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_ON_DATA: {
|
case HTTP_EVENT_ON_DATA: {
|
||||||
size_t len = esp_http_client_get_content_length(evt->client);
|
size_t len = esp_http_client_get_content_length(evt->client);
|
||||||
if (!http_context->data) {
|
if (!http_context->data) {
|
||||||
if ((http_context->data = (uint8_t*) malloc(len)) == NULL) {
|
if ((http_context->data = (uint8_t*) malloc(len)) == NULL) {
|
||||||
http_context->abort = true;
|
http_context->abort = true;
|
||||||
ESP_LOGE(TAG, "gailed to allocate memory for output buffer %zu", len);
|
ESP_LOGE(TAG, "failed to allocate memory for output buffer %zu", len);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(http_context->data + http_context->bytes, evt->data, evt->data_len);
|
memcpy(http_context->data + http_context->bytes, evt->data, evt->data_len);
|
||||||
http_context->bytes += evt->data_len;
|
http_context->bytes += evt->data_len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HTTP_EVENT_ON_FINISH:
|
case HTTP_EVENT_ON_FINISH:
|
||||||
http_context->callback(http_context->data, http_context->bytes, http_context->user_context);
|
http_context->callback(http_context->data, http_context->bytes, http_context->user_context);
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_DISCONNECTED: {
|
case HTTP_EVENT_DISCONNECTED: {
|
||||||
int mbedtls_err = 0;
|
int mbedtls_err = 0;
|
||||||
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "HTTP download disconnect %d", err);
|
ESP_LOGE(TAG, "HTTP download disconnect %d", err);
|
||||||
if (http_context->data) free(http_context->data);
|
if (http_context->data) free(http_context->data);
|
||||||
http_context->callback(NULL, 0, http_context->user_context);
|
http_context->callback(NULL, 0, http_context->user_context);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,18 @@ const char* str_or_null(const char * str);
|
|||||||
typedef void (*http_download_cb_t)(uint8_t* data, size_t len, void *context);
|
typedef void (*http_download_cb_t)(uint8_t* data, size_t len, void *context);
|
||||||
void http_download(char *url, size_t max, http_download_cb_t callback, void *context);
|
void http_download(char *url, size_t max, http_download_cb_t callback, void *context);
|
||||||
|
|
||||||
|
/* Use these to dynamically create tasks whose stack is on EXTRAM. Be aware that it
|
||||||
|
* requires configNUM_THREAD_LOCAL_STORAGE_POINTERS to bet set to 2 at least (index 0
|
||||||
|
* is used by pthread and this uses index 1, obviously
|
||||||
|
*/
|
||||||
|
BaseType_t xTaskCreateEXTRAM( TaskFunction_t pvTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
configSTACK_DEPTH_TYPE usStackDepth,
|
||||||
|
void *pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t *pxCreatedTask);
|
||||||
|
void vTaskDeleteEXTRAM(TaskHandle_t xTask);
|
||||||
|
|
||||||
extern const char unknown_string_placeholder[];
|
extern const char unknown_string_placeholder[];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Reference in New Issue
Block a user