| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

nvm_data_helpers.cpp
Go to the documentation of this file.
1 /*!
2
3 Copyright 2018(c) Analog Devices, Inc.
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the
14 distribution.
15 - Neither the name of Analog Devices, Inc. nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
18 - The use of this software may or may not infringe the patent rights
19 of one or more patent holders. This license does not release you
20 from the requirement that you obtain separate licenses from these
21 patent holders to use this software.
22 - Use of the software either in source or binary form, must be run
23 on or directly connected to an Analog Devices Inc. component.
24
25 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
26 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
27 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
31 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 /*! @file
37 @ingroup LTPSM_InFlightUpdate
38 Library File
39 */
40
41 #include "nvm_data_helpers.h"
42
43 #define MAX_RECORD_SIZE 600
44
45 static uint8_t record_data[MAX_RECORD_SIZE];
46 static uint8_t record_data_hold[MAX_RECORD_SIZE];
47 static uint16_t *words;
48 static uint16_t nWords;
49 static uint8_t nvram_somethingToVerify = 0; // Simple flag to make sure you are not verifying something you have not buffered or written
50
51 int getMaxRecordSize()
52 {
53 return MAX_RECORD_SIZE;
54 }
55
56 uint8_t *getRecordData()
57 {
58 return record_data;
59 }
60
61 uint8_t *getRecordHoldData()
62 {
63 return record_data_hold;
64 }
65
66 uint8_t *holdRecord()
67 {
68 memcpy(record_data_hold, record_data, MAX_RECORD_SIZE);
69 return record_data_hold;
70 }
71
72 // This function replaced the older one above. It reads through the whole linked list
73 // and writes the nodes word by word. It also sets the 'nvramListTopVerify' pointer to
74 // the root node of the linked list it just wrote. This allows the verify function
75 // to know what to verify.
76 uint8_t writeNvmData(t_RECORD_NVM_DATA *pRecord)
77 {
78 uint8_t allGood = 1; // Eventually use this for a timeout
79 int8_t busy;
80 int16_t count;
81
82 nvram_somethingToVerify = 1;
83
84 for (uint16_t i = 0; i < nWords; i++)
85 {
86 if (allGood)
87 {
88 if (pRecord->detailedRecordHeader.UsePec)
89 smbusPec__->writeWord((uint8_t) pRecord->detailedRecordHeader.DeviceAddress,
90 pRecord->detailedRecordHeader.CommandCode,
91 words[i]);
92 else
93 smbusNoPec__->writeWord((uint8_t) pRecord->detailedRecordHeader.DeviceAddress,
94 pRecord->detailedRecordHeader.CommandCode,
95 words[i]);
96
97 count = 0;
98 do
99 {
100 if (pRecord->detailedRecordHeader.UsePec)
101 busy = smbusPec__->readByte((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, 0xef);
102 else
103 busy = smbusNoPec__->readByte((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, 0xef);
104
105 busy = (busy & 0x40)==0;
106 }
107 while (busy && (count++ < 4096));
108 if (count == 4097)
109 {
110 Serial.println(F("NVM Write Timeout"));
111 allGood = 0;
112 }
113 }
114 }
115 return allGood;
116 }
117
118 // This function is called to store the block of NVRAM data in the bitstream
119 // into a linked list to be used later.
120 uint8_t bufferNvmData(t_RECORD_NVM_DATA *pRecord)
121 {
122 nvram_somethingToVerify = 1;
123
124 nWords = (uint16_t)((pRecord->baseRecordHeader.Length-8)/2);
125 words = (uint16_t *) ((uint16_t)(holdRecord()+8)); // Change (UINT16) to the size of an address on the target machine.
126
127 return 1;
128 }
129
130 // This function reads the NVRAM back from the device and compares it against
131 // what was buffered. If any word does not match, it returns a fail flag.
132 uint8_t readThenVerifyNvmData(t_RECORD_NVM_DATA *pRecord)
133 {
134 uint8_t allGood = 1;
135 uint16_t actual_value;
136 uint16_t expected_value;
137 uint8_t busy;
138 uint16_t count;
139
140 if (nvram_somethingToVerify == 0)
141 {
142 Serial.println(F("No NVM Data"));
143 return 1;
144 }
145
146 nvram_somethingToVerify = 0;
147
148 for (uint16_t i = 0; i < nWords; i++)
149 {
150 expected_value = words[i];
151 actual_value = 0;
152
153 if (allGood)
154 {
155 if (pRecord->detailedRecordHeader.UsePec)
156 actual_value = smbusPec__->readWord((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, pRecord->detailedRecordHeader.CommandCode);
157 else
158 actual_value = smbusNoPec__->readWord((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, pRecord->detailedRecordHeader.CommandCode);
159
160
161 if (actual_value != expected_value)
162 {
163
164 Serial.print(F("Failed verify: Address "));
165 Serial.print(pRecord->detailedRecordHeader.DeviceAddress, HEX);
166 Serial.print(F(" Command "));
167 Serial.print(pRecord->detailedRecordHeader.CommandCode, HEX);
168 Serial.print(F(" Index "));
169 Serial.print(i);
170 Serial.print(F(" Expected "));
171 Serial.print(expected_value, HEX);
172 Serial.print(F(" Actual "));
173 Serial.println(actual_value, HEX);
174
175 allGood = 0;
176 }
177
178 count = 0;
179 do
180 {
181 if (pRecord->detailedRecordHeader.UsePec)
182 busy = smbusPec__->readByte((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, 0xef);
183 else
184 busy = smbusNoPec__->readByte((uint8_t) pRecord->detailedRecordHeader.DeviceAddress, 0xef);
185
186 // Serial.println(F("Loop NVM Data"));
187
188 busy = (busy & 0x40)==0;
189 }
190 while (busy && (count++ < 4096));
191 if (count == 4097)
192 {
193 Serial.println(F("NVM Read Timeout"));
194 allGood = 0;
195 }
196
197 }
198 // else
199 // Serial.println(F("Good"));
200
201 }
202
203 return allGood;
204 }
tRecordHeader::Length
uint16_t Length
Definition: record_type_basic_definitions.h:54
LT_SMBusBase::writeWord
void writeWord(uint8_t address, uint8_t command, uint16_t data)
SMBus write word command.
Definition: LT_SMBusBase.cpp:265
tRecordHeaderAddressAndCommandWithOptionalPEC::DeviceAddress
uint16_t DeviceAddress
Definition: record_type_basic_definitions.h:60
nWords
static uint16_t nWords
Definition: nvm_data_helpers.cpp:48
nvm_data_helpers.h
Copyright 2018(c) Analog Devices, Inc.
t_RECORD_NVM_DATA::baseRecordHeader
tRecordHeaderLengthAndType baseRecordHeader
Definition: record_type_definitions.h:236
bufferNvmData
uint8_t bufferNvmData(t_RECORD_NVM_DATA *pRecord)
Definition: nvm_data_helpers.cpp:120
tRecordHeaderAddressAndCommandWithOptionalPEC::CommandCode
uint8_t CommandCode
Definition: record_type_basic_definitions.h:61
MAX_RECORD_SIZE
#define MAX_RECORD_SIZE
Definition: nvm_data_helpers.cpp:43
LT_SMBusBase::readByte
uint8_t readByte(uint8_t address, uint8_t command)
SMBus read byte command.
Definition: LT_SMBusBase.cpp:234
getRecordData
uint8_t * getRecordData()
Definition: nvm_data_helpers.cpp:56
getMaxRecordSize
int getMaxRecordSize()
Definition: nvm_data_helpers.cpp:51
words
static uint16_t * words
Definition: nvm_data_helpers.cpp:47
smbusPec__
LT_SMBusPec * smbusPec__
Definition: nvm.cpp:55
t_RECORD_NVM_DATA
Definition: record_type_definitions.h:234
record_data_hold
static uint8_t record_data_hold[MAX_RECORD_SIZE]
Definition: nvm_data_helpers.cpp:46
t_RECORD_NVM_DATA::detailedRecordHeader
tRecordHeaderAddressAndCommandWithOptionalPEC detailedRecordHeader
Definition: record_type_definitions.h:237
writeNvmData
uint8_t writeNvmData(t_RECORD_NVM_DATA *pRecord)
Definition: nvm_data_helpers.cpp:76
record_data
static uint8_t record_data[MAX_RECORD_SIZE]
Definition: nvm_data_helpers.cpp:45
nvram_somethingToVerify
static uint8_t nvram_somethingToVerify
Definition: nvm_data_helpers.cpp:49
i
static int i
Definition: DC2430A.ino:184
holdRecord
uint8_t * holdRecord()
Definition: nvm_data_helpers.cpp:66
getRecordHoldData
uint8_t * getRecordHoldData()
Definition: nvm_data_helpers.cpp:61
smbusNoPec__
LT_SMBusNoPec * smbusNoPec__
Definition: nvm.cpp:54
readThenVerifyNvmData
uint8_t readThenVerifyNvmData(t_RECORD_NVM_DATA *pRecord)
Definition: nvm_data_helpers.cpp:132
tRecordHeaderAddressAndCommandWithOptionalPEC::UsePec
uint8_t UsePec
Definition: record_type_basic_definitions.h:62
LT_SMBusBase::readWord
uint16_t readWord(uint8_t address, uint8_t command)
SMBus read word command.
Definition: LT_SMBusBase.cpp:301