Example #1
0
static bool idle_hook(void) {
#if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1
    if (xPortGetCoreID()!=0) return true;
#endif
    esp_task_wdt_feed();
    return true;
}
Example #2
0
static void IRAM_ATTR ipc_task(void* arg)
{
    const uint32_t cpuid = (uint32_t) arg;
    assert(cpuid == xPortGetCoreID());
    while (true) {
        // Wait for IPC to be initiated.
        // This will be indicated by giving the semaphore corresponding to
        // this CPU.
        if (xSemaphoreTake(s_ipc_sem[cpuid], portMAX_DELAY) != pdTRUE) {
            // TODO: when can this happen?
            abort();
        }

        esp_ipc_func_t func = s_func;
        void* arg = s_func_arg;

        if (s_ipc_wait == IPC_WAIT_FOR_START) {
            xSemaphoreGive(s_ipc_ack);
        }
        (*func)(arg);
        if (s_ipc_wait == IPC_WAIT_FOR_END) {
            xSemaphoreGive(s_ipc_ack);
        }
    }
    // TODO: currently this is unreachable code. Introduce esp_ipc_uninit
    // function which will signal to both tasks that they can shut down.
    // Not critical at this point, we don't have a use case for stopping
    // IPC yet.
    // Also need to delete the semaphore here.
    vTaskDelete(NULL);
}
Example #3
0
/*
  This function registers a handler for the specified interrupt. The "arg"
  parameter specifies the argument to be passed to the handler when it is
  invoked. The function returns the address of the previous handler.
  On error, it returns 0.
*/
xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg)
{
    xt_handler_table_entry * entry;
    xt_handler               old;

    if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
        return 0;       /* invalid interrupt number */
    if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
        return 0;       /* priority level too high to safely handle in C */

    /* Convert exception number to _xt_exception_table name */
    n = n * portNUM_PROCESSORS + xPortGetCoreID();

    entry = _xt_interrupt_table + n;
    old   = entry->handler;

    if (f) {
        entry->handler = f;
        entry->arg     = arg;
    }
    else {
        entry->handler = &xt_unhandled_interrupt;
        entry->arg     = (void*)n;
    }

    return ((old == &xt_unhandled_interrupt) ? 0 : old);
}
Example #4
0
/* stall other cpu that this cpu is pending to access dport register end */
void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
{
#ifndef CONFIG_FREERTOS_UNICORE
    int cpu_id = xPortGetCoreID();
    
    if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
            || dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
        return;
    }

    if (dport_access_ref[cpu_id] == 0) {
        assert(0);
    }

    dport_access_ref[cpu_id]--;

    if (dport_access_ref[cpu_id] == 0) {
        dport_access_end[cpu_id] = 1;

        portEXIT_CRITICAL_ISR(&g_dport_mux);
    }
        
    portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]);

#ifdef DPORT_ACCESS_BENCHMARK
    ccount_end[cpu_id] = XTHAL_GET_CCOUNT();
    ccount_margin[cpu_id][ccount_margin_cnt] = ccount_end[cpu_id] - ccount_start[cpu_id];
    ccount_margin_cnt = (ccount_margin_cnt + 1)&(DPORT_ACCESS_BENCHMARK_STORE_NUM - 1);
