Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers settings_rom.c Source File

settings_rom.c

Go to the documentation of this file.
00001 /**
00002  * @file    settings_rom.c
00003  * @brief   Implementation of settings.h
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include <string.h>
00023 
00024 #include "settings.h"
00025 #include "target_config.h"
00026 #include "compiler.h"
00027 #include "cortex_m.h"
00028 #include "FlashPrg.h"
00029 
00030 // 'kvld' in hex - key valid
00031 #define CFG_KEY             0x6b766c64
00032 #define SECTOR_BUFFER_SIZE  16
00033 
00034 // WARNING - THIS STRUCTURE RESIDES IN NON-VOLATILE STORAGE!
00035 // Be careful with changes:
00036 // -Only add new members to end end of this structure
00037 // -Do not change the order of members in this structure
00038 // -Structure must remain packed so no padding bytes are added
00039 typedef struct __attribute__((__packed__)) cfg_setting {
00040     uint32_t key;               // Magic key to indicate a valid record
00041     uint16_t size;              // Size of cfg_setting_t
00042 
00043     // Configurable values
00044     uint8_t auto_rst;
00045     uint8_t automation_allowed;
00046     uint8_t overflow_detect;
00047 
00048     // Add new members here
00049 
00050 } cfg_setting_t;
00051 
00052 // Make sure FORMAT in generate_config.py is updated if size changes
00053 COMPILER_ASSERT(sizeof(cfg_setting_t) == 9);
00054 
00055 // Sector buffer must be as big or bigger than settings
00056 COMPILER_ASSERT(sizeof(cfg_setting_t) < SECTOR_BUFFER_SIZE);
00057 // Sector buffer must be a multiple of 4 bytes at least.
00058 // ProgramPage for some interfaces, like the k20dx, require that
00059 // the data is a multiple of 4 bytes, otherwise programming will
00060 // fail.  Assert 8 byte alignement just to be safe.
00061 COMPILER_ASSERT(SECTOR_BUFFER_SIZE % 8 == 0);
00062 
00063 // Configuration ROM
00064 static volatile const cfg_setting_t config_rom __attribute__((section("cfgrom"), zero_init));
00065 // Ram copy of ROM config
00066 static cfg_setting_t config_rom_copy;
00067 
00068 // Configuration defaults in flash
00069 static const cfg_setting_t config_default = {
00070     .auto_rst = 1,
00071     .automation_allowed = 1,
00072     .overflow_detect = 1,
00073 };
00074 
00075 // Buffer for data to flash
00076 static uint32_t write_buffer[SECTOR_BUFFER_SIZE / 4];
00077 
00078 // Check if the configuration in flash needs to be updated
00079 static bool config_needs_update()
00080 {
00081     // Update if the key is invalid
00082     if (CFG_KEY != config_rom.key) {
00083         return true;
00084     }
00085 
00086     // Update if the config key is valid but
00087     // has a smaller size.
00088     if (config_rom.size < sizeof(config_rom)) {
00089         return true;
00090     }
00091 
00092     // The config is valid and has the right
00093     // size so it does not need to be updated
00094     return false;
00095 }
00096 
00097 // Reprogram the new settings if flash writing is allowed
00098 static void program_cfg(cfg_setting_t *new_cfg)
00099 {
00100     uint32_t status;
00101     uint32_t addr;
00102     cortex_int_state_t state;
00103     addr = (uint32_t)&config_rom;
00104     state = cortex_int_get_and_disable();
00105     status = EraseSector(addr);
00106     cortex_int_restore(state);
00107 
00108     if (status != 0) {
00109         return;
00110     }
00111 
00112     memset(write_buffer, 0xFF, sizeof(write_buffer));
00113     memcpy(write_buffer, new_cfg, sizeof(cfg_setting_t));
00114     state = cortex_int_get_and_disable();
00115     status = ProgramPage(addr, sizeof(write_buffer), write_buffer);
00116     cortex_int_restore(state);
00117 
00118     if (0 != status) {
00119         return;
00120     }
00121 }
00122 
00123 void config_rom_init()
00124 {
00125     Init(0, 0, 0);
00126     // Fill in the ram copy with the defaults
00127     memcpy(&config_rom_copy, &config_default, sizeof(config_rom_copy));
00128 
00129     // Read settings from flash if the key is valid
00130     if (CFG_KEY == config_rom.key) {
00131         uint32_t size = MIN(config_rom.size, sizeof(config_rom));
00132         memcpy(&config_rom_copy, (void *)&config_rom, size);
00133     }
00134 
00135     // Fill in special values
00136     config_rom_copy.key = CFG_KEY;
00137     config_rom_copy.size = sizeof(config_rom);
00138 
00139     // Write settings back to flash if they are out of date
00140     // Note - program_cfg only programs data in bootloader mode
00141     if (config_needs_update()) {
00142         // Program with defaults if none are set
00143         program_cfg(&config_rom_copy);
00144     }
00145 }
00146 
00147 
00148 void config_set_auto_rst(bool on)
00149 {
00150     config_rom_copy.auto_rst = on;
00151     program_cfg(&config_rom_copy);
00152 }
00153 
00154 void config_set_automation_allowed(bool on)
00155 {
00156     config_rom_copy.automation_allowed = on;
00157     program_cfg(&config_rom_copy);
00158 }
00159 
00160 void config_set_overflow_detect(bool on)
00161 {
00162     config_rom_copy.overflow_detect = on;
00163     program_cfg(&config_rom_copy);
00164 }
00165 
00166 bool config_get_auto_rst()
00167 {
00168     return config_rom_copy.auto_rst;
00169 }
00170 
00171 bool config_get_automation_allowed(void)
00172 {
00173     return config_rom_copy.automation_allowed;
00174 }
00175 
00176 bool config_get_overflow_detect()
00177 {
00178     return config_rom_copy.overflow_detect;
00179 }