User | Revision | Line number | New contents of line |
Sergunb |
0:8f0d870509fe
|
1
|
// This file has been prepared for Doxygen automatic documentation generation.
|
Sergunb |
0:8f0d870509fe
|
2
|
/*! \file ********************************************************************
|
Sergunb |
0:8f0d870509fe
|
3
|
*
|
Sergunb |
0:8f0d870509fe
|
4
|
* Atmel Corporation
|
Sergunb |
0:8f0d870509fe
|
5
|
*
|
Sergunb |
0:8f0d870509fe
|
6
|
* \li File: eeprom.c
|
Sergunb |
0:8f0d870509fe
|
7
|
* \li Compiler: IAR EWAAVR 3.10c
|
Sergunb |
0:8f0d870509fe
|
8
|
* \li Support mail: avr@atmel.com
|
Sergunb |
0:8f0d870509fe
|
9
|
*
|
Sergunb |
0:8f0d870509fe
|
10
|
* \li Supported devices: All devices with split EEPROM erase/write
|
Sergunb |
0:8f0d870509fe
|
11
|
* capabilities can be used.
|
Sergunb |
0:8f0d870509fe
|
12
|
* The example is written for ATmega48.
|
Sergunb |
0:8f0d870509fe
|
13
|
*
|
Sergunb |
0:8f0d870509fe
|
14
|
* \li AppNote: AVR103 - Using the EEPROM Programming Modes.
|
Sergunb |
0:8f0d870509fe
|
15
|
*
|
Sergunb |
0:8f0d870509fe
|
16
|
* \li Description: Example on how to use the split EEPROM erase/write
|
Sergunb |
0:8f0d870509fe
|
17
|
* capabilities in e.g. ATmega48. All EEPROM
|
Sergunb |
0:8f0d870509fe
|
18
|
* programming modes are tested, i.e. Erase+Write,
|
Sergunb |
0:8f0d870509fe
|
19
|
* Erase-only and Write-only.
|
Sergunb |
0:8f0d870509fe
|
20
|
*
|
Sergunb |
0:8f0d870509fe
|
21
|
* $Revision: 1.6 $
|
Sergunb |
0:8f0d870509fe
|
22
|
* $Date: Friday, February 11, 2005 07:16:44 UTC $
|
Sergunb |
0:8f0d870509fe
|
23
|
****************************************************************************/
|
Sergunb |
0:8f0d870509fe
|
24
|
#include "grbl.h"
|
Sergunb |
0:8f0d870509fe
|
25
|
#ifdef AVRTARGET
|
Sergunb |
0:8f0d870509fe
|
26
|
#include <avr/io.h>
|
Sergunb |
0:8f0d870509fe
|
27
|
#include <avr/interrupt.h>
|
Sergunb |
0:8f0d870509fe
|
28
|
/* These EEPROM bits have different names on different devices. */
|
Sergunb |
0:8f0d870509fe
|
29
|
#ifndef EEPE
|
Sergunb |
0:8f0d870509fe
|
30
|
#define EEPE EEWE //!< EEPROM program/write enable.
|
Sergunb |
0:8f0d870509fe
|
31
|
#define EEMPE EEMWE //!< EEPROM master program/write enable.
|
Sergunb |
0:8f0d870509fe
|
32
|
#endif
|
Sergunb |
0:8f0d870509fe
|
33
|
|
Sergunb |
0:8f0d870509fe
|
34
|
/* These two are unfortunately not defined in the device include files. */
|
Sergunb |
0:8f0d870509fe
|
35
|
#define EEPM1 5 //!< EEPROM Programming Mode Bit 1.
|
Sergunb |
0:8f0d870509fe
|
36
|
#define EEPM0 4 //!< EEPROM Programming Mode Bit 0.
|
Sergunb |
0:8f0d870509fe
|
37
|
|
Sergunb |
0:8f0d870509fe
|
38
|
/* Define to reduce code size. */
|
Sergunb |
0:8f0d870509fe
|
39
|
#define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling.
|
Sergunb |
0:8f0d870509fe
|
40
|
#endif
|
Sergunb |
0:8f0d870509fe
|
41
|
#ifdef WIN32
|
Sergunb |
0:8f0d870509fe
|
42
|
#include <stdio.h>
|
Sergunb |
0:8f0d870509fe
|
43
|
#include <string.h>
|
Sergunb |
0:8f0d870509fe
|
44
|
#endif
|
Sergunb |
0:8f0d870509fe
|
45
|
#ifdef STM32F103C8
|
Sergunb |
0:8f0d870509fe
|
46
|
#include <string.h>
|
Sergunb |
0:8f0d870509fe
|
47
|
#include "stm32eeprom.h"
|
Sergunb |
0:8f0d870509fe
|
48
|
#include "settings.h"
|
Sergunb |
0:8f0d870509fe
|
49
|
#endif
|
Sergunb |
0:8f0d870509fe
|
50
|
#if defined(WIN32) || defined (STM32F103C8)
|
Sergunb |
0:8f0d870509fe
|
51
|
unsigned char EE_Buffer[0x400];
|
Sergunb |
0:8f0d870509fe
|
52
|
#endif
|
Sergunb |
0:8f0d870509fe
|
53
|
#if defined(WIN32)
|
Sergunb |
0:8f0d870509fe
|
54
|
#ifndef NOEEPROMSUPPORT
|
Sergunb |
0:8f0d870509fe
|
55
|
void eeprom_flush()
|
Sergunb |
0:8f0d870509fe
|
56
|
{
|
Sergunb |
0:8f0d870509fe
|
57
|
FILE *out = fopen("eeprom.bin", "wb");
|
Sergunb |
0:8f0d870509fe
|
58
|
fwrite(EE_Buffer, 1, 0x400, out);
|
Sergunb |
0:8f0d870509fe
|
59
|
fclose(out);
|
Sergunb |
0:8f0d870509fe
|
60
|
}
|
Sergunb |
0:8f0d870509fe
|
61
|
#endif
|
Sergunb |
0:8f0d870509fe
|
62
|
void eeprom_init()
|
Sergunb |
0:8f0d870509fe
|
63
|
{
|
Sergunb |
0:8f0d870509fe
|
64
|
#ifndef NOEEPROMSUPPORT
|
Sergunb |
0:8f0d870509fe
|
65
|
FILE *in = fopen("eeprom.bin", "rb");
|
Sergunb |
0:8f0d870509fe
|
66
|
if (in != NULL)
|
Sergunb |
0:8f0d870509fe
|
67
|
{
|
Sergunb |
0:8f0d870509fe
|
68
|
fread(EE_Buffer, 1, 0x400, in);
|
Sergunb |
0:8f0d870509fe
|
69
|
fclose(in);
|
Sergunb |
0:8f0d870509fe
|
70
|
}
|
Sergunb |
0:8f0d870509fe
|
71
|
else
|
Sergunb |
0:8f0d870509fe
|
72
|
{
|
Sergunb |
0:8f0d870509fe
|
73
|
memset(EE_Buffer, 0xff, 0x400);
|
Sergunb |
0:8f0d870509fe
|
74
|
}
|
Sergunb |
0:8f0d870509fe
|
75
|
#else
|
Sergunb |
0:8f0d870509fe
|
76
|
memset(EE_Buffer, 0x0, 0x400);
|
Sergunb |
0:8f0d870509fe
|
77
|
#endif
|
Sergunb |
0:8f0d870509fe
|
78
|
}
|
Sergunb |
0:8f0d870509fe
|
79
|
#endif
|
Sergunb |
0:8f0d870509fe
|
80
|
|
Sergunb |
0:8f0d870509fe
|
81
|
#ifdef STM32F103C8
|
Sergunb |
0:8f0d870509fe
|
82
|
#ifndef NOEEPROMSUPPORT
|
Sergunb |
0:8f0d870509fe
|
83
|
void eeprom_flush()
|
Sergunb |
0:8f0d870509fe
|
84
|
{
|
Sergunb |
0:8f0d870509fe
|
85
|
uint32_t nAddress = EEPROM_START_ADDRESS;
|
Sergunb |
0:8f0d870509fe
|
86
|
uint16_t *pBuffer = (uint16_t *)EE_Buffer;
|
Sergunb |
0:8f0d870509fe
|
87
|
uint16_t nSize = PAGE_SIZE;
|
Sergunb |
0:8f0d870509fe
|
88
|
|
Sergunb |
0:8f0d870509fe
|
89
|
FLASH_Status FlashStatus = FLASH_COMPLETE;
|
Sergunb |
0:8f0d870509fe
|
90
|
|
Sergunb |
0:8f0d870509fe
|
91
|
/* Erase Page0 */
|
Sergunb |
0:8f0d870509fe
|
92
|
FlashStatus = FLASH_ErasePage(EEPROM_START_ADDRESS);
|
Sergunb |
0:8f0d870509fe
|
93
|
|
Sergunb |
0:8f0d870509fe
|
94
|
/* If erase operation was failed, a Flash error code is returned */
|
Sergunb |
0:8f0d870509fe
|
95
|
if (FlashStatus != FLASH_COMPLETE)
|
Sergunb |
0:8f0d870509fe
|
96
|
{
|
Sergunb |
0:8f0d870509fe
|
97
|
return;
|
Sergunb |
0:8f0d870509fe
|
98
|
}
|
Sergunb |
0:8f0d870509fe
|
99
|
|
Sergunb |
0:8f0d870509fe
|
100
|
while (nSize > 0)
|
Sergunb |
0:8f0d870509fe
|
101
|
{
|
Sergunb |
0:8f0d870509fe
|
102
|
if (*pBuffer != 0xffff)
|
Sergunb |
0:8f0d870509fe
|
103
|
{
|
Sergunb |
0:8f0d870509fe
|
104
|
FLASH_ProgramHalfWord(nAddress, *pBuffer++);
|
Sergunb |
0:8f0d870509fe
|
105
|
}
|
Sergunb |
0:8f0d870509fe
|
106
|
else
|
Sergunb |
0:8f0d870509fe
|
107
|
{
|
Sergunb |
0:8f0d870509fe
|
108
|
pBuffer++;
|
Sergunb |
0:8f0d870509fe
|
109
|
}
|
Sergunb |
0:8f0d870509fe
|
110
|
if (*pBuffer != 0xffff)
|
Sergunb |
0:8f0d870509fe
|
111
|
{
|
Sergunb |
0:8f0d870509fe
|
112
|
FLASH_ProgramHalfWord(nAddress + 2, *pBuffer++);
|
Sergunb |
0:8f0d870509fe
|
113
|
}
|
Sergunb |
0:8f0d870509fe
|
114
|
else
|
Sergunb |
0:8f0d870509fe
|
115
|
{
|
Sergunb |
0:8f0d870509fe
|
116
|
pBuffer++;
|
Sergunb |
0:8f0d870509fe
|
117
|
}
|
Sergunb |
0:8f0d870509fe
|
118
|
nSize -= 4;
|
Sergunb |
0:8f0d870509fe
|
119
|
nAddress += 4;
|
Sergunb |
0:8f0d870509fe
|
120
|
}
|
Sergunb |
0:8f0d870509fe
|
121
|
}
|
Sergunb |
0:8f0d870509fe
|
122
|
void eeprom_init()
|
Sergunb |
0:8f0d870509fe
|
123
|
{
|
Sergunb |
0:8f0d870509fe
|
124
|
uint16_t VarIdx = 0;
|
Sergunb |
0:8f0d870509fe
|
125
|
uint8_t *pTmp = EE_Buffer;
|
Sergunb |
0:8f0d870509fe
|
126
|
|
Sergunb |
0:8f0d870509fe
|
127
|
for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
|
Sergunb |
0:8f0d870509fe
|
128
|
{
|
Sergunb |
0:8f0d870509fe
|
129
|
*pTmp++ = (*(__IO uint8_t*)(EEPROM_START_ADDRESS + VarIdx));
|
Sergunb |
0:8f0d870509fe
|
130
|
}
|
Sergunb |
0:8f0d870509fe
|
131
|
|
Sergunb |
0:8f0d870509fe
|
132
|
if (EE_Buffer[0] != SETTINGS_VERSION)
|
Sergunb |
0:8f0d870509fe
|
133
|
{
|
Sergunb |
0:8f0d870509fe
|
134
|
pTmp = EE_Buffer;
|
Sergunb |
0:8f0d870509fe
|
135
|
|
Sergunb |
0:8f0d870509fe
|
136
|
for (VarIdx = 0; VarIdx < PAGE_SIZE; VarIdx++)
|
Sergunb |
0:8f0d870509fe
|
137
|
{
|
Sergunb |
0:8f0d870509fe
|
138
|
*pTmp++ = 0xFF;
|
Sergunb |
0:8f0d870509fe
|
139
|
}
|
Sergunb |
0:8f0d870509fe
|
140
|
}
|
Sergunb |
0:8f0d870509fe
|
141
|
}
|
Sergunb |
0:8f0d870509fe
|
142
|
#endif
|
Sergunb |
0:8f0d870509fe
|
143
|
#endif
|
Sergunb |
0:8f0d870509fe
|
144
|
|
Sergunb |
0:8f0d870509fe
|
145
|
/*! \brief Read byte from EEPROM.
|
Sergunb |
0:8f0d870509fe
|
146
|
*
|
Sergunb |
0:8f0d870509fe
|
147
|
* This function reads one byte from a given EEPROM address.
|
Sergunb |
0:8f0d870509fe
|
148
|
*
|
Sergunb |
0:8f0d870509fe
|
149
|
* \note The CPU is halted for 4 clock cycles during EEPROM read.
|
Sergunb |
0:8f0d870509fe
|
150
|
*
|
Sergunb |
0:8f0d870509fe
|
151
|
* \param addr EEPROM address to read from.
|
Sergunb |
0:8f0d870509fe
|
152
|
* \return The byte read from the EEPROM address.
|
Sergunb |
0:8f0d870509fe
|
153
|
*/
|
Sergunb |
0:8f0d870509fe
|
154
|
unsigned char eeprom_get_char( unsigned int addr )
|
Sergunb |
0:8f0d870509fe
|
155
|
{
|
Sergunb |
0:8f0d870509fe
|
156
|
#ifdef AVRTARGET
|
Sergunb |
0:8f0d870509fe
|
157
|
do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
|
Sergunb |
0:8f0d870509fe
|
158
|
EEAR = addr; // Set EEPROM address register.
|
Sergunb |
0:8f0d870509fe
|
159
|
EECR = (1<<EERE); // Start EEPROM read operation.
|
Sergunb |
0:8f0d870509fe
|
160
|
return EEDR; // Return the byte read from EEPROM.
|
Sergunb |
0:8f0d870509fe
|
161
|
#endif
|
Sergunb |
0:8f0d870509fe
|
162
|
#if defined(WIN32) || defined(STM32F103C8)
|
Sergunb |
0:8f0d870509fe
|
163
|
return EE_Buffer[addr];
|
Sergunb |
0:8f0d870509fe
|
164
|
#endif
|
Sergunb |
0:8f0d870509fe
|
165
|
}
|
Sergunb |
0:8f0d870509fe
|
166
|
|
Sergunb |
0:8f0d870509fe
|
167
|
/*! \brief Write byte to EEPROM.
|
Sergunb |
0:8f0d870509fe
|
168
|
*
|
Sergunb |
0:8f0d870509fe
|
169
|
* This function writes one byte to a given EEPROM address.
|
Sergunb |
0:8f0d870509fe
|
170
|
* The differences between the existing byte and the new value is used
|
Sergunb |
0:8f0d870509fe
|
171
|
* to select the most efficient EEPROM programming mode.
|
Sergunb |
0:8f0d870509fe
|
172
|
*
|
Sergunb |
0:8f0d870509fe
|
173
|
* \note The CPU is halted for 2 clock cycles during EEPROM programming.
|
Sergunb |
0:8f0d870509fe
|
174
|
*
|
Sergunb |
0:8f0d870509fe
|
175
|
* \note When this function returns, the new EEPROM value is not available
|
Sergunb |
0:8f0d870509fe
|
176
|
* until the EEPROM programming time has passed. The EEPE bit in EECR
|
Sergunb |
0:8f0d870509fe
|
177
|
* should be polled to check whether the programming is finished.
|
Sergunb |
0:8f0d870509fe
|
178
|
*
|
Sergunb |
0:8f0d870509fe
|
179
|
* \note The EEPROM_GetChar() function checks the EEPE bit automatically.
|
Sergunb |
0:8f0d870509fe
|
180
|
*
|
Sergunb |
0:8f0d870509fe
|
181
|
* \param addr EEPROM address to write to.
|
Sergunb |
0:8f0d870509fe
|
182
|
* \param new_value New EEPROM value.
|
Sergunb |
0:8f0d870509fe
|
183
|
*/
|
Sergunb |
0:8f0d870509fe
|
184
|
void eeprom_put_char( unsigned int addr, unsigned char new_value )
|
Sergunb |
0:8f0d870509fe
|
185
|
{
|
Sergunb |
0:8f0d870509fe
|
186
|
#ifdef AVRTARGET
|
Sergunb |
0:8f0d870509fe
|
187
|
char old_value; // Old EEPROM value.
|
Sergunb |
0:8f0d870509fe
|
188
|
char diff_mask; // Difference mask, i.e. old value XOR new value.
|
Sergunb |
0:8f0d870509fe
|
189
|
|
Sergunb |
0:8f0d870509fe
|
190
|
cli(); // Ensure atomic operation for the write operation.
|
Sergunb |
0:8f0d870509fe
|
191
|
|
Sergunb |
0:8f0d870509fe
|
192
|
do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
|
Sergunb |
0:8f0d870509fe
|
193
|
#ifndef EEPROM_IGNORE_SELFPROG
|
Sergunb |
0:8f0d870509fe
|
194
|
do {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.
|
Sergunb |
0:8f0d870509fe
|
195
|
#endif
|
Sergunb |
0:8f0d870509fe
|
196
|
|
Sergunb |
0:8f0d870509fe
|
197
|
EEAR = addr; // Set EEPROM address register.
|
Sergunb |
0:8f0d870509fe
|
198
|
EECR = (1<<EERE); // Start EEPROM read operation.
|
Sergunb |
0:8f0d870509fe
|
199
|
old_value = EEDR; // Get old EEPROM value.
|
Sergunb |
0:8f0d870509fe
|
200
|
diff_mask = old_value ^ new_value; // Get bit differences.
|
Sergunb |
0:8f0d870509fe
|
201
|
|
Sergunb |
0:8f0d870509fe
|
202
|
// Check if any bits are changed to '1' in the new value.
|
Sergunb |
0:8f0d870509fe
|
203
|
if( diff_mask & new_value ) {
|
Sergunb |
0:8f0d870509fe
|
204
|
// Now we know that _some_ bits need to be erased to '1'.
|
Sergunb |
0:8f0d870509fe
|
205
|
|
Sergunb |
0:8f0d870509fe
|
206
|
// Check if any bits in the new value are '0'.
|
Sergunb |
0:8f0d870509fe
|
207
|
if( new_value != 0xff ) {
|
Sergunb |
0:8f0d870509fe
|
208
|
// Now we know that some bits need to be programmed to '0' also.
|
Sergunb |
0:8f0d870509fe
|
209
|
|
Sergunb |
0:8f0d870509fe
|
210
|
EEDR = new_value; // Set EEPROM data register.
|
Sergunb |
0:8f0d870509fe
|
211
|
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
|
Sergunb |
0:8f0d870509fe
|
212
|
(0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.
|
Sergunb |
0:8f0d870509fe
|
213
|
EECR |= (1<<EEPE); // Start Erase+Write operation.
|
Sergunb |
0:8f0d870509fe
|
214
|
} else {
|
Sergunb |
0:8f0d870509fe
|
215
|
// Now we know that all bits should be erased.
|
Sergunb |
0:8f0d870509fe
|
216
|
|
Sergunb |
0:8f0d870509fe
|
217
|
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
|
Sergunb |
0:8f0d870509fe
|
218
|
(1<<EEPM0); // ...and Erase-only mode.
|
Sergunb |
0:8f0d870509fe
|
219
|
EECR |= (1<<EEPE); // Start Erase-only operation.
|
Sergunb |
0:8f0d870509fe
|
220
|
}
|
Sergunb |
0:8f0d870509fe
|
221
|
} else {
|
Sergunb |
0:8f0d870509fe
|
222
|
// Now we know that _no_ bits need to be erased to '1'.
|
Sergunb |
0:8f0d870509fe
|
223
|
|
Sergunb |
0:8f0d870509fe
|
224
|
// Check if any bits are changed from '1' in the old value.
|
Sergunb |
0:8f0d870509fe
|
225
|
if( diff_mask ) {
|
Sergunb |
0:8f0d870509fe
|
226
|
// Now we know that _some_ bits need to the programmed to '0'.
|
Sergunb |
0:8f0d870509fe
|
227
|
|
Sergunb |
0:8f0d870509fe
|
228
|
EEDR = new_value; // Set EEPROM data register.
|
Sergunb |
0:8f0d870509fe
|
229
|
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
|
Sergunb |
0:8f0d870509fe
|
230
|
(1<<EEPM1); // ...and Write-only mode.
|
Sergunb |
0:8f0d870509fe
|
231
|
EECR |= (1<<EEPE); // Start Write-only operation.
|
Sergunb |
0:8f0d870509fe
|
232
|
}
|
Sergunb |
0:8f0d870509fe
|
233
|
}
|
Sergunb |
0:8f0d870509fe
|
234
|
|
Sergunb |
0:8f0d870509fe
|
235
|
sei(); // Restore interrupt flag state.
|
Sergunb |
0:8f0d870509fe
|
236
|
#endif
|
Sergunb |
0:8f0d870509fe
|
237
|
#if defined(WIN32) || defined(STM32F103C8)
|
Sergunb |
0:8f0d870509fe
|
238
|
EE_Buffer[addr] = new_value;
|
Sergunb |
0:8f0d870509fe
|
239
|
#endif
|
Sergunb |
0:8f0d870509fe
|
240
|
}
|
Sergunb |
0:8f0d870509fe
|
241
|
|
Sergunb |
0:8f0d870509fe
|
242
|
// Extensions added as part of Grbl
|
Sergunb |
0:8f0d870509fe
|
243
|
|
Sergunb |
0:8f0d870509fe
|
244
|
|
Sergunb |
0:8f0d870509fe
|
245
|
void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size) {
|
Sergunb |
0:8f0d870509fe
|
246
|
unsigned char checksum = 0;
|
Sergunb |
0:8f0d870509fe
|
247
|
for(; size > 0; size--) {
|
Sergunb |
0:8f0d870509fe
|
248
|
checksum = (checksum << 1) || (checksum >> 7);
|
Sergunb |
0:8f0d870509fe
|
249
|
checksum += *source;
|
Sergunb |
0:8f0d870509fe
|
250
|
eeprom_put_char(destination++, *(source++));
|
Sergunb |
0:8f0d870509fe
|
251
|
}
|
Sergunb |
0:8f0d870509fe
|
252
|
eeprom_put_char(destination, checksum);
|
Sergunb |
0:8f0d870509fe
|
253
|
#if defined(WIN32) || defined(STM32F103C8)
|
Sergunb |
0:8f0d870509fe
|
254
|
#ifndef NOEEPROMSUPPORT
|
Sergunb |
0:8f0d870509fe
|
255
|
eeprom_flush();
|
Sergunb |
0:8f0d870509fe
|
256
|
#endif
|
Sergunb |
0:8f0d870509fe
|
257
|
#endif
|
Sergunb |
0:8f0d870509fe
|
258
|
}
|
Sergunb |
0:8f0d870509fe
|
259
|
|
Sergunb |
0:8f0d870509fe
|
260
|
int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) {
|
Sergunb |
0:8f0d870509fe
|
261
|
unsigned char data, checksum = 0;
|
Sergunb |
0:8f0d870509fe
|
262
|
for(; size > 0; size--) {
|
Sergunb |
0:8f0d870509fe
|
263
|
data = eeprom_get_char(source++);
|
Sergunb |
0:8f0d870509fe
|
264
|
checksum = (checksum << 1) || (checksum >> 7);
|
Sergunb |
0:8f0d870509fe
|
265
|
checksum += data;
|
Sergunb |
0:8f0d870509fe
|
266
|
*(destination++) = data;
|
Sergunb |
0:8f0d870509fe
|
267
|
}
|
Sergunb |
0:8f0d870509fe
|
268
|
return(checksum == eeprom_get_char(source));
|
Sergunb |
0:8f0d870509fe
|
269
|
}
|
Sergunb |
0:8f0d870509fe
|
270
|
|
Sergunb |
0:8f0d870509fe
|
271
|
// end of file
|