#endif
#endif /* CONFIG_FREERTOS_UNICORE */
}
Example #5
0
bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length)
{
    uint32_t len = 0;
    bool task_is_valid = false;
    len = (uint32_t)task_snaphort->stack_end - (uint32_t)task_snaphort->stack_start;
    // Check task's stack
    if (!esp_stack_ptr_is_sane(task_snaphort->stack_start) ||
        !esp_task_stack_start_is_sane((uint32_t)task_snaphort->stack_end) ||
        (len > COREDUMP_MAX_TASK_STACK_SIZE)) {
        // Check if current task stack corrupted
        if (task_snaphort->tcb_addr == xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID())) {
            ESP_COREDUMP_LOG_PROCESS("Crashed task will be skipped!");
        }
        ESP_COREDUMP_LOG_PROCESS("Corrupted TCB %x: stack len %lu, top %x, end %x!",
            task_snaphort->tcb_addr, len, task_snaphort->stack_start, task_snaphort->stack_end);
        task_snaphort->tcb_addr = 0; // make TCB addr invalid to skip it in dump
        task_is_valid = false;
    } else {
        ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", len,
                task_snaphort->stack_start, task_snaphort->stack_end);
        // Take stack padding into account
        *length = (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
        task_is_valid = true;
    }
    return task_is_valid;
}
Example #6
0
bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snaphort, uint32_t tcb_sz)
{
    XtExcFrame *exc_frame = (XtExcFrame*)frame;

    if (!esp_tcb_addr_is_sane((uint32_t)task_snaphort->tcb_addr, tcb_sz)) {
        ESP_COREDUMP_LOG_PROCESS("Bad TCB addr %x!", task_snaphort->tcb_addr);
        return false;
    }
    if (task_snaphort->tcb_addr == xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID())) {
        // Set correct stack top for current task
        task_snaphort->stack_start = (uint32_t)exc_frame;
        // This field is not initialized for crashed task, but stack frame has the structure of interrupt one,
        // so make workaround to allow espcoredump to parse it properly.
        if (exc_frame->exit == 0)
            exc_frame->exit = -1;
        ESP_COREDUMP_LOG_PROCESS("Current task %x EXIT/PC/PS/A0/SP %x %x %x %x %x",
                task_snaphort->tcb_addr, exc_frame->exit, exc_frame->pc, exc_frame->ps, exc_frame->a0, exc_frame->a1);
    }
    else {
        XtSolFrame *task_frame = (XtSolFrame *)task_snaphort->stack_start;
        if (task_frame->exit == 0) {
                ESP_COREDUMP_LOG_PROCESS("Task %x EXIT/PC/PS/A0/SP %x %x %x %x %x",
                        task_snaphort->tcb_addr, task_frame->exit, task_frame->pc, task_frame->ps, task_frame->a0, task_frame->a1);
        }
        else {
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
                XtExcFrame *task_frame2 = (XtExcFrame *)task_snaphort->stack_start;
                ESP_COREDUMP_LOG_PROCESS("Task %x EXIT/PC/PS/A0/SP %x %x %x %x %x",
                        task_snaphort->tcb_addr, task_frame2->exit, task_frame2->pc, task_frame2->ps, task_frame2->a0, task_frame2->a1);
#endif
        }
    }
    return true;
}
Example #7
0
/*********************************************************************
*
*       SEGGER_RTT_WriteSkipNoLock
*
*  Function description
*    Stores a specified number of characters in SEGGER RTT
*    control block which is then read by the host.
*    SEGGER_RTT_WriteSkipNoLock does not lock the application and
*    skips all data, if the data does not fit into the buffer.
*
*  Parameters
*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
*
*  Return value
*    Number of bytes which have been stored in the "Up"-buffer.
*
*  Notes
*    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
*    (2) For performance reasons this function does not call Init()
*        and may only be called after RTT has been initialized.
*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
*/
unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
  uint8_t *pbuf = (uint8_t *)pBuffer;
  uint8_t event_id = *pbuf;

  if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
      ESP_LOGE(TAG, "Too large event %d bytes!", NumBytes);
      return 0;
  }
  if (xPortGetCoreID()) { // dual core specific code
    // use the highest - 1 bit of event ID to indicate core ID
    // the highest bit can not be used due to event ID encoding method
    // this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
    if (*pbuf & 0x80) { // 2 bytes ID
      *(pbuf + 1) |= (1 << 6);
    } else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
      *pbuf |= (1 << 6);
    }
  }
  if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
    esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
    if (res != ESP_OK) {
      return 0; // skip current data buffer only, accumulated events are kept
    }
    s_events_buf_filled = 0;
  }
  memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
  s_events_buf_filled += NumBytes;
  if (event_id == SYSVIEW_EVTID_TRACE_STOP) {
    SEGGER_RTT_ESP32_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
  }
  return NumBytes;
}
Example #8
0
/*  This initialise should be really effective after vTaskStartScheduler */
void esp_dport_access_int_init(void)
{
    if (xPortGetCoreID() == 0) {
        xTaskCreatePinnedToCore(&dport_access_init_core0, "dport0", 512, NULL, 5, NULL, 0);
    } else {
        xTaskCreatePinnedToCore(&dport_access_init_core1, "dport1", 512, NULL, 5, NULL, 1);
    }
}
Example #9
0
/*
 * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
 * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
 */
