Mercurial > ecos
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, |
