Magnificent7 / Hackathon
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers basicAPI.cpp Source File

basicAPI.cpp

00001 /*
00002  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #if !DEVICE_STORAGE
00019     #error [NOT_SUPPORTED] Storage not supported for this target
00020 #endif
00021 
00022 #ifndef AVOID_GREENTEA
00023 #include "greentea-client/test_env.h"
00024 #endif
00025 #include "utest/utest.h"
00026 #include "unity/unity.h"
00027 
00028 #include "storage_abstraction/Driver_Storage.h"
00029 
00030 #include <string.h>
00031 #include <inttypes.h>
00032 
00033 using namespace utest::v1;
00034 
00035 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
00036 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
00037 
00038 /* temporary buffer to hold data for testing. */
00039 static const unsigned BUFFER_SIZE = 16384;
00040 static uint8_t buffer[BUFFER_SIZE];
00041 
00042 /* forward declaration */
00043 void initializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation);
00044 
00045 /*
00046  * Most tests need some basic initialization of the driver before proceeding
00047  * with their operations.
00048  */
00049 static control_t preambleForBasicInitialization(void)
00050 {
00051     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00052 
00053     int32_t rc = drv->Initialize(initializationCompleteCallback);
00054     TEST_ASSERT(rc >= ARM_DRIVER_OK);
00055     if (rc == ARM_DRIVER_OK) {
00056         TEST_ASSERT_EQUAL(1,  capabilities.asynchronous_ops);
00057         return CaseTimeout(200) + CaseRepeatAll;
00058     } else {
00059         TEST_ASSERT(rc == 1);
00060         return CaseRepeatAll;
00061     }
00062 }
00063 
00064 template<typename T>
00065 static void verifyBytePattern(uint64_t addr, size_t sizeofData, T bytePattern)
00066 {
00067     /* we're limited by BUFFER_SIZE in how much we can verify in a single iteration;
00068      * the variable 'amountBeingVerified' captures the size being verified in each
00069      * iteration. */
00070     size_t amountBeingVerified = sizeofData;
00071     if (amountBeingVerified > BUFFER_SIZE) {
00072         amountBeingVerified = BUFFER_SIZE;
00073     }
00074     TEST_ASSERT((amountBeingVerified % sizeof(T)) == 0);
00075 
00076     while (sizeofData) {
00077         int32_t rc = drv->ReadData(addr, buffer, amountBeingVerified);
00078         TEST_ASSERT_EQUAL(amountBeingVerified, rc);
00079         for (size_t index = 0; index < amountBeingVerified / sizeof(T); index++) {
00080             // if (bytePattern != ((const T *)buffer)[index]) {
00081             //     printf("%u: expected %x, found %x\n", index, bytePattern, ((const T *)buffer)[index]);
00082             // }
00083             TEST_ASSERT_EQUAL(bytePattern, ((const T *)buffer)[index]);
00084         }
00085 
00086         sizeofData -= amountBeingVerified;
00087         addr       += amountBeingVerified;
00088     }
00089 }
00090 
00091 void test_getVersion()
00092 {
00093     ARM_DRIVER_VERSION version = drv->GetVersion();
00094 
00095     TEST_ASSERT_EQUAL(version.api, ARM_STORAGE_API_VERSION);
00096     TEST_ASSERT_EQUAL(version.drv, ARM_DRIVER_VERSION_MAJOR_MINOR(1,00));
00097 }
00098 
00099 void test_getCapabilities()
00100 {
00101     TEST_ASSERT(sizeof(ARM_STORAGE_CAPABILITIES) == sizeof(uint32_t));
00102 
00103     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00104     TEST_ASSERT_EQUAL(0, capabilities.reserved);
00105 }
00106 
00107 void test_getInfo()
00108 {
00109     ARM_STORAGE_INFO info = {};
00110     int32_t rc = drv->GetInfo(&info);
00111     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00112 
00113     TEST_ASSERT_EQUAL(0, info.security.reserved1);
00114     TEST_ASSERT_EQUAL(0, info.security.reserved2);
00115     TEST_ASSERT(info.total_storage > 0);
00116 }
00117 
00118 void initializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00119 {
00120     printf("init complete callback\n");
00121     TEST_ASSERT_EQUAL(1, status);
00122     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_INITIALIZE);
00123 
00124     Harness::validate_callback();
00125 }
00126 
00127 control_t test_initialize(const size_t call_count)
00128 {
00129     static const unsigned REPEAT_INSTANCES = 3;
00130     printf("in test_initialize with call_count %u\n", call_count);
00131 
00132     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00133 
00134     int32_t rc = drv->Initialize(initializationCompleteCallback);
00135     TEST_ASSERT(rc >= ARM_DRIVER_OK);
00136     if (rc == ARM_DRIVER_OK) {
00137         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00138         return (call_count < REPEAT_INSTANCES) ? (CaseTimeout(200) + CaseRepeatAll) : (control_t) CaseNext;
00139     }
00140 
00141     TEST_ASSERT(rc == 1);
00142     return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00143 }
00144 
00145 void uninitializationCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00146 {
00147     printf("uninit complete callback\n");
00148     TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
00149     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_UNINITIALIZE);
00150 
00151     Harness::validate_callback();
00152 }
00153 
00154 control_t test_uninitialize(const size_t call_count)
00155 {
00156     static const unsigned REPEAT_INSTANCES = 3;
00157     printf("in test_uninitialize with call_count %u\n", call_count);
00158 
00159     /* update the completion callback. */
00160     if (call_count == 1) {
00161         /* Achieve basic initialization for the driver before anything else. */
00162         return preambleForBasicInitialization();
00163     }
00164 
00165     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00166 
00167     int32_t rc = drv->Uninitialize();
00168     if (call_count > 2) {
00169         /* the driver should return some error for repeated un-initialization. */
00170         TEST_ASSERT(rc < ARM_DRIVER_OK);
00171         return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00172     }
00173     TEST_ASSERT(rc >= ARM_DRIVER_OK);
00174     if (rc == ARM_DRIVER_OK) {
00175         /* asynchronous operation */
00176         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00177         return CaseTimeout(200) + CaseRepeatAll;
00178     }
00179 
00180     /* synchronous operation */
00181     TEST_ASSERT(rc == 1);
00182     return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00183 }
00184 
00185 void powerControlCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00186 {
00187     printf("power control complete callback\n");
00188     TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
00189     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_POWER_CONTROL);
00190 
00191     Harness::validate_callback();
00192 }
00193 
00194 control_t test_powerControl(const size_t call_count)
00195 {
00196     static const unsigned REPEAT_INSTANCES = 2;
00197     printf("in test_powerControl with call_count %u\n", call_count);
00198 
00199     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00200 
00201     if (call_count == 1) {
00202         /* Achieve basic initialization for the driver before anything else. */
00203         return preambleForBasicInitialization();
00204     }
00205 
00206     /* Update the completion callback to 'powerControlCompleteCallback'. */
00207     if (call_count == 2) {
00208         int32_t rc = drv->Initialize(powerControlCompleteCallback);
00209         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00210                                * initialized by the previous iteration. */
00211     }
00212 
00213     int32_t rc = drv->PowerControl(ARM_POWER_FULL);
00214     if (rc == ARM_DRIVER_OK) {
00215         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00216         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00217     } else {
00218         TEST_ASSERT(rc == 1);
00219         return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00220     }
00221 }
00222 
00223 void readDataCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00224 {
00225     printf("ReadData complete callback\n");
00226     TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
00227     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_READ_DATA);
00228 
00229     Harness::validate_callback();
00230 }
00231 
00232 control_t test_readData(const size_t call_count)
00233 {
00234     static const unsigned REPEAT_INSTANCES = 5;
00235     printf("in test_readData with call_count %u\n", call_count);
00236 
00237     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00238 
00239     if (call_count == 1) {
00240         /* Achieve basic initialization for the driver before anything else. */
00241         return preambleForBasicInitialization();
00242     }
00243 
00244     /* Update the completion callback to 'readDataCompleteCallback'. */
00245     int32_t rc;
00246     if (call_count == 2) {
00247         rc = drv->Initialize(readDataCompleteCallback);
00248         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00249                                * initialized by the previous iteration. */
00250     }
00251 
00252     /* Get the first block. */
00253     ARM_STORAGE_BLOCK firstBlock;
00254     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00255     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00256     TEST_ASSERT(firstBlock.size > 0);
00257 
00258     ARM_STORAGE_INFO info;
00259     rc = drv->GetInfo(&info);
00260     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00261 
00262     TEST_ASSERT(info.program_unit <= BUFFER_SIZE);
00263     TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * info.program_unit);
00264 
00265     /* choose an increasing address for each iteration. */
00266     uint64_t addr = firstBlock.addr + (call_count - 1) * info.program_unit;
00267     size_t sizeofData = info.program_unit;
00268 
00269     rc = drv->ReadData(addr, buffer, sizeofData);
00270     if (rc == ARM_DRIVER_OK) {
00271         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00272         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00273     } else {
00274         TEST_ASSERT(rc > 0);
00275         return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00276     }
00277 }
00278 
00279 void programDataCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00280 {
00281     TEST_ASSERT(status >= 0);
00282     static unsigned programIteration = 0;
00283 
00284     static const uint32_t BYTE_PATTERN = 0xAA551122;
00285     ARM_STORAGE_BLOCK firstBlock;
00286     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00287     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00288 
00289     ARM_STORAGE_INFO info;
00290     int32_t rc = drv->GetInfo(&info);
00291     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00292 
00293     const uint64_t addr = firstBlock.addr + programIteration * firstBlock.attributes.erase_unit;
00294     size_t sizeofData = info.program_unit;
00295     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00296 
00297     TEST_ASSERT((operation == ARM_STORAGE_OPERATION_ERASE) || (operation == ARM_STORAGE_OPERATION_PROGRAM_DATA));
00298     if (operation == ARM_STORAGE_OPERATION_ERASE) {
00299         // printf("programming %u bytes at address %lu with pattern 0x%" PRIx32 "\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
00300 
00301         size_t sizeofData = info.program_unit;
00302         TEST_ASSERT(BUFFER_SIZE >= sizeofData);
00303         TEST_ASSERT((sizeofData % sizeof(uint32_t)) == 0);
00304         for (size_t index = 0; index < sizeofData / sizeof(uint32_t); index++) {
00305             ((uint32_t *)buffer)[index] = BYTE_PATTERN;
00306         }
00307 
00308         status = drv->ProgramData(addr, buffer, sizeofData);
00309         if (status < ARM_DRIVER_OK) {
00310             return; /* failure. this will trigger a timeout and cause test failure. */
00311         }
00312         if (status == ARM_DRIVER_OK) {
00313             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00314             return; /* We've successfully pended a programData operation; we'll have another
00315                      * invocation of this callback when programming completes. */
00316         }
00317     }
00318 
00319     /* We come here either because of completion for program-data or as a very
00320      * unlikely fall through from synchronous completion of program-data (above). */
00321 
00322 #ifndef __CC_ARM
00323     printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
00324 #endif
00325     verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
00326     ++programIteration;
00327 
00328     Harness::validate_callback();
00329 }
00330 
00331 control_t test_programDataUsingProgramUnit(const size_t call_count)
00332 {
00333     static const unsigned REPEAT_INSTANCES = 5;
00334     printf("in test_programDataUsingProgramUnit with call_count %u\n", call_count);
00335 
00336     if (call_count == 1) {
00337         /* Achieve basic initialization for the driver before anything else. */
00338         return preambleForBasicInitialization();
00339     }
00340 
00341     /* Get the first block. */
00342     ARM_STORAGE_BLOCK firstBlock;
00343     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00344     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00345     TEST_ASSERT(firstBlock.size > 0);
00346 
00347     ARM_STORAGE_INFO info;
00348     int32_t rc = drv->GetInfo(&info);
00349     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00350 
00351     TEST_ASSERT(info.program_unit <= firstBlock.attributes.erase_unit);
00352     TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * firstBlock.attributes.erase_unit);
00353 
00354     /* initialize the buffer to hold the pattern. */
00355     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00356 
00357     /* Update the completion callback to 'programDataCompleteCallback'. */
00358     if (call_count == 2) {
00359         int32_t rc = drv->Initialize(programDataCompleteCallback);
00360         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00361                                * initialized by the previous iteration. */
00362     }
00363 
00364     /* choose an increasing address for each iteration. */
00365     uint64_t addr = firstBlock.addr + (call_count - 2) * firstBlock.attributes.erase_unit;
00366 
00367     /* erase the sector at 'addr' */
00368     printf("erasing sector at addr %lu\n", (uint32_t)addr);
00369     rc = drv->Erase(addr, firstBlock.attributes.erase_unit);
00370     TEST_ASSERT(rc >= 0);
00371     if (rc == ARM_DRIVER_OK) {
00372         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00373         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00374     } else {
00375         TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, rc);
00376         verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00377 
00378         static const uint32_t BYTE_PATTERN = 0xAA551122;
00379         size_t sizeofData = info.program_unit;
00380         TEST_ASSERT(BUFFER_SIZE >= sizeofData);
00381         TEST_ASSERT((sizeofData % sizeof(uint32_t)) == 0);
00382         for (size_t index = 0; index < sizeofData / sizeof(uint32_t); index++) {
00383             ((uint32_t *)buffer)[index] = BYTE_PATTERN;
00384         }
00385 
00386         /* program the sector at addr */
00387         // printf("programming %u bytes at address %lu with pattern 0x%" PRIx32 "\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
00388         rc = drv->ProgramData((uint32_t)addr, buffer, sizeofData);
00389         if (rc == ARM_DRIVER_OK) {
00390             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00391             return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00392         } else {
00393             TEST_ASSERT(rc > 0);
00394 
00395             printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
00396             verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
00397 
00398             return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00399         }
00400     }
00401 }
00402 
00403 void programDataOptimalCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00404 {
00405     TEST_ASSERT(status >= 0);
00406     static unsigned programIteration = 0;
00407 
00408     static const uint8_t BYTE_PATTERN = 0xAA;
00409     ARM_STORAGE_BLOCK firstBlock;
00410     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00411     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00412     const uint64_t addr = firstBlock.addr + programIteration * firstBlock.attributes.erase_unit;
00413 
00414     ARM_STORAGE_INFO info;
00415     int32_t rc = drv->GetInfo(&info);
00416     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00417 
00418     size_t sizeofData = info.optimal_program_unit;
00419     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00420 
00421     TEST_ASSERT((operation == ARM_STORAGE_OPERATION_ERASE) || (operation == ARM_STORAGE_OPERATION_PROGRAM_DATA));
00422     if (operation == ARM_STORAGE_OPERATION_ERASE) {
00423 #ifndef __CC_ARM
00424         printf("programming %u bytes at address %lu with pattern 0x%x\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
00425 #endif
00426         size_t sizeofData = info.optimal_program_unit;
00427         TEST_ASSERT(BUFFER_SIZE >= sizeofData);
00428         memset(buffer, BYTE_PATTERN, sizeofData);
00429 
00430         status = drv->ProgramData(addr, buffer, sizeofData);
00431         if (status < ARM_DRIVER_OK) {
00432             return; /* failure. this will trigger a timeout and cause test failure. */
00433         }
00434         if (status == ARM_DRIVER_OK) {
00435             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00436             return; /* We've successfully pended a programData operation; we'll have another
00437                      * invocation of this callback when programming completes. */
00438         }
00439     }
00440 
00441     /* We come here either because of completion for program-data or as a very
00442      * unlikely fall through from synchronous completion of program-data (above). */
00443 
00444 #ifndef __CC_ARM
00445     printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
00446 #endif
00447     verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
00448     ++programIteration;
00449 
00450     Harness::validate_callback();
00451 }
00452 
00453 control_t test_programDataUsingOptimalProgramUnit(const size_t call_count)
00454 {
00455     static const unsigned REPEAT_INSTANCES = 5;
00456     printf("in test_programDataUsingOptimalProgramUnit with call_count %u\n", call_count);
00457 
00458     if (call_count == 1) {
00459         /* Achieve basic initialization for the driver before anything else. */
00460         return preambleForBasicInitialization();
00461     }
00462 
00463     /* Get the first block. */
00464     ARM_STORAGE_BLOCK firstBlock;
00465     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00466     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00467     TEST_ASSERT(firstBlock.size > 0);
00468 
00469     ARM_STORAGE_INFO info;
00470     int32_t rc = drv->GetInfo(&info);
00471     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00472 
00473     TEST_ASSERT(info.optimal_program_unit <= firstBlock.attributes.erase_unit);
00474     TEST_ASSERT(firstBlock.size >= (REPEAT_INSTANCES - 1) * firstBlock.attributes.erase_unit);
00475 
00476     /* initialize the buffer to hold the pattern. */
00477     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00478 
00479     /* Update the completion callback to 'programDataCompleteCallback'. */
00480     if (call_count == 2) {
00481         int32_t rc = drv->Initialize(programDataOptimalCompleteCallback);
00482         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00483                                * initialized by the previous iteration. */
00484     }
00485 
00486     /* choose an increasing address for each iteration. */
00487     uint64_t addr = firstBlock.addr + (call_count - 2) * firstBlock.attributes.erase_unit;
00488 
00489     /* erase the sector at 'addr' */
00490     printf("erasing sector at addr %lu\n", (uint32_t)addr);
00491     rc = drv->Erase(addr, firstBlock.attributes.erase_unit);
00492     TEST_ASSERT(rc >= 0);
00493     if (rc == ARM_DRIVER_OK) {
00494         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00495         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00496     } else {
00497         TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, rc);
00498         verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00499 
00500         static const uint8_t BYTE_PATTERN = 0xAA;
00501         size_t sizeofData = info.optimal_program_unit;
00502         TEST_ASSERT(BUFFER_SIZE >= sizeofData);
00503         memset(buffer, BYTE_PATTERN, sizeofData);
00504 
00505         /* program the sector at addr */
00506         printf("programming %u bytes at address %lu with pattern 0x%x\n", sizeofData, (uint32_t)addr, BYTE_PATTERN);
00507         rc = drv->ProgramData((uint32_t)addr, buffer, sizeofData);
00508         if (rc == ARM_DRIVER_OK) {
00509             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00510             return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00511         } else {
00512             TEST_ASSERT_EQUAL(sizeofData, rc);
00513 
00514             printf("verifying programmed sector at addr %lu\n", (uint32_t)addr);
00515             verifyBytePattern(addr, sizeofData, BYTE_PATTERN);
00516 
00517             return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00518         }
00519     }
00520 }
00521 
00522 void test_eraseWithInvalidParameters(void)
00523 {
00524     int32_t rc;
00525 
00526     rc = drv->Erase(0, 0);
00527     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00528 
00529     /* operate before the start of the first block. */
00530     ARM_STORAGE_BLOCK block;
00531     rc = drv->GetNextBlock(NULL, &block); /* get the first block */
00532     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00533     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&block));
00534     TEST_ASSERT(block.size > 0);
00535     rc = drv->Erase(block.addr - 1, BUFFER_SIZE);
00536     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00537 
00538     /* operate at an address past the end of the last block */
00539     uint64_t endAddr = block.addr + block.size;
00540     for (; ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
00541         endAddr = block.addr + block.size;
00542     }
00543     rc = drv->Erase(endAddr + 1, BUFFER_SIZE);
00544     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00545 
00546     ARM_STORAGE_INFO info;
00547     rc = drv->GetInfo(&info);
00548     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00549 
00550     drv->GetNextBlock(NULL, &block); /* get the first block */
00551     TEST_ASSERT(block.size >= block.attributes.erase_unit);
00552     TEST_ASSERT((block.size % block.attributes.erase_unit) == 0);
00553 
00554     rc = drv->Erase(block.addr + 1, block.attributes.erase_unit);
00555     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00556     rc = drv->Erase(block.addr, block.attributes.erase_unit - 1);
00557     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00558     rc = drv->Erase(block.addr, block.attributes.erase_unit + 1);
00559     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00560     rc = drv->Erase(block.addr, block.attributes.erase_unit / 2);
00561     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00562 }
00563 
00564 template<size_t ERASE_UNITS_PER_ITERATION>
00565 void eraseCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00566 {
00567     static unsigned eraseIteration = 0;
00568 #ifndef __CC_ARM
00569     printf("erase<%u> complete callback: iteration %u\n", ERASE_UNITS_PER_ITERATION, eraseIteration);
00570 #endif
00571     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_ERASE);
00572 
00573     /* test that the actual sector has been erased */
00574     ARM_STORAGE_BLOCK firstBlock;
00575     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00576     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00577     TEST_ASSERT_EQUAL(ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, status);
00578 
00579     const uint64_t addr = firstBlock.addr + eraseIteration * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit;
00580     ++eraseIteration;
00581 
00582 #ifndef __CC_ARM
00583     printf("testing erased sector at addr %lu\n", (uint32_t)addr);
00584 #endif
00585     verifyBytePattern(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00586 
00587     Harness::validate_callback();
00588 }
00589 
00590 template <size_t ERASE_UNITS_PER_ITERATION>
00591 control_t test_erase(const size_t call_count)
00592 {
00593     static const unsigned REPEAT_INSTANCES = 5;
00594     printf("in test_erase<%u> with call_count %u\n", ERASE_UNITS_PER_ITERATION, call_count);
00595 
00596     if (call_count == 1) {
00597         /* Achieve basic initialization for the driver before anything else. */
00598         return preambleForBasicInitialization();
00599     }
00600 
00601     /* Get the first block. */
00602     ARM_STORAGE_BLOCK firstBlock;
00603     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00604     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00605     TEST_ASSERT(firstBlock.size > 0);
00606     if (firstBlock.size < ((call_count - 1) * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit)) {
00607         printf("firstBlock isn't large enough to support instance %u of test_erase<%u>\n", call_count, ERASE_UNITS_PER_ITERATION);
00608         return CaseNext;
00609     }
00610 
00611     /* Update the completion callback to 'eraseCompleteCallback'. */
00612     if (call_count == 2) {
00613         int32_t rc = drv->Initialize(eraseCompleteCallback<ERASE_UNITS_PER_ITERATION>);
00614         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00615                                * initialized by the previous iteration. */
00616     }
00617 
00618     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00619 
00620     /* choose an increasing address for each iteration. */
00621     uint64_t addr = firstBlock.addr + (call_count - 2) * ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit;
00622 
00623     printf("erasing %lu bytes at addr %lu\n", (ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit), (uint32_t)addr);
00624     int32_t rc = drv->Erase(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit);
00625     if (rc == ARM_DRIVER_OK) {
00626         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00627         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00628     } else {
00629         TEST_ASSERT_EQUAL(ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, rc);
00630 
00631         /* test that the actual sector has been erased */
00632         printf("testing erased sector at addr %lu\n", (uint32_t)addr);
00633         verifyBytePattern(addr, ERASE_UNITS_PER_ITERATION * firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00634 
00635         return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00636     }
00637 }
00638 
00639 void eraseChipCompleteCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00640 {
00641 #ifndef __CC_ARM
00642     printf("eraseChip complete callback\n");
00643 #endif
00644     TEST_ASSERT_EQUAL(status, ARM_DRIVER_OK);
00645     TEST_ASSERT_EQUAL(operation, ARM_STORAGE_OPERATION_ERASE_ALL);
00646 
00647     ARM_STORAGE_BLOCK firstBlock;
00648     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00649     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00650     uint64_t addr = firstBlock.addr;
00651 
00652     /* test that the flash has been erased */
00653 #ifndef __CC_ARM
00654     printf("testing erased chip\n");
00655 #endif
00656     unsigned index = 0;
00657     static const unsigned MAX_VERIFY_ITERATIONS = 5;
00658     while ((index < MAX_VERIFY_ITERATIONS) && (addr < (firstBlock.addr + firstBlock.size))) {
00659         // printf("testing erased chip at addr %lu\n", (uint32_t)addr);
00660         verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00661 
00662         index++;
00663         addr += firstBlock.attributes.erase_unit;
00664     }
00665 
00666     Harness::validate_callback();
00667 }
00668 
00669 control_t test_eraseAll(const size_t call_count)
00670 {
00671     static const unsigned REPEAT_INSTANCES = 5;
00672     printf("in test_eraseAll with call_count %u\n", call_count);
00673 
00674     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00675     if (!capabilities.erase_all) {
00676         printf("chip erase not supported on this flash\n");
00677         return CaseNext;
00678     }
00679 
00680     if (call_count == 1) {
00681         /* Achieve basic initialization for the driver before anything else. */
00682         return preambleForBasicInitialization();
00683     }
00684 
00685     /* Update the completion callback to 'eraseChipCompleteCallback'. */
00686     if (call_count == 2) {
00687         int32_t rc = drv->Initialize(eraseChipCompleteCallback);
00688         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00689                                * initialized by the previous iteration. */
00690     }
00691 
00692     /* Get the first block. */
00693     ARM_STORAGE_BLOCK firstBlock;
00694     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00695     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00696     TEST_ASSERT(firstBlock.size > 0);
00697     uint64_t addr = firstBlock.addr;
00698     printf("erasing chip\n");
00699 
00700     int32_t rc = drv->EraseAll();
00701     if (rc == ARM_DRIVER_OK) {
00702         TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00703         return (call_count < REPEAT_INSTANCES) ? CaseTimeout(200) + CaseRepeatAll: CaseTimeout(200);
00704     } else {
00705         TEST_ASSERT(rc == 1);
00706 
00707         /* test that the flash has been erased */
00708         unsigned index = 0;
00709         static const unsigned MAX_VERIFY_ITERATIONS = 5;
00710         while ((index < MAX_VERIFY_ITERATIONS) && (addr < (firstBlock.addr + firstBlock.size))) {
00711             printf("testing erased chip at addr %lu\n", (uint32_t)addr);
00712             verifyBytePattern(addr, firstBlock.attributes.erase_unit, (uint8_t)0xFF);
00713 
00714             index++;
00715             addr += firstBlock.attributes.erase_unit;
00716         }
00717 
00718         return (call_count < REPEAT_INSTANCES) ? CaseRepeatAll : CaseNext;
00719     }
00720 }
00721 
00722 void test_programDataWithInvalidParameters(void)
00723 {
00724     int32_t rc;
00725 
00726     rc = drv->ProgramData(0, NULL, 0);
00727     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00728     rc = drv->ProgramData(0, buffer, 0);
00729     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00730     rc = drv->ProgramData(0, NULL, BUFFER_SIZE);
00731     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00732 
00733     /* operate before the start of the first block. */
00734     ARM_STORAGE_BLOCK block;
00735     rc = drv->GetNextBlock(NULL, &block); /* get the first block */
00736     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00737     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&block));
00738     TEST_ASSERT(block.size > 0);
00739     rc = drv->ProgramData(block.addr - 1, buffer, BUFFER_SIZE);
00740     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00741 
00742     /* operate at an address past the end of the last block */
00743     uint64_t endAddr = block.addr + block.size;
00744     for (; ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
00745         endAddr = block.addr + block.size;
00746     }
00747     rc = drv->ProgramData(endAddr + 1, buffer, BUFFER_SIZE);
00748     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00749 
00750     ARM_STORAGE_INFO info;
00751     rc = drv->GetInfo(&info);
00752     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00753     if (info.program_unit <= 1) {
00754         return; /* if program_unit is 1 (or 0), we can't proceed with any alignment tests */
00755     }
00756 
00757     drv->GetNextBlock(NULL, &block); /* get the first block */
00758 
00759     TEST_ASSERT(block.size >= info.program_unit);
00760 
00761     rc = drv->ProgramData(block.addr + 1, buffer, info.program_unit);
00762     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00763     rc = drv->ProgramData(block.addr, buffer, info.program_unit - 1);
00764     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00765     rc = drv->ProgramData(block.addr, buffer, info.program_unit + 1);
00766     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00767     rc = drv->ProgramData(block.addr, buffer, info.program_unit / 2);
00768     TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_PARAMETER, rc);
00769 }
00770 
00771 template <size_t N_UNITS>
00772 void programDataWithMultipleProgramUnitsCallback(int32_t status, ARM_STORAGE_OPERATION operation)
00773 {
00774     TEST_ASSERT(status >= ARM_DRIVER_OK);
00775 
00776     ARM_STORAGE_BLOCK firstBlock;
00777     drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00778     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00779     TEST_ASSERT(firstBlock.size > 0);
00780 
00781     ARM_STORAGE_INFO info;
00782     int32_t rc = drv->GetInfo(&info);
00783     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00784 
00785     ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00786 
00787     size_t rangeNeededForTest = (N_UNITS * info.program_unit);
00788     /* round-up range to the nearest erase_unit */
00789     rangeNeededForTest = ((rangeNeededForTest + firstBlock.attributes.erase_unit - 1) / firstBlock.attributes.erase_unit) * firstBlock.attributes.erase_unit;
00790 
00791     static const uint32_t BYTE_PATTERN = 0xABCDEF00;
00792 
00793     if (operation == ARM_STORAGE_OPERATION_ERASE) {
00794         TEST_ASSERT_EQUAL(rangeNeededForTest, status);
00795         TEST_ASSERT((N_UNITS * info.program_unit) <= BUFFER_SIZE);
00796 
00797         /* setup byte pattern in buffer */
00798         if (info.program_unit >= sizeof(BYTE_PATTERN)) {
00799             for (size_t index = 0; index < ((N_UNITS * info.program_unit) / sizeof(BYTE_PATTERN)); index++) {
00800                 ((uint32_t *)buffer)[index] = BYTE_PATTERN;
00801             }
00802         } else {
00803            for (size_t index = 0; index < ((N_UNITS * info.program_unit)); index++) {
00804                buffer[index] = ((const uint8_t *)&BYTE_PATTERN)[0];
00805            }
00806         }
00807 
00808 #ifndef __CC_ARM
00809         printf("Callback: programming %lu bytes at address %lu with pattern 0x%lx\n", (N_UNITS * info.program_unit), (uint32_t)firstBlock.addr, BYTE_PATTERN);
00810 #endif
00811         rc = drv->ProgramData(firstBlock.addr, buffer, (N_UNITS * info.program_unit));
00812         TEST_ASSERT(rc >= ARM_DRIVER_OK);
00813         if (rc == ARM_DRIVER_OK) {
00814             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00815             return; /* We've successfully pended a programData operation; we'll have another
00816                      * invocation of this callback when programming completes. */
00817         }
00818 
00819         status = rc;
00820     }
00821 
00822     TEST_ASSERT_EQUAL((N_UNITS * info.program_unit), status);
00823 
00824 #ifndef __CC_ARM
00825     printf("Callback: verifying programmed sector at addr %lu\n", (uint32_t)firstBlock.addr);
00826 #endif
00827     if (info.program_unit >= sizeof(BYTE_PATTERN)) {
00828         verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), BYTE_PATTERN);
00829     } else {
00830         verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), ((const uint8_t *)&BYTE_PATTERN)[0]);
00831     }
00832 
00833     Harness::validate_callback();
00834 }
00835 
00836 template<size_t N_UNITS>
00837 control_t test_programDataWithMultipleProgramUnits(const size_t call_count)
00838 {
00839     int32_t rc;
00840     printf("in test_programDataWithMultipleProgramUnits<%u> with call_count %u\n", N_UNITS, call_count);
00841 
00842     if (call_count == 1) {
00843         /* Achieve basic initialization for the driver before anything else. */
00844         return preambleForBasicInitialization();
00845     }
00846 
00847     /* Update the completion callback to 'programDataWithMultipleProgramUnitsCallback'. */
00848     if (call_count == 2) {
00849         rc = drv->Initialize(programDataWithMultipleProgramUnitsCallback<N_UNITS>);
00850         TEST_ASSERT(rc == 1); /* Expect synchronous completion of initialization; the system must have been
00851                                * initialized by the previous iteration. */
00852 
00853         ARM_STORAGE_BLOCK firstBlock;
00854         drv->GetNextBlock(NULL, &firstBlock); /* get first block */
00855         TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00856         TEST_ASSERT(firstBlock.size > 0);
00857 
00858         ARM_STORAGE_INFO info;
00859         int32_t rc = drv->GetInfo(&info);
00860         TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00861 
00862         ARM_STORAGE_CAPABILITIES capabilities = drv->GetCapabilities();
00863 
00864         size_t rangeNeededForTest = (N_UNITS * info.program_unit);
00865         /* round-up range to the nearest erase_unit */
00866         rangeNeededForTest = ((rangeNeededForTest + firstBlock.attributes.erase_unit - 1) / firstBlock.attributes.erase_unit) * firstBlock.attributes.erase_unit;
00867         if (firstBlock.size < rangeNeededForTest) {
00868             printf("first block not large enough; rangeNeededForTest: %u\n", rangeNeededForTest);
00869             return CaseNext; /* first block isn't large enough for the intended operation */
00870         }
00871 
00872         if (rangeNeededForTest > BUFFER_SIZE) {
00873             printf("buffer (%u) not large enough; rangeNeededForTest: %u\n", BUFFER_SIZE, rangeNeededForTest);
00874             return CaseNext;
00875         }
00876 
00877         // printf("erasing %u bytes at addr %lu\n", rangeNeededForTest, (uint32_t)firstBlock.addr);
00878         rc = drv->Erase(firstBlock.addr, rangeNeededForTest);
00879         TEST_ASSERT(rc >= 0);
00880         if (rc == ARM_DRIVER_OK) {
00881             TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00882             return CaseTimeout(500);
00883         } else {
00884             TEST_ASSERT_EQUAL(rangeNeededForTest, rc);
00885 
00886             /* setup byte pattern in buffer */
00887             static const uint32_t BYTE_PATTERN = 0xABCDEF00;
00888             if (info.program_unit >= sizeof(BYTE_PATTERN)) {
00889                 for (size_t index = 0; index < ((N_UNITS * info.program_unit) / sizeof(BYTE_PATTERN)); index++) {
00890                     ((uint32_t *)buffer)[index] = BYTE_PATTERN;
00891                 }
00892             } else {
00893                for (size_t index = 0; index < ((N_UNITS * info.program_unit)); index++) {
00894                    buffer[index] = ((const uint8_t *)&BYTE_PATTERN)[0];
00895                }
00896             }
00897 
00898             printf("programming %lu bytes at address %lu with pattern 0x%lx\n", (N_UNITS * info.program_unit), (uint32_t)firstBlock.addr, BYTE_PATTERN);
00899             rc = drv->ProgramData(firstBlock.addr, buffer, (N_UNITS * info.program_unit));
00900             TEST_ASSERT(rc >= 0);
00901             if (rc == ARM_DRIVER_OK) {
00902                 TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
00903                 return CaseTimeout(500);
00904             } else {
00905                 TEST_ASSERT_EQUAL((N_UNITS * info.program_unit), rc);
00906 
00907                 printf("verifying programmed sector at addr %lu\n", (uint32_t)firstBlock.addr);
00908                 if (info.program_unit >= sizeof(BYTE_PATTERN)) {
00909                     verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), BYTE_PATTERN);
00910                 } else {
00911                     verifyBytePattern(firstBlock.addr, (N_UNITS * info.program_unit), ((const uint8_t *)&BYTE_PATTERN)[0]);
00912                 }
00913 
00914                 return CaseNext;
00915             }
00916         }
00917     }
00918 
00919     return CaseNext;
00920 }
00921 
00922 #ifndef AVOID_GREENTEA
00923 // Custom setup handler required for proper Greentea support
00924 utest::v1::status_t greentea_setup(const size_t number_of_cases)
00925 {
00926     GREENTEA_SETUP(60, "default_auto");
00927     // Call the default reporting function
00928     return greentea_test_setup_handler(number_of_cases);
00929 }
00930 #else
00931 status_t default_setup(const size_t)
00932 {
00933     return STATUS_CONTINUE;
00934 }
00935 #endif
00936 
00937 // Specify all your test cases here
00938 Case cases[] = {
00939     Case("get version",                              test_getVersion),
00940     Case("get capabilities",                         test_getCapabilities),
00941     Case("get info",                                 test_getInfo),
00942     Case("initialize",                               test_initialize),
00943     Case("uninitialize",                             test_uninitialize),
00944     Case("power control",                            test_powerControl),
00945     Case("erase all",                                test_eraseAll),
00946     Case("read data",                                test_readData),
00947     Case("erase with invalid parameters",            test_eraseWithInvalidParameters),
00948     Case("erase single unit",                        test_erase<1>),
00949     Case("erase two units",                          test_erase<2>),
00950     Case("erase four units",                         test_erase<4>),
00951     Case("erase eight units",                        test_erase<8>),
00952     Case("program data with invalid parameters",     test_programDataWithInvalidParameters),
00953     Case("program data using program_unit",          test_programDataUsingProgramUnit),
00954     Case("program data using optimal_program_unit",  test_programDataUsingOptimalProgramUnit),
00955     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1>),
00956     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<2>),
00957     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<7>),
00958     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<8>),
00959     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<9>),
00960     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<31>),
00961     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<32>),
00962     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<33>),
00963     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<127>),
00964     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<128>),
00965     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<129>),
00966     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1023>),
00967     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1024>),
00968     Case("program data with multiple program units", test_programDataWithMultipleProgramUnits<1025>),
00969 };
00970 
00971 // Declare your test specification with a custom setup handler
00972 #ifndef AVOID_GREENTEA
00973 Specification specification(greentea_setup, cases);
00974 #else
00975 Specification specification(default_setup, cases);
00976 #endif
00977 
00978 int main(int argc, char** argv)
00979 {
00980     // Run the test specification
00981     Harness::run(specification);
00982 }