BaseType_t xPortInIsrContext()
{
	unsigned int irqStatus;
	BaseType_t ret;
	irqStatus=portENTER_CRITICAL_NESTED();
	ret=(port_interruptNesting[xPortGetCoreID()] != 0);
	portEXIT_CRITICAL_NESTED(irqStatus);
	return ret;
}
Example #10
0
void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os()
{
    const uint32_t cpuid = xPortGetCoreID();

    // Re-enable cache on this CPU
    spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
    // Re-enable non-iram interrupts
    esp_intr_noniram_enable();
}
Example #11
0
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os()
{
    const uint32_t cpuid = xPortGetCoreID();
    const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;

    // do not care about other CPU, it was halted upon entering panic handler
    spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]);
    // Kill interrupts that aren't located in IRAM
    esp_intr_noniram_disable();
    // Disable cache on this CPU as well
    spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
}
Example #12
0
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
{
    spi_flash_op_lock();

    const uint32_t cpuid = xPortGetCoreID();
    const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
#ifndef NDEBUG
    // For sanity check later: record the CPU which has started doing flash operation
    assert(s_flash_op_cpu == -1);
    s_flash_op_cpu = cpuid;
#endif

    if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
        // Scheduler hasn't been started yet, it means that spi_flash API is being
        // called from the 2nd stage bootloader or from user_start_cpu0, i.e. from
        // PRO CPU. APP CPU is either in reset or spinning inside user_start_cpu1,
        // which is in IRAM. So it is safe to disable cache for the other_cpuid here.
        assert(other_cpuid == 1);
        spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]);
    } else {
        // Signal to the spi_flash_op_block_task on the other CPU that we need it to
        // disable cache there and block other tasks from executing.
        s_flash_op_can_start = false;
        esp_err_t ret = esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void*) other_cpuid);
        assert(ret == ESP_OK);
        while (!s_flash_op_can_start) {
            // Busy loop and wait for spi_flash_op_block_func to disable cache
            // on the other CPU
        }
        // Disable scheduler on the current CPU
        vTaskSuspendAll();
        // This is guaranteed to run on CPU <cpuid> because the other CPU is now
        // occupied by highest priority task
        assert(xPortGetCoreID() == cpuid);
    }
    // Kill interrupts that aren't located in IRAM
    esp_intr_noniram_disable();
    // Disable cache on this CPU as well
    spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
}
Example #13
0
void * xt_get_interrupt_handler_arg(int n)
{
    xt_handler_table_entry * entry;

    if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
        return 0;       /* invalid interrupt number */

    /* Convert exception number to _xt_exception_table name */
    n = n * portNUM_PROCESSORS + xPortGetCoreID();

    entry = _xt_interrupt_table + n;
    return entry->arg;
}
Example #14
0
static void dport_access_init_core1(void *arg)
{
    int core_id = xPortGetCoreID();

    assert(core_id == 1);

    ESP_INTR_DISABLE(ETS_DPORT_INUM);
    intr_matrix_set(core_id, ETS_FROM_CPU_INTR3_SOURCE, ETS_DPORT_INUM);
    ESP_INTR_ENABLE(ETS_DPORT_INUM);

    dport_access_ref[core_id] = 0;
    dport_access_start[core_id] = 0;
    dport_access_end[core_id] = 0;
    dport_core_state[core_id] = DPORT_CORE_STATE_RUNNING;

    vTaskDelete(NULL);
}
Example #15
0
/*
  This function registers a handler for the specified exception.
  The function returns the address of the previous handler.
  On error, it returns 0.
*/
xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f)
{
    xt_exc_handler old;

    if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
        return 0;       /* invalid exception number */

    /* Convert exception number to _xt_exception_table name */
    n = n * portNUM_PROCESSORS + xPortGetCoreID();
    old = _xt_exception_table[n];

    if (f) {
        _xt_exception_table[n] = f;
    }
    else {
        _xt_exception_table[n] = &xt_unhandled_exception;
    }

    return ((old == &xt_unhandled_exception) ? 0 : old);
}
Example #16
0
void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu()
{
    const uint32_t cpuid = xPortGetCoreID();
    const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
#ifndef NDEBUG
    // Sanity check: flash operation ends on the same CPU as it has started
    assert(cpuid == s_flash_op_cpu);
    s_flash_op_cpu = -1;
#endif

    // Re-enable cache on this CPU
    spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);

    if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
        // Scheduler is not running yet — this means we are running on PRO CPU.
        // other_cpuid is APP CPU, and it is either in reset or is spinning in
        // user_start_cpu1, which is in IRAM. So we can simply reenable cache.
        assert(other_cpuid == 1);
        spi_flash_restore_cache(other_cpuid, s_flash_op_cache_state[other_cpuid]);
    } else {
        // Signal to spi_flash_op_block_task that flash operation is complete
        s_flash_op_complete = true;
    }
    // Re-enable non-iram interrupts
    esp_intr_noniram_enable();

    // Resume tasks on the current CPU, if the scheduler has started.
    // NOTE: enabling non-IRAM interrupts has to happen before this,
    // because once the scheduler has started, due to preemption the
    // current task can end up being moved to the other CPU.
    // But esp_intr_noniram_enable has to be called on the same CPU which
    // called esp_intr_noniram_disable
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
        xTaskResumeAll();
    }
    // Release API lock
    spi_flash_op_unlock();
}
Example #17
0
BaseType_t xPortStartScheduler( void )
{
	// Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored

	#if XCHAL_CP_NUM > 0
	/* Initialize co-processor management for tasks. Leave CPENABLE alone. */
	_xt_coproc_init();
	#endif

	/* Init the tick divisor value */
	_xt_tick_divisor_init();

	/* Setup the hardware to generate the tick. */
	_frxt_tick_timer_init();

	port_xSchedulerRunning[xPortGetCoreID()] = 1;

	// Cannot be directly called from C; never returns
	__asm__ volatile ("call0    _frxt_dispatch\n");

	/* Should not get here. */
	return pdTRUE;
}
Example #18
0
static void test_delay_task(void* p)
{
    const delay_test_arg_t* arg = (delay_test_arg_t*) p;
    struct timeval tv_start, tv_stop;
    gettimeofday(&tv_start, NULL);
    switch (arg->method) {
        case 0:
            ets_delay_us(arg->delay_us);
            break;
        case 1:
            vTaskDelay(arg->delay_us / portTICK_PERIOD_MS / 1000);
            break;
        default:
            TEST_FAIL();
    }
    gettimeofday(&tv_stop, NULL);
    int real_delay_us = (tv_stop.tv_sec - tv_start.tv_sec) * 1000000 +
            tv_stop.tv_usec - tv_start.tv_usec;
    printf("%s core=%d expected=%d actual=%d\n", arg->method ? "vTaskDelay" : "ets_delay_us",
            xPortGetCoreID(), arg->delay_us, real_delay_us);
    TEST_ASSERT_TRUE(abs(real_delay_us - arg->delay_us) < 1000);
    vTaskDelay(1);
    vTaskDelete(NULL);
}
Example #19
0
/* stall other cpu that this cpu is pending to access dport register start */
void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void)
{
#ifndef CONFIG_FREERTOS_UNICORE
    int cpu_id = xPortGetCoreID();

    if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
            || dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
        return;
    }

