joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers strategy.c Source File

strategy.c

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 #include "flash-journal-strategy-sequential/flash_journal_private.h"
00019 #include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h"
00020 #include "support_funcs.h"
00021 #include <string.h>
00022 #include <stdio.h>
00023 
00024 SequentialFlashJournal_t *activeJournal;
00025 
00026 /* forward declarations */
00027 void mtdHandler(int32_t status, ARM_STORAGE_OPERATION operation);
00028 
00029 static inline int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP)
00030 {
00031     /* fetch MTD's INFO */
00032     ARM_STORAGE_INFO mtdInfo;
00033     int32_t rc = mtd->GetInfo(&mtdInfo);
00034     if (rc != ARM_DRIVER_OK) {
00035         return JOURNAL_STATUS_STORAGE_API_ERROR;
00036     }
00037     *capacityP = mtdInfo.total_storage;
00038 
00039     return JOURNAL_STATUS_OK;
00040 }
00041 
00042 static inline int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
00043 {
00044     if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
00045         return JOURNAL_STATUS_PARAMETER;
00046     }
00047     if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
00048         return JOURNAL_STATUS_NOT_INITIALIZED;
00049     }
00050     if (journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
00051         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00052     }
00053     // printf("read sanity checks: totalDataRead = %lu, sizeofJournaledBlob = %lu\n", (uint32_t)journal->read.totalDataRead, (uint32_t)journal->info.sizeofJournaledBlob);
00054     if ((journal->info.sizeofJournaledBlob == 0) || (journal->read.totalDataRead == journal->info.sizeofJournaledBlob)) {
00055         journal->read.totalDataRead = 0;
00056         return JOURNAL_STATUS_EMPTY;
00057     }
00058 
00059     return JOURNAL_STATUS_OK;
00060 }
00061 
00062 static inline int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
00063 {
00064     if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
00065         return JOURNAL_STATUS_PARAMETER;
00066     }
00067     if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
00068         return JOURNAL_STATUS_NOT_INITIALIZED;
00069     }
00070     if ((journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) && (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY)) {
00071         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00072     }
00073     if (journal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
00074         if (sizeofBlob > journal->info.capacity) {
00075             return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
00076         }
00077     } else if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00078         if (journal->log.offset + sizeofBlob > journal->log.tailOffset) {
00079             return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
00080         }
00081     }
00082 
00083     return JOURNAL_STATUS_OK;
00084 }
00085 
00086 static inline int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal)
00087 {
00088     if (journal == NULL) {
00089         return JOURNAL_STATUS_PARAMETER;
00090     }
00091     if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00092         if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00093             return JOURNAL_STATUS_ERROR;
00094         }
00095         if ((journal->log.offset          == ARM_STORAGE_INVALID_OFFSET) ||
00096             (journal->log.tailOffset      == ARM_STORAGE_INVALID_OFFSET) ||
00097             (journal->log.tailOffset       < journal->log.offset)        ||
00098             (journal->log.tail.sizeofBlob == 0)                          ||
00099             (journal->log.tail.sizeofBlob  > journal->info.capacity)) {
00100             return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00101         }
00102     }
00103 
00104     return JOURNAL_STATUS_OK;
00105 }
00106 
00107 int32_t flashJournalStrategySequential_initialize(FlashJournal_t           *_journal,
00108                                                   ARM_DRIVER_STORAGE       *mtd,
00109                                                   const FlashJournal_Ops_t *ops,
00110                                                   FlashJournal_Callback_t   callback)
00111 {
00112     int32_t rc;
00113 
00114     SequentialFlashJournal_t *journal;
00115     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00116     journal->state          = SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED;
00117 
00118     /* fetch MTD's total capacity */
00119     uint64_t mtdCapacity;
00120     if ((rc = mtdGetTotalCapacity(mtd, &mtdCapacity)) != JOURNAL_STATUS_OK) {
00121         return rc;
00122     }
00123     ARM_STORAGE_INFO mtdInfo;
00124     if ((rc = mtd->GetInfo(&mtdInfo)) != ARM_DRIVER_OK) {
00125         return JOURNAL_STATUS_STORAGE_API_ERROR;
00126     }
00127 
00128     /* initialize the journal structure */
00129     memcpy(&journal->ops, ops, sizeof(FlashJournal_Ops_t));
00130     journal->mtd               = mtd;
00131     journal->mtdCapabilities   = mtd->GetCapabilities(); /* fetch MTD's capabilities */
00132     journal->sequentialSkip    = mtdCapacity / SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS;
00133     journal->info.capacity     = journal->sequentialSkip - (sizeof(SequentialFlashJournalLogHead_t) + sizeof(SequentialFlashJournalLogTail_t)); /* effective capacity */
00134     journal->info.program_unit = mtdInfo.program_unit;
00135     journal->callback          = callback;
00136     journal->prevCommand       = FLASH_JOURNAL_OPCODE_INITIALIZE;
00137 
00138     /* initialize MTD */
00139     ARM_STORAGE_CAPABILITIES mtdCaps = mtd->GetCapabilities();
00140     rc = mtd->Initialize(mtdHandler);
00141     if (rc < ARM_DRIVER_OK) {
00142         memset(journal, 0, sizeof(FlashJournal_t));
00143         return JOURNAL_STATUS_STORAGE_API_ERROR;
00144     }
00145     if ((mtdCaps.asynchronous_ops) && (rc == ARM_DRIVER_OK)) {
00146         return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */
00147     }
00148 
00149     if ((rc = discoverLatestLoggedBlob(journal)) != JOURNAL_STATUS_OK) {
00150         return rc;
00151     }
00152 
00153     return 1; /* synchronous completion */
00154 }
00155 
00156 FlashJournal_Status_t flashJournalStrategySequential_getInfo(FlashJournal_t *_journal, FlashJournal_Info_t *infoP)
00157 {
00158     SequentialFlashJournal_t *journal;
00159     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00160 
00161     memcpy(infoP, &journal->info, sizeof(FlashJournal_Info_t));
00162     return JOURNAL_STATUS_OK;
00163 }
00164 
00165 int32_t flashJournalStrategySequential_read(FlashJournal_t *_journal, void *blob, size_t sizeofBlob)
00166 {
00167     SequentialFlashJournal_t *journal;
00168     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00169 
00170     int32_t rc;
00171     if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) {
00172         return rc;
00173     }
00174 
00175     journal->read.blob       = blob;
00176     journal->read.sizeofBlob = sizeofBlob;
00177 
00178     if ((journal->prevCommand != FLASH_JOURNAL_OPCODE_READ_BLOB) || (journal->read.totalDataRead == 0)) {
00179         journal->read.offset        = journal->mtdStartOffset
00180                                       + (journal->currentBlobIndex * journal->sequentialSkip)
00181                                       + sizeof(SequentialFlashJournalLogHead_t);
00182         journal->read.totalDataRead = 0;
00183     } else {
00184         /* journal->read.offset is already set from the previous read execution */
00185         // printf("flashJournalStrategySequential_read: continuing read of %lu from offset %lu\n", sizeofBlob, (uint32_t)journal->read.offset);
00186     }
00187     journal->read.dataBeingRead    = blob;
00188     journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.totalDataRead) < sizeofBlob) ?
00189                                         (journal->info.sizeofJournaledBlob - journal->read.totalDataRead) : sizeofBlob;
00190     // printf("amount left to read %u\n", journal->read.amountLeftToRead);
00191 
00192     journal->state       = SEQUENTIAL_JOURNAL_STATE_READING;
00193     journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB;
00194     return flashJournalStrategySequential_read_progress();
00195 }
00196 
00197 int32_t flashJournalStrategySequential_log(FlashJournal_t *_journal, const void *blob, size_t size)
00198 {
00199     SequentialFlashJournal_t *journal;
00200     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00201 
00202     int32_t rc;
00203     if ((rc = flashJournalStrategySequential_log_sanityChecks(journal, blob, size)) != JOURNAL_STATUS_OK) {
00204         return rc;
00205     }
00206 
00207     journal->log.blob       = blob;
00208     journal->log.sizeofBlob = size;
00209 
00210     if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00211         uint32_t logBlobIndex = journal->currentBlobIndex + 1;
00212         if (logBlobIndex == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) {
00213             logBlobIndex = 0;
00214         }
00215         journal->log.eraseOffset = journal->mtdStartOffset + (logBlobIndex * journal->sequentialSkip);
00216 
00217         /* ensure that the request is at least as large as the minimum program unit */
00218         if (size < journal->info.program_unit) {
00219             return JOURNAL_STATUS_SMALL_LOG_REQUEST;
00220         }
00221 
00222         journal->state       = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE; /* start with erasing the log region */
00223         journal->prevCommand = FLASH_JOURNAL_OPCODE_LOG_BLOB;
00224     } else {
00225         journal->log.dataBeingLogged = blob;
00226         journal->log.amountLeftToLog = size;
00227     }
00228 
00229     return flashJournalStrategySequential_log_progress();
00230 }
00231 
00232 int32_t flashJournalStrategySequential_commit(FlashJournal_t *_journal)
00233 {
00234     SequentialFlashJournal_t *journal;
00235     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00236 
00237     int32_t rc;
00238     if ((rc = flashJournalStrategySequential_commit_sanityChecks(journal)) != JOURNAL_STATUS_OK) {
00239         return rc;
00240     }
00241 
00242     if (journal->prevCommand == FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00243         journal->log.offset          = journal->log.tailOffset;
00244         journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail;
00245         journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t);
00246         journal->state               = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL;
00247     } else {
00248         uint32_t logBlobIndex = journal->currentBlobIndex + 1;
00249         if (logBlobIndex == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) {
00250             logBlobIndex = 0;
00251         }
00252         journal->log.eraseOffset = journal->mtdStartOffset + (logBlobIndex * journal->sequentialSkip);
00253         journal->state           = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE;
00254     }
00255 
00256     journal->prevCommand = FLASH_JOURNAL_OPCODE_COMMIT;
00257     return flashJournalStrategySequential_log_progress();
00258 }
00259 
00260 int32_t flashJournalStrategySequential_reset(FlashJournal_t *_journal)
00261 {
00262     SequentialFlashJournal_t *journal;
00263     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00264 
00265     journal->state = SEQUENTIAL_JOURNAL_STATE_RESETING;
00266 
00267     journal->prevCommand = FLASH_JOURNAL_OPCODE_RESET;
00268     return flashJournalStrategySequential_reset_progress();
00269 }