Add rotating hash init function.
[bertos.git] / mware / prog.c
1 /**
2  * \file
3  * <!--
4  * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
5  * All Rights Reserved.
6  * -->
7  *
8  * \brief Flash memory programmar interface.
9  *
10  * \version $Id$
11  * \author Stefano Fedrigo <aleph@develer.com>
12  * \author Francesco Sacchi <batt@develer.com>
13  * \author Daniele Basile <asterix@develer.com>
14  */
15
16 #include "prog.h"
17
18 #include <string.h>
19
20 #include <cfg/os.h>
21 #include <cfg/cpu.h>
22 #include <cfg/compiler.h>
23
24 #include <cfg/debug.h>
25
26 /*
27  * Include platform-specific binding code if we're hosted.
28  * Try the CPU specific one for bare-metal environments.
29  */
30 #if OS_HOSTED
31         #include OS_CSOURCE(prog)
32 #else
33         #include CPU_CSOURCE(prog)
34 #endif
35
36
37 #define TEST_SIZE 683
38 #define ONE_BYTE_TEST_ADDRESS 347
39
40 uint8_t test_buf[TEST_SIZE];
41 uint8_t save_buf[TEST_SIZE];
42
43 /**
44  * Program memory read/write subtest.
45  * Try to write/read in the same \param f file location \param _size bytes.
46  * \return true if all is ok, false otherwise
47  * \note Restore file position at exit (if no error)
48  * \note Test buffer \param buf must be filled with
49  * the following statement:
50  * <pre>
51  * buf[i] = i & 0xff
52  * </pre>
53  */
54 static bool prog_rwTest(KFile *f, uint8_t *buf, size_t _size)
55 {
56         int32_t size = _size;
57         // Write test buffer
58         if (f->write(f, buf, size) != size)
59                 return false;
60         f->seek(f, -size);
61
62         // Reset test buffer
63         memset(buf, 0, size);
64
65         // Read flash in test buffer
66         if (f->read(f, buf, size) != size)
67                 return false;
68         f->seek(f, -size);
69
70         // Check test result
71         for (size_t i = 0; i < size; i++)
72                 if (buf[i] != (i & 0xff))
73                         return false;
74
75         return true;
76 }
77
78 /**
79  * Test for program memory read/write.
80  */
81 bool prog_test(void)
82 {
83         KFile fd;
84
85         // Set up flash programming functions.
86         fd.open = prog_open;
87         fd.close = prog_close;
88         fd.read = prog_read;
89         fd.write = prog_write;
90         fd.seek = prog_seek;
91
92         // Fill in test buffer
93         for (int i = 0; i < TEST_SIZE; i++)
94                 test_buf[i] = (i & 0xff);
95
96         // Open flash
97         fd.open(&fd, NULL, 0);
98         // Save flash content (for later restore).
99         fd.read(&fd, save_buf, sizeof(save_buf));
100         fd.seek(&fd, -TEST_SIZE);
101
102         // Test flash read/write to address 0..TEST_SIZE
103         if (!prog_rwTest(&fd, test_buf, TEST_SIZE))
104                 goto prog_test_end;
105
106         // One byte read/write test
107         fd.seek(&fd, ONE_BYTE_TEST_ADDRESS); // Random address
108         if (!prog_rwTest(&fd, test_buf, 1))
109                 goto prog_test_end;
110         fd.seek(&fd, -(int32_t)ONE_BYTE_TEST_ADDRESS);
111
112         // Restore old flash data
113         if (fd.write(&fd, save_buf, sizeof(test_buf)) != TEST_SIZE)
114                 goto prog_test_end;
115         fd.seek(&fd, -TEST_SIZE);
116
117         // Go to the Flash end
118         fd.seek(&fd, fd.size - TEST_SIZE);
119         // Save flash content (for later restore).
120         fd.read(&fd, save_buf, sizeof(save_buf));
121         fd.seek(&fd, -TEST_SIZE);
122
123         // Test flash read/write to address (FLASHEND - TEST_SIZE) ... FLASHEND
124         if (!prog_rwTest(&fd, test_buf, TEST_SIZE))
125                 goto prog_test_end;
126
127         // Go to half test size.
128         fd.seek(&fd, (TEST_SIZE / 2));
129
130         // This test should FAIL, cause we try to write over file end.
131         if (prog_rwTest(&fd, test_buf, TEST_SIZE))
132                 goto prog_test_end;
133
134         fd.seek(&fd, -TEST_SIZE);
135         // Restore old flash data
136         fd.write(&fd, save_buf, TEST_SIZE);
137
138         fd.close(&fd);
139         return true;
140
141 prog_test_end:
142         fd.close(&fd);
143         return false;
144 }