comparison packages/devs/flash/synthv2/current/src/synth.c @ 2700:99efb5fe625e

* src/synth.c: Implemented simulation of proper NOR flash writes. General cleanup.
author asl
date Tue, 23 Dec 2008 18:27:45 +0000
parents b1cdd12003cd
children 74dbf4c3f2e1
comparison
equal deleted inserted replaced
2699:8d3a60779c64 2700:99efb5fe625e
65 #endif 65 #endif
66 66
67 static int 67 static int
68 synth_flash_init(struct cyg_flash_dev *dev) 68 synth_flash_init(struct cyg_flash_dev *dev)
69 { 69 {
70 struct cyg_flash_synth_priv *priv = (struct cyg_flash_synth_priv*)dev->priv; 70 struct cyg_flash_synth_priv *priv =
71 (struct cyg_flash_synth_priv *) dev->priv;
71 cyg_flashaddr_t base; 72 cyg_flashaddr_t base;
72 int flags=CYG_HAL_SYS_MAP_SHARED; 73 int flags = CYG_HAL_SYS_MAP_SHARED;
73 74
74 priv->flashfd = 75 priv->flashfd = cyg_hal_sys_open(
75 cyg_hal_sys_open(priv->filename, 76 priv->filename,
76 CYG_HAL_SYS_O_RDWR, 77 CYG_HAL_SYS_O_RDWR,
77 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG| 78 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
78 CYG_HAL_SYS_S_IRWXO); 79
79 if (priv->flashfd == -ENOENT) { 80 if (priv->flashfd == -ENOENT) {
80 long w, bytesleft; 81 long w, bytesleft;
81 char buf[128]; 82 char buf[128];
82 83
83 priv->flashfd = cyg_hal_sys_open( 84 priv->flashfd = cyg_hal_sys_open(
84 priv->filename, 85 priv->filename,
85 CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT, 86 CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT,
86 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO); 87 CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
87 CYG_ASSERT( priv->flashfd >= 0, 88 CYG_ASSERT(priv->flashfd >= 0,
88 "Opening of the file for the synth flash failed!"); 89 "Opening of the file for the synth flash failed!");
89 // fill with 0xff 90
90 memset( buf, 0xff, sizeof(buf) ); 91 // Fill with 0xff
92 memset(buf, 0xff, sizeof(buf));
91 bytesleft = priv->block_size * priv->blocks + 93 bytesleft = priv->block_size * priv->blocks +
92 priv->boot_block_size * priv->boot_blocks; 94 priv->boot_block_size * priv->boot_blocks;
93
94 while (bytesleft > 0) { 95 while (bytesleft > 0) {
95 int bytesneeded; 96 int bytesneeded;
96 bytesneeded = bytesleft < sizeof(buf) ? 97 bytesneeded = bytesleft < sizeof(buf) ? bytesleft : sizeof(buf);
97 bytesleft : sizeof(buf); 98 w = cyg_hal_sys_write(priv->flashfd, buf, bytesneeded);
98 99 CYG_ASSERT(w == bytesneeded, "initialization of flash file failed");
99 w = cyg_hal_sys_write( priv->flashfd, buf,
100 bytesneeded );
101 CYG_ASSERT(w == bytesneeded,
102 "initialization of flash file failed");
103 bytesleft -= bytesneeded; 100 bytesleft -= bytesneeded;
104 } // while 101 }
105 } 102 }
106 CYG_ASSERT( priv->flashfd >= 0, 103
107 "Opening of the file for the synth flash failed!"); 104 CYG_ASSERT(priv->flashfd >= 0,
108 if ( priv->flashfd <= 0 ) { 105 "Opening of the file for the synth flash failed!");
106
107 if (priv->flashfd <= 0)
109 return CYG_FLASH_ERR_HWR; 108 return CYG_FLASH_ERR_HWR;
110 } 109
111 110 if (dev->start != 0)
112 if (dev->start != 0) {
113 flags |= CYG_HAL_SYS_MAP_FIXED; 111 flags |= CYG_HAL_SYS_MAP_FIXED;
114 } 112
115 base = (cyg_flashaddr_t)cyg_hal_sys_mmap( 113 base = (cyg_flashaddr_t) cyg_hal_sys_mmap(
116 (void *)dev->start, 114 (void *) dev->start,
117 priv->blocks * priv->block_size + 115 priv->blocks * priv->block_size +
118 priv->boot_block_size * priv->boot_blocks, 116 priv->boot_block_size * priv->boot_blocks,
119 CYG_HAL_SYS_PROT_READ, 117 CYG_HAL_SYS_PROT_READ,
120 flags, 118 flags,
121 priv->flashfd, 119 priv->flashfd,
122 0l); 120 0l);
123 CYG_ASSERT( base != -1, "mmap of flash file failed!" ); 121 CYG_ASSERT(base != -1, "mmap of flash file failed!");
124 if (base == -1) { 122 if (base == -1)
125 return CYG_FLASH_ERR_HWR; 123 return CYG_FLASH_ERR_HWR;
126 } 124
127 dev->start = base; 125 dev->start = base;
128 dev->end = base + (priv->blocks * priv->block_size) + 126 dev->end = base + (priv->blocks * priv->block_size) +
129 (priv->boot_blocks * priv->boot_block_size) - 1; 127 (priv->boot_blocks * priv->boot_block_size) - 1;
130 if (priv->boot_blocks) { 128 if (priv->boot_blocks) {
131 if (priv->boot_block_bottom) { 129 if (priv->boot_block_bottom) {
148 dev->block_info = &priv->block_info[0]; 146 dev->block_info = &priv->block_info[0];
149 147
150 return CYG_FLASH_ERR_OK; 148 return CYG_FLASH_ERR_OK;
151 } 149 }
152 150
153 /* This helps speed up the erase. */
154 static char empty[4096];
155 static cyg_bool empty_inited = false;
156
157 // Return the size of the block which is at the given address. 151 // Return the size of the block which is at the given address.
158 // __inline__ so that we know it will be in RAM, not ROM. 152 // __inline__ so that we know it will be in RAM, not ROM.
159 static __inline__ size_t 153 static __inline__ size_t
160 flash_block_size(struct cyg_flash_dev *dev, const cyg_flashaddr_t addr) 154 flash_block_size(struct cyg_flash_dev *dev, const cyg_flashaddr_t addr)
161 { 155 {
162 int i; 156 int i;
163 size_t offset; 157 cyg_flashaddr_t offset;
164 158
159 CYG_ASSERT((addr >= dev->start) && (addr <= dev->end), "Not inside device");
165 160
166 CYG_ASSERT((addr >= dev->start) && (addr <= dev->end), "Not inside device"); 161 offset = addr - dev->start;
167 162 for (i=0; i < dev->num_block_infos; i++) {
168 offset = addr - dev->start; 163 if (offset < (dev->block_info[i].blocks *
169 for (i=0; i < dev->num_block_infos; i++) { 164 dev->block_info[i].block_size))
170 if (offset < (dev->block_info[i].blocks * dev->block_info[i].block_size)) 165 return dev->block_info[i].block_size;
171 return dev->block_info[i].block_size; 166 offset = offset -
172 offset = offset - 167 (dev->block_info[i].blocks * dev->block_info[i].block_size);
173 (dev->block_info[i].blocks * dev->block_info[i].block_size); 168 }
174 } 169 CYG_FAIL("Programming error");
175 CYG_FAIL("Programming error"); 170 return 0;
176 return 0;
177 } 171 }
178 172
179 static int 173 static int
180 synth_flash_erase_block(struct cyg_flash_dev *dev, 174 synth_flash_erase_block(struct cyg_flash_dev *dev,
181 cyg_flashaddr_t block_base) 175 cyg_flashaddr_t block_base)
182 { 176 {
183 const struct cyg_flash_synth_priv *priv = dev->priv; 177 const struct cyg_flash_synth_priv *priv = dev->priv;
184 int offset = (int)block_base; 178 cyg_flashaddr_t offset = block_base;
185 size_t remaining; 179 size_t remaining;
186 int write_size; 180 int write_size;
181
182 // This helps speed up the erasing
183 static cyg_uint8 empty[4096];
184 static cyg_bool empty_inited;
187 185
188 offset -= dev->start; 186 offset -= dev->start;
189 187
190 cyg_hal_sys_lseek(priv->flashfd, offset, 188 cyg_hal_sys_lseek(priv->flashfd, offset, CYG_HAL_SYS_SEEK_SET);
191 CYG_HAL_SYS_SEEK_SET);
192 189
193 if (!empty_inited) { 190 if (!empty_inited) {
194 memset(empty, 0xff, sizeof(empty)); 191 memset(empty, 0xff, sizeof(empty));
195 empty_inited = true; 192 empty_inited = true;
196 } 193 }
200 while (remaining) { 197 while (remaining) {
201 write_size = MIN(remaining, sizeof(empty)); 198 write_size = MIN(remaining, sizeof(empty));
202 cyg_hal_sys_write(priv->flashfd, empty, write_size); 199 cyg_hal_sys_write(priv->flashfd, empty, write_size);
203 remaining -= write_size; 200 remaining -= write_size;
204 } 201 }
202
205 return CYG_FLASH_ERR_OK; 203 return CYG_FLASH_ERR_OK;
206 } 204 }
207 205
208 static int 206 static int
209 synth_flash_program (struct cyg_flash_dev *dev, 207 synth_flash_program (struct cyg_flash_dev *dev,
210 cyg_flashaddr_t base, 208 cyg_flashaddr_t base,
211 const void* data, size_t len) 209 const void* data, size_t len)
212 { 210 {
213 const struct cyg_flash_synth_priv *priv = dev->priv; 211 const struct cyg_flash_synth_priv *priv = dev->priv;
214 int offset = base; 212 cyg_flashaddr_t offset = base;
213 cyg_uint8 *buf = (cyg_uint8 *) data;
214
215 // This helps speed up the programming
216 static cyg_uint8 tmp[4096];
217
215 offset -= dev->start; 218 offset -= dev->start;
216 219
217 cyg_hal_sys_lseek(priv->flashfd, offset, CYG_HAL_SYS_SEEK_SET); 220 while (len > 0) {
218 cyg_hal_sys_write(priv->flashfd, data, len); 221 int i;
219 222 int write_size = MIN(len, sizeof(tmp));
223 // Writing to NOR flash only sets bits from 1 to 0, not vice-versa
224 cyg_hal_sys_lseek(priv->flashfd, offset, CYG_HAL_SYS_SEEK_SET);
225 cyg_hal_sys_read(priv->flashfd, tmp, write_size);
226 for (i = 0; i < write_size; i++)
227 tmp[i] = tmp[i] & buf[i];
228 cyg_hal_sys_lseek(priv->flashfd, offset, CYG_HAL_SYS_SEEK_SET);
229 cyg_hal_sys_write(priv->flashfd, tmp, write_size);
230 // Process next chunk
231 buf += write_size;
232 offset += write_size;
233 len -= write_size;
234 }
235
220 return CYG_FLASH_ERR_OK; 236 return CYG_FLASH_ERR_OK;
221 } 237 }
222 238
223 #define QUERY "Linux Synthetic Flash" 239 #define QUERY "Linux Synthetic Flash"
224 240
225 static size_t 241 static size_t
226 synth_flash_query(struct cyg_flash_dev *dev, void * data, 242 synth_flash_query(struct cyg_flash_dev *dev, void * data, size_t len)
227 size_t len) 243 {
228 { 244 memcpy(data, QUERY, sizeof(QUERY));
229 memcpy(data,QUERY,sizeof(QUERY));
230 return sizeof(QUERY); 245 return sizeof(QUERY);
231 } 246 }
232 247
233 const CYG_FLASH_FUNS(cyg_flash_synth_funs, 248 const CYG_FLASH_FUNS(cyg_flash_synth_funs,
234 synth_flash_init, 249 synth_flash_init,