#ifdef DPORT_ACCESS_BENCHMARK
    ccount_start[cpu_id] = XTHAL_GET_CCOUNT();
#endif
    BaseType_t intLvl=portENTER_CRITICAL_NESTED();
    oldInterruptLevel[cpu_id]=intLvl;

    if (dport_access_ref[cpu_id] == 0) {
        portENTER_CRITICAL_ISR(&g_dport_mux); 

        dport_access_start[cpu_id] = 0;
        dport_access_end[cpu_id] = 0;

        if (cpu_id == 0) {
            _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_3_REG, DPORT_CPU_INTR_FROM_CPU_3); //interrupt on cpu1
        } else {
            _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2); //interrupt on cpu0
        }

        while (!dport_access_start[cpu_id]) {};

        REG_READ(SPI_DATE_REG(3));  //just read a APB register sure that the APB-bus is idle
    }

    dport_access_ref[cpu_id]++;
#endif /* CONFIG_FREERTOS_UNICORE */
}
static void task_delete_self(void *param)
{
    printf("Task %p running on core %d. Deleting shortly...\n", xTaskGetCurrentTaskHandle(), xPortGetCoreID());
    vTaskDelay(5);
    vTaskDelete(NULL);
}
Example #21
0
/*
  Default handler for unhandled interrupts.
*/
void xt_unhandled_interrupt(void * arg)
{
	ets_printf("Unhandled interrupt %d on cpu %d!\n", (int)arg, xPortGetCoreID());
}
Example #22
0
static void esp_apptrace_test_task(void *p)
{
    esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p;
    int res, flags = 0;
    timer_isr_handle_t *inth = NULL;
    TickType_t tmo_ticks = arg->data.period / (1000 * portTICK_PERIOD_MS);

    ESP_APPTRACE_TEST_LOGI("%x: run (period %u us, stamp mask %x, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->data.mask, arg->timers_num);

    if (arg->timers_num > 0) {
        inth = pvPortMalloc(arg->timers_num * sizeof(timer_isr_handle_t));
        if (!inth) {
            ESP_APPTRACE_TEST_LOGE("Failed to alloc timer ISR handles!");
            goto on_fail;
        }
        memset(inth, 0, arg->timers_num * sizeof(timer_isr_handle_t));
        for (int i = 0; i < arg->timers_num; i++) {
            esp_apptrace_test_timer_init(arg->timers[i].group, arg->timers[i].id, arg->timers[i].data.period);
            res = timer_isr_register(arg->timers[i].group, arg->timers[i].id, arg->timers[i].isr_func, &arg->timers[i], flags, &inth[i]);
            if (res != ESP_OK) {
                ESP_APPTRACE_TEST_LOGE("Failed to timer_isr_register (%d)!", res);
                goto on_fail;
            }
            *(uint32_t *)arg->timers[i].data.buf = ((uint32_t)inth[i]) | (1 << 31) | (xPortGetCoreID() ? 0x1 : 0);
            ESP_APPTRACE_TEST_LOGI("%x: start timer %x period %u us", xTaskGetCurrentTaskHandle(), inth[i], arg->timers[i].data.period);
            res = timer_start(arg->timers[i].group, arg->timers[i].id);
            if (res != ESP_OK) {
                ESP_APPTRACE_TEST_LOGE("Failed to timer_start (%d)!", res);
                goto on_fail;
            }
        }
    }

    *(uint32_t *)arg->data.buf = (uint32_t)xTaskGetCurrentTaskHandle() | (xPortGetCoreID() ? 0x1 : 0);
    arg->data.wr_cnt = 0;
    arg->data.wr_err = 0;
    while (!arg->stop) {
        uint32_t *ts = (uint32_t *)(arg->data.buf + sizeof(uint32_t));
        *ts = (uint32_t)esp_apptrace_test_ts_get();
        memset(arg->data.buf + 2 * sizeof(uint32_t), arg->data.wr_cnt & arg->data.mask, arg->data.buf_sz - 2 * sizeof(uint32_t));
        // ESP_APPTRACE_TEST_LOGD("%x:%x: Write chunk%d %d bytes, %x", xTaskGetCurrentTaskHandle(), *ts, arg->data.wr_cnt, arg->data.buf_sz, arg->data.wr_cnt & arg->data.mask);
        if (arg->nowait) {
            res = ESP_APPTRACE_TEST_WRITE_NOWAIT(arg->data.buf, arg->data.buf_sz);
        } else {
            res = ESP_APPTRACE_TEST_WRITE(arg->data.buf, arg->data.buf_sz);
        }
        if (res) {
            if (1){//arg->data.wr_err++ < ESP_APPTRACE_TEST_PRN_WRERR_MAX) {
                ESP_APPTRACE_TEST_LOGE("%x: Failed to write trace %d %x!", xTaskGetCurrentTaskHandle(), res, arg->data.wr_cnt & arg->data.mask);
                if (arg->data.wr_err == ESP_APPTRACE_TEST_PRN_WRERR_MAX) {
                    ESP_APPTRACE_TEST_LOGE("\n");
                }
            }
        } else {
            if (0) {
                ESP_APPTRACE_TEST_LOGD("%x:%x: Written chunk%d %d bytes, %x", xTaskGetCurrentTaskHandle(), *ts, arg->data.wr_cnt, arg->data.buf_sz, arg->data.wr_cnt & arg->data.mask);
            }
            arg->data.wr_err = 0;
        }
        arg->data.wr_cnt++;
        if (tmo_ticks) {
            vTaskDelay(tmo_ticks);
        }
    }

on_fail:
    if (inth) {
        for (int i = 0; i < arg->timers_num; i++) {
            timer_pause(arg->timers[i].group, arg->timers[i].id);
            timer_disable_intr(arg->timers[i].group, arg->timers[i].id);
            if (inth[i]) {
                esp_intr_free(inth[i]);
            }
        }
        vPortFree(inth);
    }
    xSemaphoreGive(arg->done);
    vTaskDelay(1);
    vTaskDelete(NULL);
}
Example #23
0
/* "inner" restart function for after RTOS, interrupts & anything else on this
 * core are already stopped. Stalls other core, resets hardware,
 * triggers restart.
*/
void IRAM_ATTR esp_restart_noos()
{
    // Disable interrupts
    xt_ints_off(0xFFFFFFFF);

    // Enable RTC watchdog for 1 second
    rtc_wdt_protect_off();
    rtc_wdt_disable();
    rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC);
    rtc_wdt_set_stage(RTC_WDT_STAGE1, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
    rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_200ns);
    rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_200ns);
    rtc_wdt_set_time(RTC_WDT_STAGE0, 1000);
    rtc_wdt_flashboot_mode_enable();

    // Reset and stall the other CPU.
    // CPU must be reset before stalling, in case it was running a s32c1i
    // instruction. This would cause memory pool to be locked by arbiter
    // to the stalled CPU, preventing current CPU from accessing this pool.
    const uint32_t core_id = xPortGetCoreID();
    const uint32_t other_core_id = (core_id == 0) ? 1 : 0;
    esp_cpu_reset(other_core_id);
    esp_cpu_stall(other_core_id);

    // Other core is now stalled, can access DPORT registers directly
    esp_dport_access_int_abort();

    // Disable TG0/TG1 watchdogs
    TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
    TIMERG0.wdt_config0.en = 0;
    TIMERG0.wdt_wprotect=0;
    TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
    TIMERG1.wdt_config0.en = 0;
    TIMERG1.wdt_wprotect=0;

    // Flush any data left in UART FIFOs
    uart_tx_wait_idle(0);
    uart_tx_wait_idle(1);
    uart_tx_wait_idle(2);

    // Disable cache
    Cache_Read_Disable(0);
    Cache_Read_Disable(1);

    // 2nd stage bootloader reconfigures SPI flash signals.
    // Reset them to the defaults expected by ROM.
    WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
    WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
    WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
    WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
    WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
    WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);

    // Reset wifi/bluetooth/ethernet/sdio (bb/mac)
    DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 
         DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
         DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
         DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST | 
         DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
    DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);

    // Reset timer/spi/uart
    DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
            DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST);
    DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);

    // Set CPU back to XTAL source, no PLL, same as hard reset
    rtc_clk_cpu_freq_set_xtal();

    // Clear entry point for APP CPU
    DPORT_REG_WRITE(DPORT_APPCPU_CTRL_D_REG, 0);

    // Reset CPUs
    if (core_id == 0) {
        // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
        esp_cpu_reset(1);
        esp_cpu_reset(0);
    } else {
        // Running on APP CPU: need to reset PRO CPU and unstall it,
        // then reset APP CPU
        esp_cpu_reset(0);
        esp_cpu_unstall(0);
        esp_cpu_reset(1);
    }
    while(true) {
        ;
    }
}
Example #24
0
static void esp_apptrace_dummy_task(void *p)
{
    esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p;
    int res, flags = 0, i;
    timer_isr_handle_t *inth = NULL;
    TickType_t tmo_ticks = arg->data.period / (1000 * portTICK_PERIOD_MS);

    ESP_APPTRACE_TEST_LOGI("%x: run dummy task (period %u us, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->timers_num);

    if (arg->timers_num > 0) {
        inth = pvPortMalloc(arg->timers_num * sizeof(timer_isr_handle_t));
        if (!inth) {
            ESP_APPTRACE_TEST_LOGE("Failed to alloc timer ISR handles!");
            goto on_fail;
        }
        memset(inth, 0, arg->timers_num * sizeof(timer_isr_handle_t));
        for (int i = 0; i < arg->timers_num; i++) {
            esp_apptrace_test_timer_init(arg->timers[i].group, arg->timers[i].id, arg->timers[i].data.period);
            res = timer_isr_register(arg->timers[i].group, arg->timers[i].id, arg->timers[i].isr_func, &arg->timers[i], flags, &inth[i]);
            if (res != ESP_OK) {
                ESP_APPTRACE_TEST_LOGE("Failed to timer_isr_register (%d)!", res);
                goto on_fail;
            }
            *(uint32_t *)arg->timers[i].data.buf = (uint32_t)inth[i] | (1 << 31);
            ESP_APPTRACE_TEST_LOGI("%x: start timer %x period %u us", xTaskGetCurrentTaskHandle(), inth[i], arg->timers[i].data.period);
            res = timer_start(arg->timers[i].group, arg->timers[i].id);
            if (res != ESP_OK) {
                ESP_APPTRACE_TEST_LOGE("Failed to timer_start (%d)!", res);
                goto on_fail;
            }
        }
    }

    i = 0;
    while (!arg->stop) {
        ESP_APPTRACE_TEST_LOGD("%x: dummy task work %d.%d", xTaskGetCurrentTaskHandle(), xPortGetCoreID(), i++);
        if (tmo_ticks) {
            vTaskDelay(tmo_ticks);
        }
    }

on_fail:
    if (inth) {
        for (int i = 0; i < arg->timers_num; i++) {
            timer_pause(arg->timers[i].group, arg->timers[i].id);
            timer_disable_intr(arg->timers[i].group, arg->timers[i].id);
            if (inth[i]) {
                esp_intr_free(inth[i]);
            }
        }
        vPortFree(inth);
    }
    xSemaphoreGive(arg->done);
    vTaskDelay(1);
    vTaskDelete(NULL);
}