diff --git a/test/mfs/.cproject b/test/mfs/.cproject
new file mode 100644
index 000000000..896066e66
--- /dev/null
+++ b/test/mfs/.cproject
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/mfs/.project b/test/mfs/.project
new file mode 100644
index 000000000..6485f730e
--- /dev/null
+++ b/test/mfs/.project
@@ -0,0 +1,32 @@
+
+
+ MFS Tests Generator
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+ com.st.tools.spc5.spc5StudioPatchBuilder
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+ com.st.tools.spc5.spc5StudioNature
+
+
diff --git a/test/mfs/.spc5project b/test/mfs/.spc5project
new file mode 100644
index 000000000..104c5aa76
--- /dev/null
+++ b/test/mfs/.spc5project
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/test/mfs/config.fmpp b/test/mfs/config.fmpp
new file mode 100644
index 000000000..62a3641e2
--- /dev/null
+++ b/test/mfs/config.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../tools/ftl/processors/unittest
+outputRoot: source
+dataRoot: .
+
+freemarkerLinks: {
+ ftllibs: ../../tools/ftl/libs
+}
+
+data : {
+ xml:xml (
+ configuration.xml
+ {
+ }
+ )
+}
diff --git a/test/mfs/configuration.xml b/test/mfs/configuration.xml
new file mode 100644
index 000000000..e51d568f4
--- /dev/null
+++ b/test/mfs/configuration.xml
@@ -0,0 +1,862 @@
+
+
+
+ Test Specification for ChibiOS/HAL MFS Complex Driver.
+
+
+
+
+
+
+
+
+ ChibiOS/HAL MFS Test Suite.
+
+
+
+
+
+ Test suite for ChibiOS/HAL MFS. The purpose of this suite is to perform unit tests on the MFS module and to converge to 100% code coverage through successive improvements.
+
+
+
+
+ nil_
+
+
+
+
+
+
+
+
+
+
+
+ Internal Tests
+
+
+ Functional tests.
+
+
+ The APIs are tested for functionality, correct cases and expected error cases are tested.
+
+
+
+#include "key_storage.h"
+
+static const uint8_t pattern1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static const uint8_t pattern2[] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
+};
+
+static const uint8_t pattern3[] = {
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
+};
+
+static const uint8_t pattern512[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
+};]]>
+
+
+
+
+ Testing ksInit() behavior.
+
+
+ The initialization function is tested. This function can fail only in case of Flash Array failures or in case of unexpected internal errors.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Erasing the flash array using a low level function.
+
+
+
+
+
+
+
+
+
+
+ Calling ksInit() on an uninitialized flash array, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Calling ksInit() on a newly initialized flash array, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+
+
+ Checking for non existing keys.
+
+
+ The keys space is explored with an initialized but empty keys storage, no key should exist.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Exploring the keys space, KS_KEY_NOT_FOUND is expected for each key.
+
+
+
+
+
+
+
+
+
+
+
+
+ Creating, updating and erasing a key.
+
+
+ A key is created, updated several times with different payloads and finally erased.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The key must not already exists, KS_KEY_NOT_FOUND is expected.
+
+
+
+
+
+
+
+
+
+
+ Creating the key then retrieving it again, KS_KEY_NOT_FOUND is expected, key content and size are compared with the original.
+
+
+
+
+
+
+
+
+
+
+ Updating the key then retrieving it again, KS_NOERROR is expected, key content and size are compared with the original.
+
+
+
+
+
+
+
+
+
+
+ Updating the key again with an unaligned key size then retrieving it again, KS_NOERROR is expected, key content and size are compared with the original.
+
+
+
+
+
+
+
+
+
+
+ Erasing the key the then retrieving it, KS_NOERROR is expected on erase, KS_KEY_NOT_FOUND is expected on retrieve.
+
+
+
+
+
+
+
+
+
+
+
+
+ Erasing the whole storage.
+
+
+ The key storage is erased and re-initialized.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Creating keys 0, 1 and 2, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Erasing storage and verify that the keys have been removed, KS_NOERROR is expected on erase, KS_KEY_NOT_FOUND is expected on retrieve.
+
+
+
+
+
+
+
+
+
+
+
+
+ Testing storage size limit.
+
+
+ The storage is entirely filled with different keys and the final error is tested.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Creating one more key, should fail, KS_OUT_OF_MEM is expected.
+
+
+
+
+
+
+
+
+
+
+ Adding a smaller key to fill the final gap. A reinitialization is performed and KS_NOERROR is expected.
+
+
+
+
+
+ = sizeof(kskeyheader_t), "not enough space");
+test_assert((remaining & KS_LLD_PAGE_SIZE) == 0, "unaligned space");
+
+if (remaining > sizeof(kskeyheader_t) * 2) {
+ error = ksWriteKey(KS_CFG_NUM_KEYS - 1,
+ remaining - (sizeof(kskeyheader_t) * 2),
+ pattern512);
+ test_assert(error == KS_NOERROR, "error filling remaining space");
+}
+else {
+ if (remaining == sizeof(kskeyheader_t) * 2) {
+ error = ksEraseKey(1);
+ test_assert(error == KS_NOERROR, "error filling remaining space");
+ }
+ error = ksEraseKey(0);
+ test_assert(error == KS_NOERROR, "error filling remaining space");
+}
+
+remaining = KS_LLD_BLOCK0_ADDRESS + KS_LLD_BLOCKS_SIZE - (size_t)ks.free_next;
+test_assert(remaining == 0, "remaining space not zero");
+
+ksDeinit();
+error = ksInit();
+test_assert(error == KS_NOERROR, "initialization error");]]>
+
+
+
+
+
+
+ Testing garbage collection by writing.
+
+
+ The garbage collection procedure is triggeredby a write operation and the state of both banks is checked.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Erasing one key in the middle, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Writing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.
+
+
+
+
+
+ fields.instance == 1, "not first instance");
+error = ksWriteKey(16, sizeof(pattern512), pattern512);
+test_assert(error == KS_WARNING, "error creating the key");
+test_assert(ks.header->fields.instance == 2, "not second instance");
+error = ksGetKey(16, &size, &keyp);
+test_assert(error == KS_NOERROR, "key not found");
+test_assert(size == sizeof(pattern512), "unexpected key length");
+test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+test_assert(ks.block == KS_BLOCK1, "unexpected block");
+test_assert(ks_lld_is_block_erased(KS_BLOCK0) == true, "block 0 not erased");]]>
+
+
+
+
+ Checking for all keys in the new bank, KS_NOERROR is expected for each key.
+
+
+
+
+
+
+
+
+
+
+ Erasing one key in the middle, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Writing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.
+
+
+
+
+
+ fields.instance == 2, "not second instance");
+error = ksWriteKey(16, sizeof(pattern512), pattern512);
+test_assert(error == KS_WARNING, "error creating the key");
+test_assert(ks.header->fields.instance == 3, "not third instance");
+error = ksGetKey(16, &size, &keyp);
+test_assert(error == KS_NOERROR, "key not found");
+test_assert(size == sizeof(pattern512), "unexpected key length");
+test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+test_assert(ks.block == KS_BLOCK0, "unexpected block");
+test_assert(ks_lld_is_block_erased(KS_BLOCK1) == true, "block 0 not erased");]]>
+
+
+
+
+ Checking for all keys in the new bank, KS_NOERROR is expected for each key.
+
+
+
+
+
+
+
+
+
+
+
+
+ Testing garbage collection by erasing
+
+
+ The garbage collection procedure is triggeredby an erase operation and the state of both banks is checked.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Erase keys until the flash bank is filled entirely.
+
+
+
+
+
+
+
+
+
+
+ Erasing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.
+
+
+
+
+
+ fields.instance == 1, "not first instance");
+error = ksEraseKey(16);
+test_assert(error == KS_WARNING, "error erasing the key");
+test_assert(ks.header->fields.instance == 2, "not second instance");
+error = ksGetKey(16, &size, &keyp);
+test_assert(error == KS_KEY_NOT_FOUND, "key not erased");
+test_assert(ks.block == KS_BLOCK1, "unexpected block");
+test_assert(ks_lld_is_block_erased(KS_BLOCK0) == true, "block 0 not erased");]]>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/mfs/nil_test.mk b/test/mfs/nil_test.mk
new file mode 100644
index 000000000..c49541d73
--- /dev/null
+++ b/test/mfs/nil_test.mk
@@ -0,0 +1,9 @@
+# List of all the ChibiOS/NIL test files.
+TESTSRC += ${CHIBIOS}/test/nil/source/test/nil_test_root.c \
+ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_001.c \
+ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_002.c \
+ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_003.c \
+ ${CHIBIOS}/test/nil/source/test/nil_test_sequence_004.c
+
+# Required include directories
+TESTINC += ${CHIBIOS}/test/nil/source/test
diff --git a/test/mfs/patch.xml b/test/mfs/patch.xml
new file mode 100644
index 000000000..879b2ed23
--- /dev/null
+++ b/test/mfs/patch.xml
@@ -0,0 +1,5 @@
+
+
+
+
+