tests: sd: Adds MMC test and Kconfigs
Adds MMC test and Kconfigs for MMC Note: MMC not yet implemented as of this commit Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
parent
cad243d59e
commit
fea01b4254
6 changed files with 290 additions and 1 deletions
|
@ -5,6 +5,11 @@
|
|||
|
||||
menu "SD"
|
||||
|
||||
config MMC_STACK
|
||||
bool "MMC protocol support"
|
||||
help
|
||||
Enable MMC protocol support. Required for eMMC cards to function.
|
||||
|
||||
config SDMMC_STACK
|
||||
bool "SDMMC protocol support"
|
||||
help
|
||||
|
@ -18,7 +23,7 @@ config SDIO_STACK
|
|||
|
||||
config SD_STACK
|
||||
bool
|
||||
default y if SDMMC_STACK || SDIO_STACK
|
||||
default y if MMC_STACK || SDMMC_STACK || SDIO_STACK
|
||||
select SDHC
|
||||
help
|
||||
Enable SD card support.
|
||||
|
@ -65,6 +70,8 @@ config SD_BUFFER_SIZE
|
|||
# If SDHC required buffer alignment, we need a full block size in
|
||||
# internal buffer
|
||||
default 512 if SDHC_BUFFER_ALIGNMENT != 1
|
||||
# If MMC is being used, need 512 bytes to read EXT_CSD
|
||||
default 512 if MMC_STACK
|
||||
# Otherwise, we only need 64 bytes to read SD switch function
|
||||
default 64
|
||||
help
|
||||
|
@ -85,6 +92,12 @@ config SD_UHS_PROTOCOL
|
|||
Enable support for ultra high speed SD cards. This can be disabled to
|
||||
reduce code size, at the cost of data transfer speeds.
|
||||
|
||||
config MMC_RCA
|
||||
hex "MMC Relative card address"
|
||||
default 2
|
||||
help
|
||||
Relative card address to publish to MMC card.
|
||||
|
||||
endif # SD_STACK
|
||||
|
||||
endmenu
|
||||
|
|
8
tests/subsys/sd/mmc/CMakeLists.txt
Normal file
8
tests/subsys/sd/mmc/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(mmc_subsys_test)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
29
tests/subsys/sd/mmc/README.txt
Normal file
29
tests/subsys/sd/mmc/README.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
MMC Subsystem Test
|
||||
##################
|
||||
|
||||
This test is designed to verify the MMC protocol stack implementation,
|
||||
and run stress tests to verify large data transfers succeed using the
|
||||
subsystem. Due to the differences between underlying SD host controller drivers,
|
||||
this test also serves as a complete test for the SDHC driver implementation in
|
||||
use. It requires an SD card be connected to the board to pass, and will
|
||||
perform destructive I/O on the card, wiping any data present. The test has
|
||||
the following phases:
|
||||
|
||||
* Init test: verify the SD host controller can detect card presence, and
|
||||
test the initialization flow of the MMC subsystem to verify that the stack
|
||||
can correctly initialize an SD card.
|
||||
|
||||
* IOCTL test: verify the SD subsystem correctly implements IOCTL calls required
|
||||
for block devices in Zephyr.
|
||||
|
||||
* Read test: verify that single block reads work, followed by multiple
|
||||
block reads. Ensure the subsystem will reject reads beyond the end of
|
||||
the card's stated size.
|
||||
|
||||
* Write test: verify that single block writes work, followed by multiple
|
||||
block writes. Ensure the subsystem will reject writes beyond the end of
|
||||
the card's stated size.
|
||||
|
||||
* R/W test: write data to the MMC card, and verify that it is able
|
||||
to be read back without error. Perform this R/W combination at several
|
||||
sector locations across the MMC card.
|
5
tests/subsys/sd/mmc/prj.conf
Normal file
5
tests/subsys/sd/mmc/prj.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
CONFIG_TEST=y
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_MMC_STACK=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_ZTEST_NEW_API=y
|
224
tests/subsys/sd/mmc/src/main.c
Normal file
224
tests/subsys/sd/mmc/src/main.c
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright 2022 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/disk.h>
|
||||
#include <zephyr/sd/mmc.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/ztest.h>
|
||||
|
||||
#define SECTOR_COUNT 32
|
||||
#define SECTOR_SIZE 512 /* subsystem should set all cards to 512 byte blocks */
|
||||
#define BUF_SIZE (SECTOR_SIZE * SECTOR_COUNT)
|
||||
static const struct device *const sdhc_dev = DEVICE_DT_GET(DT_ALIAS(sdhc0));
|
||||
static struct sd_card card;
|
||||
static uint8_t buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
|
||||
static uint8_t check_buf[BUF_SIZE] __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT);
|
||||
static uint32_t sector_size;
|
||||
static uint32_t sector_count;
|
||||
|
||||
#define MMC_UNALIGN_OFFSET 1
|
||||
|
||||
/*
|
||||
* Verify that SD stack can initialize an MMC card
|
||||
* This test must run first, to ensure the card is initialized.
|
||||
*/
|
||||
ZTEST(sd_stack, test_0_init)
|
||||
{
|
||||
int ret;
|
||||
|
||||
zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready");
|
||||
|
||||
ret = sd_init(sdhc_dev, &card);
|
||||
|
||||
zassert_equal(ret, 0, "Card initialization failed");
|
||||
}
|
||||
|
||||
/* Verify that MMC stack returns valid IOCTL values */
|
||||
ZTEST(sd_stack, test_ioctl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_COUNT, §or_count);
|
||||
zassert_equal(ret, 0, "IOCTL sector count read failed");
|
||||
TC_PRINT("SD card reports sector count of %d\n", sector_count);
|
||||
|
||||
ret = mmc_ioctl(&card, DISK_IOCTL_GET_SECTOR_SIZE, §or_size);
|
||||
zassert_equal(ret, 0, "IOCTL sector size read failed");
|
||||
TC_PRINT("SD card reports sector size of %d\n", sector_size);
|
||||
}
|
||||
|
||||
/* Verify that SD stack can read from an SD card */
|
||||
ZTEST(sd_stack, test_read)
|
||||
{
|
||||
int ret;
|
||||
int block_addr = 0;
|
||||
|
||||
/* Try simple reads from start of SD card */
|
||||
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, 1);
|
||||
zassert_equal(ret, 0, "Single block card read failed");
|
||||
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
|
||||
zassert_equal(ret, 0, "Multiple block card read failed");
|
||||
|
||||
/* Try a series of reads from the same block */
|
||||
block_addr = sector_count / 2;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
|
||||
zassert_equal(ret, 0, "Multiple reads from same addr failed");
|
||||
}
|
||||
/* Verify that out of bounds read fails */
|
||||
block_addr = sector_count;
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, 1);
|
||||
zassert_not_equal(ret, 0, "Out of bounds read should fail");
|
||||
|
||||
block_addr = sector_count - 2;
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, 2);
|
||||
zassert_equal(ret, 0, "Read from end of card failed");
|
||||
|
||||
/* Verify that unaligned reads work */
|
||||
block_addr = 3;
|
||||
ret = mmc_read_blocks(&card, buf + MMC_UNALIGN_OFFSET, block_addr, SECTOR_COUNT - 1);
|
||||
zassert_equal(ret, 0, "Unaligned read failed");
|
||||
}
|
||||
|
||||
/* Verify that SD stack can write to an SD card */
|
||||
ZTEST(sd_stack, test_write)
|
||||
{
|
||||
int ret;
|
||||
int block_addr = 0;
|
||||
|
||||
/* Try simple writes from start of SD card */
|
||||
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, 1);
|
||||
zassert_equal(ret, 0, "Single block card write failed");
|
||||
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
|
||||
zassert_equal(ret, 0, "Multiple block card write failed");
|
||||
|
||||
/* Try a series of reads from the same block */
|
||||
block_addr = sector_count / 2;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
|
||||
zassert_equal(ret, 0, "Multiple writes to same addr failed");
|
||||
}
|
||||
/* Verify that out of bounds write fails */
|
||||
block_addr = sector_count;
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, 1);
|
||||
zassert_not_equal(ret, 0, "Out of bounds write should fail");
|
||||
|
||||
block_addr = sector_count - 2;
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, 2);
|
||||
zassert_equal(ret, 0, "Write to end of card failed");
|
||||
|
||||
/* Verify that unaligned writes work */
|
||||
block_addr = 3;
|
||||
ret = mmc_write_blocks(&card, buf + MMC_UNALIGN_OFFSET, block_addr, SECTOR_COUNT - 1);
|
||||
zassert_equal(ret, 0, "Unaligned write failed");
|
||||
}
|
||||
|
||||
/* Test reads and writes interleaved, to verify data is making it on disk */
|
||||
ZTEST(sd_stack, test_rw)
|
||||
{
|
||||
int ret;
|
||||
int block_addr = 0;
|
||||
|
||||
/* Zero the write buffer */
|
||||
memset(buf, 0, BUF_SIZE);
|
||||
memset(check_buf, 0, BUF_SIZE);
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
|
||||
zassert_equal(ret, 0, "Write to card failed");
|
||||
/* Verify that a read from this area is empty */
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT / 2);
|
||||
zassert_equal(ret, 0, "Read from card failed");
|
||||
zassert_mem_equal(buf, check_buf, BUF_SIZE, "Read of erased area was not zero");
|
||||
|
||||
/* Now write nonzero data block */
|
||||
for (int i = 0; i < sizeof(buf); i++) {
|
||||
check_buf[i] = buf[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
ret = mmc_write_blocks(&card, buf, block_addr, SECTOR_COUNT);
|
||||
zassert_equal(ret, 0, "Write to card failed");
|
||||
/* Clear the read buffer, then write to it again */
|
||||
memset(buf, 0, BUF_SIZE);
|
||||
ret = mmc_read_blocks(&card, buf, block_addr, SECTOR_COUNT);
|
||||
zassert_equal(ret, 0, "Read from card failed");
|
||||
zassert_mem_equal(buf, check_buf, BUF_SIZE, "Read of written area was not correct");
|
||||
|
||||
block_addr = (sector_count / 3);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
/* Verify that unaligned writes work */
|
||||
ret = mmc_write_blocks(&card, buf + MMC_UNALIGN_OFFSET, block_addr,
|
||||
SECTOR_COUNT - 1);
|
||||
zassert_equal(ret, 0, "Write to card failed");
|
||||
/* Zero check buffer and read into it */
|
||||
memset(check_buf + MMC_UNALIGN_OFFSET, 0, (SECTOR_COUNT - 1) * sector_size);
|
||||
ret = mmc_read_blocks(&card, check_buf + MMC_UNALIGN_OFFSET, block_addr,
|
||||
(SECTOR_COUNT - 1));
|
||||
zassert_equal(ret, 0, "Read from card failed");
|
||||
zassert_mem_equal(buf + MMC_UNALIGN_OFFSET, check_buf + MMC_UNALIGN_OFFSET,
|
||||
(SECTOR_COUNT - 1) * sector_size,
|
||||
"Unaligned read of written area was not correct");
|
||||
}
|
||||
}
|
||||
|
||||
/* Simply dump the card configuration. */
|
||||
ZTEST(sd_stack, test_card_config)
|
||||
{
|
||||
switch (card.card_voltage) {
|
||||
case SD_VOL_1_2_V:
|
||||
TC_PRINT("Card voltage: 1.2V\n");
|
||||
break;
|
||||
case SD_VOL_1_8_V:
|
||||
TC_PRINT("Card voltage: 1.8V\n");
|
||||
break;
|
||||
case SD_VOL_3_0_V:
|
||||
TC_PRINT("Card voltage: 3.0V\n");
|
||||
break;
|
||||
case SD_VOL_3_3_V:
|
||||
TC_PRINT("Card voltage: 3.3V\n");
|
||||
break;
|
||||
default:
|
||||
zassert_unreachable("Card voltage is not known value");
|
||||
}
|
||||
zassert_equal(card.status, CARD_INITIALIZED, "Card status is not OK");
|
||||
switch (card.card_speed) {
|
||||
case MMC_LEGACY_TIMING:
|
||||
TC_PRINT("Card timing: Legacy MMC\n");
|
||||
break;
|
||||
case MMC_HS_TIMING:
|
||||
TC_PRINT("Card timing: High Speed MMC\n");
|
||||
break;
|
||||
case MMC_HS200_TIMING:
|
||||
TC_PRINT("Card timing: MMC HS200\n");
|
||||
break;
|
||||
case MMC_HS400_TIMING:
|
||||
TC_PRINT("Card timing: MMC HS400\n");
|
||||
break;
|
||||
default:
|
||||
zassert_unreachable("Card timing is not known value");
|
||||
}
|
||||
switch (card.type) {
|
||||
case CARD_SDIO:
|
||||
TC_PRINT("Card type: SDIO\n");
|
||||
break;
|
||||
case CARD_SDMMC:
|
||||
TC_PRINT("Card type: SDMMC\n");
|
||||
break;
|
||||
case CARD_COMBO:
|
||||
TC_PRINT("Card type: combo card\n");
|
||||
break;
|
||||
case CARD_MMC:
|
||||
TC_PRINT("Card type: MMC\n");
|
||||
break;
|
||||
default:
|
||||
zassert_unreachable("Card type is not known value");
|
||||
}
|
||||
}
|
||||
|
||||
ZTEST_SUITE(sd_stack, NULL, NULL, NULL, NULL, NULL);
|
10
tests/subsys/sd/mmc/testcase.yaml
Normal file
10
tests/subsys/sd/mmc/testcase.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
common:
|
||||
depends_on: sdhc
|
||||
tags: drivers sdhc
|
||||
tests:
|
||||
subsys.sd.mmc:
|
||||
harness: ztest
|
||||
filter: dt_compat_enabled("zephyr,mmc-disk")
|
||||
tags: sdhc
|
||||
min_ram: 32
|
||||
integration_platforms:
|
Loading…
Add table
Add a link
Reference in a new issue