In the QSPIFBlockDevice component we checked if BUILD_TESTING was
enabled before adding the QSPIFBlockDevice/UNITTESTS subdirectory. In
the parent blockdevice/CMakeLists.txt we added the QSPIFBlockDevice
subdirectory to the build under two separate conditions:
* when "QSPIF" is present in MBED_TARGET_LABELS
* when building only unit tests
This wasn't quite enough, as when we build greentea tests for some
targets QSPIF is enabled in MBED_TARGET_LABELS, causing the
QSPIFBlockDevice subdirectory and its unit tests to be added when
building greentea tests. This caused a test failure on targets which
enable QSPIF:
```
The following tests FAILED:
40 - qspif-unittest_NOT_BUILT (Not Run)
```
To fix this we need to specifically check that we're not building
greentea tests before adding the QSPIFBlockDevice/UNITTESTS directory to
the project.
Part of this issue is our reliance on MBED_TARGET_LABELS to pull
features in to the build. We should refactor our usage of
MBED_TARGET_LABELS and use CMake target dependencies where possible.
Then we wouldn't need to add subdirectories under various, often
conflicting, scenarios. Instead the targets would always be available
and we would just choose which ones to actually build in different cases
using CMake target linking.
A Sector Map Parameter Table contains a sequence of the following
descriptors:
* (Optional) configuration detection command descriptors, one for
each command to run to determine the current configuration. This
exists only if the flash layout is configurable.
* Sector map descriptors, one for each possible configuration. On
a flash device with a non-configurable layout, there is only one
such descriptor.
Previously we only supported the non-configurable case with a single
descriptor. This commit adds support for multiple configurations.
Add a test case to verify that the quirk on `CR1NV` and `CR3NV`
registers get applied by `QSPIFBlockDevice` when the flash device
is S25FS512S.
`QSPIFBlockDevice` depends on the SFDP functions and the `QSPI` class,
but we can't use gMock on them because:
* SFDP functions are global functions, whereas gMock only supports
mocking class member functions.
* A mocked class is injected into the test subject, but passing a
preexisting `QSPI` instance into `QSPIFBlockDevice` is not possible
(unless we resort to pointers). For details, see comments in
test_QSPIFBlockDevice.cpp.
So fakes of the `QSPI` class and any SFDP functions involved are
defined in test_QSPIFBlockDevice.cpp.
The entire flash chip S25FS512S consists of uniform 256KB sectors.
Additionally, it has three configurations:
* 0x01: Eight 4KB sectors (32KB in total) overlaying the start of
the first 256KB sector
* 0x03: Eight 4KB sectors (32KB in total) overlaying the end of the
last 256KB sector
* 0x05: No overlaying sectors
The active configuration is determined from bit fields of two
registers, CR1NV and CR3NV.
Mbed OS does not currently support partially overlaying sectors,
meaning that with eight 4KB sectors overlay a 256KB sectors, the
remaining 224KB (== 256KB - 8 * 4KB) of the big sector can't be
correctly handled. Supporting such scenario would involve a large
amount of rewriting in Mbed OS's BlockDevice, SFDP and their tests,
and may increase the code size.
So, this commit applies a quirk to always report configuration 0x05
(no overlaying sectors). Even if 0x01 or 0x03 is the real configuration,
they are compatible with the 0x05 configuration because 256KB sectors
exist in all cases.
Note: This quirk does *not* change actual configurations on hardware,
because registers CR1NV and CR3NV are one-time configurable (OTP) -
each bit field has a factory value of 0 and can be changed to 1 by the
user but not back to 0. So QSPIFBlockDevice avoids changing them.
Cypress S25FS512S's SFDP table suggests that bit-1 of the register
CR3NV on 25FS512S should equal 1. But it is a known issue that the
value is actually 0 on hardware. So if we query the value of CR3NV
during configuration detection, we can't find a configuration that
matches the SFDP data. This issue has been discussed in the Linux MTD
(Memory Technology Devices) mailing list:
https://linux-mtd.infradead.narkive.com/ylHK6CyT/spi-nor-fs512s-incorrect-cr3nv-1-value
This commit adds a quirk to report bit-1 of CR3NV as 1.
Note: In Mbed OS, vendor-specific quirks can only be handled in block
devices. The SFDP functions assume data from hardware to be correct.
So this quirk is in the block device.
In Mbed OS, each library has an `include/<library>/` subdirectory
containing headers. The recommended way to include a header is
`#include "<library>/<header>.h"` to avoid potential conflicts with
any external modules that have same names of headers.
This is not enforced yet, and both include/ and include/<component>/
are in a library's include paths, to avoid breaking preexisting
Mbed projects that don't follow the recommendation. But code within
Mbed OS should follow it at least.
The second byte of the sector map descriptor is the configuration ID.
On a device with non-configurable layout, the only available map
descriptor's configuration ID must be 0x00 as required by the
JESD216D standard. This value is important, because we will check
each descriptor's configuration ID when we support multiple
configurations.
Note: The test data is fake - when we modified real data of a
configurable device to become non-configurable for test purpose, we
forgot to change this field.
The SFDP functions parse SFDP data which is fetched by a callback
called `sfdp_reader` provided by {SPIF,QSPIF,OSPIF}BlockDevice.
Currently, this callback interface only takes a read address and an RX
buffer to store output data. This has been enough, because other SPI
parameters are always the same when fetching the SFDP table only -
they are just hardcoded in each reader.
But in the future we will add support for flash devices with multiple
configurations (in a subsequent commit), and to detect which
configuration is enabled, we will need to send detection commands
which require device-dependent SPI parameters:
* address size
* instruction
* dummy cycles
This commit
* turns the above SPI parameters from predefined/hardcoded values
into parameters of the callback
* lets the SFDP functions pass the above parameters to the callback
(Note: To read the SFDP table itself, those values are constants
defined by the standard, not tied to any particular device, so they
can be known to the SFDP functions)
* updates the callbacks implemented by {SPIF,QSPIF,OSPIF}BlockDevice
* updates the mock callback for unit tests and expectations
When passing an allocation size directly to `std::make_unique`,
`std::nothrow` is unavailable, so any failed allocation results in
an exception which we cannot catch because Mbed OS is compiled with
`-fno-exceptions`. To fix this, chain `std::make_unique` with
`new (std::nothrow)`, and the allocated `unique_ptr` retains the
`nullptr` property.
The test case for multithreaded erase/program/read allocates a few
Thread objects from the heap and starts them. It has a few problems:
* To check that there will be enough heap to start a new thread, the
test case tries to allocate a dummy buffer of the thread's heap size
and then frees it, before starting the thread. Then the thread will
allocate its own stack. Such check is not reliable, because threads
that are already running also perform additional allocation (when
running `test_thread_job()`) and may take away the memory we just
checked.
* When deleting all threads in a loop, the loop boundary misses the
last thread if the last thread object was allocated but not started
(i.e. due to failed thread stack allocation check).
To fix the issues
* Start a thread without any allocation test. Following the preceding
commit "rtos: Thread: Make stack allocation failure runtime catchable",
`Thread::start()` now returns `osErrorNoMemory` if stack allocation
fails which we can handle.
* Store pointers to all threads in a zero-initialized array, and
free all elements at the end of the test.
Add an option to enable the greentea tests independently from the unit
tests.
We can't just use the typical BUILD_TESTING option to enable greentea
tests. BUILD_TESTING enables unit tests and fetches googletest, which
are compiled for the host. Greentea tests are cross compiled and require
a toolchain file. For this reason we add a new option just to enable
greentea tests, preventing build failures triggered by the unit tests
and googletest.
Add tests for `sfdp_parse_sector_map_table()` which currently (at the
time of this commit) supports flash devices with
* no Sector Map Parameter Table (i.e. the whole flash is uniform and
non-configurable)
* a single descriptor in the Sector Map Parameter Table (i.e. the
flash layout is non-configurable and has multiple regions)
Support and unit tests for flashes with multiple configurable layouts
will be added in the future.
Note: The implementation of `sfdp_parse_sector_map_table()` assumes
the table to be valid if read succeeds, so the SFDP reader callback
needs to ensure it reads data correctly or return an error.
A flash device with no sector map table has uniform sectors, and we
treat the whole flash as one region. In this case the function
`sfdp_parse_sector_map_table()` sets the single region's size and high
boundary accordingly, but it lacks setting of region count to 1, so
users of the SFDP parser may not get the correct number of regions.
This commit fixes the issue.
When a flash chip's SFDP table has no sector map, we treat the whole
flash as a single region. As an optimization, this should only be
done if there is indeed no sector map.
Individual libraries' `target_h` stub headers have now all been moved
from `mbed-headers-base` to `mbed-headers-<library>`.
Note: Even though headers previously in `target_h` are technically
stubs/fakes too, they are used by not only unit tests but also regular
libraries when compiled for unit tests, because no target-specific HAL
implementation exists in this case. In order for regular library
sources to pick up `target_h` headers, those headers must
* have the same names as regular headers
* appear first in include paths
This is why those headers are part of `mbed-headers-<library>` and not
`mbed-stubs-<library>`. Before this refactoring, `mbed-headers-base`
was the first in unit tests' include paths.
Previously a test executable was recognised as a single test by CTest.
However, test executables usually contain multiple test cases, the
results of the test cases should be individually reported. With our
previous setup we could miss test case failures that didn't cause the
executable to return an error code.
This commit uses gtest_discover_test to discover all test cases in a
test executable. This enables CTest to match test passes and failures
from the googletest binary output.
Production code should not contain any test-specific checks. Rather
than checking `UNITTEST`, MbedCRC.h can simply include in all cases
<mstd_type_traits> whose unit test stub exists.
Also remove the `UNITTEST` macro from CMake definitions of kvstore
unit tests which depend on MbedCRC.h.
The CMake target `mbed-headers` brings in all headers, and we are
gradually moving away from it and explicitly use only headers needed
by each unit test.
The header `mbed.h` pulls in headers from a number of Mbed OS
components that are not necessarily used. It was intended for user
applications only, and libraries and unit tests should explicitly
include library headers it uses to limit dependencies.
This change avoids having to link unnecessary libraries in storage
unit tests' CMake definitions.
Move storage stubs from UNITTESTS/stubs into components inside the
top-level storage directory. Specifically,
* storage/blockdevice/tests/UNITTESTS/doubles/ for BlockDevice stubs.
* storage/kvstore/filesystemstore/tests/UNITTESTS/ for a stub used by
the FileSystemStore test. The stub has been renamed from
kv_config_stub.cpp to filesystemstore_kv_config_stub.cpp, to make it
evident why it doesn't go into storage/kvstore/kv_config/.
Assumption that greentea test file is always named main.cpp is
incorrect. Updated mbed_greentea_add_test() macro to make TEST_SOURCES
parameter compulsory, which is used to specify greentea test
file(s). This allows tests to use C, or have a different name.
Therefore also updated all pre-existing greentea test CMake files to
explicity add main.cpp to TEST_SOURCES.
Typically when adding a unit test directory to a CMake project a check
will be used to ensure the subdirectory is added only if the following
are true:
* The BUILD_TESTING option is set to ON.
* The current CMake project is the top-level project.
The reason being, if a downstream project includes our project they
generally don't want to build our unit tests.
In mbed-os, we do correctly specify the above condition before adding
the central UNITTEST subdirectory, which fetches googletest and adds the
"stub" libraries the unit tests depend on. However, we only check if
CMAKE_CROSSCOMPILING is OFF (or undefined) before actually adding the
unit tests. This mismatched logic would lead to unexpected build
failures in various scenarios. One likely case could be: a downstream
project including mbed-os happens to set CMAKE_CROSSCOMPILING to
OFF/undefined for any reason (possibly to build its own unit tests).
mbed-os would go ahead and attempt to build its tests without fetching
googletest or adding the required stub targets.
To fix the issue replace the check for CMAKE_CROSSCOMPILING in the unit
tests with the same BUILD_TESTING idiom we use for adding the central
UNITTESTS subdirectory.
- Remove redundant cmake script as already added the CMake configuration file
- Remove redundant empty_baseline as it is no longer needed with the help of CMake configuration file