test: add configurable mmu page size test app

Test app to ensure that bootloader and application built with
different flash MMU page size are compatible. This is for the
SoCs that support configurable flash MMU page size.
This commit is contained in:
Mahavir Jain
2024-10-17 21:44:35 +05:30
parent 07318a4987
commit fbe93aa25e
11 changed files with 177 additions and 0 deletions

View File

@ -62,6 +62,15 @@ tools/test_apps/system/memprot:
temporary: true
reason: the other targets are not tested yet
tools/test_apps/system/mmu_page_size:
enable:
- if: IDF_TARGET in ["esp32c6", "esp32h2"]
reason: Coverage for two targets with configurable MMU page size is sufficient
depends_components:
- esp_app_format
- bootloader_support
- esp_mm
tools/test_apps/system/no_embedded_paths:
enable:
- if: IDF_TARGET in ["esp32", "esp32c3", "esp32s2"]

View File

@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(test_mmu_page_size)

View File

@ -0,0 +1,5 @@
| Supported Targets | ESP32-C6 | ESP32-H2 |
| ----------------- | -------- | -------- |
This test app ensures that bootloader can support configurable MMU page size as per the application binary header.
This test tries to boot the application with different MMU page sizes and checks if the application is able to boot successfully.

View File

@ -0,0 +1,51 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import logging
import os
import pytest
from _pytest.fixtures import FixtureRequest
from _pytest.monkeypatch import MonkeyPatch
from pytest_embedded_idf.app import FlashFile
from pytest_embedded_idf.serial import IdfSerial
# This is a custom IdfSerial class to support custom functionality
# which is required only for this test
class FlashBootloader(IdfSerial):
def bootloader_flash(self, binary_path: str) -> None:
"""
Flash bootloader.
:return: None
"""
logging.info('Flashing bootloader')
bootloader_path = os.path.join(binary_path, 'bootloader', 'bootloader.bin')
logging.info(bootloader_path)
offs = int(self.app.sdkconfig.get('BOOTLOADER_OFFSET_IN_FLASH', 0))
logging.info('bootloader offset is {0}'.format(hex(offs)))
prev_flash_files = self.app.flash_files
flash_files = []
flash_files.append(
FlashFile(
offs,
bootloader_path,
False,
)
)
self.app.flash_files = flash_files
self.flash()
# Restore self.app.flash files to original value
self.app.flash_files = prev_flash_files
@pytest.fixture(scope='module')
def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch:
mp = MonkeyPatch()
request.addfinalizer(mp.undo)
return mp
@pytest.fixture(scope='module', autouse=True)
def replace_dut_class(monkeypatch_module: MonkeyPatch) -> None:
monkeypatch_module.setattr('pytest_embedded_idf.IdfSerial', FlashBootloader)

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
PRIV_REQUIRES unity esp_partition)

View File

@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "unity.h"
#include "esp_partition.h"
#define SZ 4096
void app_main(void)
{
printf("App is running\n");
// Perform some partition and memory map related operations
char src_p_1[32] = "Test data pattern 123456789";
char buf[32];
// Find storage partition
const esp_partition_t* partition = esp_partition_find_first(
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL);
TEST_ASSERT_NOT_NULL(partition);
esp_partition_mmap_handle_t handle1;
const void *ptr1;
TEST_ESP_OK(esp_partition_mmap(partition, 0, SZ, ESP_PARTITION_MMAP_DATA, &ptr1, &handle1));
TEST_ESP_OK(esp_partition_erase_range(partition, 0, SZ));
TEST_ESP_OK(esp_partition_write(partition, 0, src_p_1, sizeof(src_p_1)));
memcpy(buf, ptr1, sizeof(buf));
TEST_ASSERT_EQUAL(0, memcmp(buf, src_p_1, sizeof(buf)));
esp_partition_munmap(handle1);
printf("Partition test done\n");
}

View File

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x6000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 1M,
storage, data, fat, , 64K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, , 0x6000,
4 phy_init, data, phy, , 0x1000,
5 factory, app, factory, , 1M,
6 storage, data, fat, , 64K,

View File

@ -0,0 +1,52 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import os
import pytest
from artifacts_handler import ArtifactType
from idf_ci_utils import IDF_PATH
from pytest_embedded import Dut
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize('config', ['32K'], indirect=True)
def test_app_mmu_page_size_32k_and_bootloader_mmu_page_size_64k(dut: Dut, app_downloader, config) -> None: # type: ignore
dut.expect('App is running')
assert '32K' in config
app_config = config.replace('32K', '64K')
path_to_mmu_page_size_64k_build = os.path.join(dut.app.app_path, f'build_{dut.target}_{app_config}')
if app_downloader:
app_downloader.download_app(
os.path.relpath(path_to_mmu_page_size_64k_build, IDF_PATH), ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES
)
dut.serial.bootloader_flash(path_to_mmu_page_size_64k_build)
dut.expect('MMU page size mismatch')
dut.expect('App is running')
dut.expect('Partition test done\n')
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize('config', ['64K'], indirect=True)
def test_app_mmu_page_size_64k_and_bootloader_mmu_page_size_32k(dut: Dut, app_downloader, config) -> None: # type: ignore
dut.expect('App is running')
assert '64K' in config
app_config = config.replace('64K', '32K')
path_to_mmu_page_size_32k_build = os.path.join(dut.app.app_path, f'build_{dut.target}_{app_config}')
if app_downloader:
app_downloader.download_app(
os.path.relpath(path_to_mmu_page_size_32k_build, IDF_PATH), ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES
)
dut.serial.bootloader_flash(path_to_mmu_page_size_32k_build)
dut.expect('MMU page size mismatch')
dut.expect('App is running')
dut.expect('Partition test done\n')

View File

@ -0,0 +1,2 @@
# This config option internally select 32KB MMU page size
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y

View File

@ -0,0 +1,2 @@
# This config option internally select 64KB MMU page size
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

View File

@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_CUSTOM=y