ulp: added basic support for building and running a binary in the lp core

This commit is contained in:
Marius Vikhammer
2023-02-27 17:03:42 +08:00
parent daf4150846
commit 284dabf17f
33 changed files with 517 additions and 23 deletions

View File

@@ -0,0 +1,8 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers")
list(APPEND SDKCONFIG_DEFAULTS "sdkconfig.defaults")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(lp_core_test)

View File

@@ -0,0 +1,3 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |

View File

@@ -0,0 +1,11 @@
set(app_sources "test_app_main.c" "test_lp_core.c")
set(lp_core_sources "lp_core/test_main.c")
idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "lp_core"
REQUIRES ulp unity
WHOLE_ARCHIVE)
set(lp_core_app_name lp_core_test_app)
set(lp_core_exp_dep_srcs ${app_sources})
ulp_embed_binary(${lp_core_app_name} "${lp_core_sources}" "${lp_core_exp_dep_srcs}")

View File

@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "test_shared.h"
volatile lp_core_test_commands_t main_cpu_command = LP_CORE_NO_COMMAND;
volatile lp_core_test_command_reply_t main_cpu_reply = LP_CORE_COMMAND_INVALID;
volatile lp_core_test_commands_t command_resp = LP_CORE_NO_COMMAND;
volatile uint32_t test_data_in = 0;
volatile uint32_t test_data_out = 0;
volatile uint32_t counter = 0;
volatile uint32_t incrementer = 0;
void handle_commands(lp_core_test_commands_t cmd)
{
counter++;
switch (cmd) {
case LP_CORE_READ_WRITE_TEST:
/* Echo the command ID back to the main CPU */
command_resp = LP_CORE_READ_WRITE_TEST;
/* Process test data */
test_data_out = test_data_in ^ XOR_MASK;
/* Set the command reply status */
main_cpu_reply = LP_CORE_COMMAND_OK;
break;
case LP_CORE_NO_COMMAND:
main_cpu_reply = LP_CORE_COMMAND_OK;
break;
default:
main_cpu_reply = LP_CORE_COMMAND_NOK;
break;
}
}
int main (void)
{
while (1) {
handle_commands(main_cpu_command);
}
return 0;
}

View File

@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#define XOR_MASK 0xDEADBEEF
typedef enum{
LP_CORE_READ_WRITE_TEST = 1,
LP_CORE_NO_COMMAND,
} lp_core_test_commands_t;
typedef enum {
LP_CORE_COMMAND_OK = 1,
LP_CORE_COMMAND_NOK,
LP_CORE_COMMAND_INVALID,
} lp_core_test_command_reply_t;

View File

@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
// Some resources are lazy allocated in the sleep code, the threshold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (-500)
static size_t before_free_8bit;
static size_t before_free_32bit;
static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
}
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
check_leak(before_free_8bit, after_free_8bit, "8BIT");
check_leak(before_free_32bit, after_free_32bit, "32BIT");
}
void app_main(void)
{
unity_run_menu();
}

View File

@@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <inttypes.h>
#include "lp_core_test_app.h"
#include "ulp_lp_core.h"
#include "test_shared.h"
#include "unity.h"
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_bin_start");
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_bin_end");
static bool firmware_loaded = false;
static void load_and_start_lp_core_firmware(void)
{
if (!firmware_loaded) {
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
};
TEST_ASSERT(ulp_lp_core_load_binary(lp_core_main_bin_start,
(lp_core_main_bin_end - lp_core_main_bin_start)) == ESP_OK);
TEST_ASSERT(ulp_lp_core_run(&cfg) == ESP_OK);
firmware_loaded = true;
}
}
TEST_CASE("LP core and main CPU are able to exchange data", "[lp_core]")
{
const uint32_t test_data = 0x12345678;
/* Load ULP RISC-V firmware and start the coprocessor */
load_and_start_lp_core_firmware();
/* Setup test data */
ulp_test_data_in = test_data ^ XOR_MASK;
ulp_main_cpu_command = LP_CORE_READ_WRITE_TEST;
/* Wait till we receive the correct command response */
while (ulp_command_resp != LP_CORE_READ_WRITE_TEST) {
}
/* Verify test data */
TEST_ASSERT(ulp_command_resp == LP_CORE_READ_WRITE_TEST);
/* Wait till we receive COMMAND_OK reply */
while (ulp_main_cpu_reply != LP_CORE_COMMAND_OK) {
}
printf("data out: 0x%" PRIx32 ", expected: 0x%" PRIx32 " \n", ulp_test_data_out, test_data);
TEST_ASSERT(test_data == ulp_test_data_out);
/* Clear test data */
ulp_main_cpu_command = LP_CORE_NO_COMMAND;
}

View File

@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32c6
@pytest.mark.generic
def test_lp_core(dut: Dut) -> None:
dut.run_all_single_board_cases()

View File

@@ -0,0 +1,5 @@
CONFIG_ESP_TASK_WDT_INIT=n
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=4096