comparison packages/io/flash/current/src/flash.c @ 1723:0cc13d07a67e

* src/flash.c: Support flash blocks of arbitary size. The DataFlash devices for example have block of 528 bytes.
author asl
date Thu, 09 Sep 2004 13:11:46 +0000
parents c4240af0fa28
children e290a0372578
comparison
equal deleted inserted replaced
1722:c4240af0fa28 1723:0cc13d07a67e
341 if (!dev) return CYG_FLASH_ERR_INVALID; 341 if (!dev) return CYG_FLASH_ERR_INVALID;
342 342
343 return flash_block_size(dev, flash_base); 343 return flash_block_size(dev, flash_base);
344 } 344 }
345 345
346 // Return the first address of a block. The flash might not be aligned
347 // in terms of its block size. So we have to be careful and use
348 // offsets.
349 static inline cyg_flashaddr_t
350 flash_block_begin(cyg_flashaddr_t addr, struct cyg_flash_dev *dev)
351 {
352 size_t block_size;
353 cyg_flashaddr_t offset;
354
355 block_size = flash_block_size(dev, addr);
356
357 offset = addr - dev->start;
358 offset = (offset / block_size) * block_size;
359 return offset + dev->start;
360 }
361
346 362
347 __externC int 363 __externC int
348 cyg_flash_erase(const cyg_flashaddr_t flash_base, 364 cyg_flash_erase(const cyg_flashaddr_t flash_base,
349 const size_t len, 365 const size_t len,
350 cyg_flashaddr_t *err_address) 366 cyg_flashaddr_t *err_address)
375 end_addr = flash_base + len - 1; 391 end_addr = flash_base + len - 1;
376 if (end_addr > dev->end) { 392 if (end_addr > dev->end) {
377 end_addr = dev->end; 393 end_addr = dev->end;
378 } 394 }
379 395
380 block_size = flash_block_size(dev, addr); 396 block = flash_block_begin(addr, dev);
381 block = (cyg_flashaddr_t)((size_t)addr & ~(block_size - 1));
382 397
383 #ifdef CYGSEM_IO_FLASH_CHATTER 398 #ifdef CYGSEM_IO_FLASH_CHATTER
384 dev->pf("... Erase from %p-%p: ", (void*)block, (void*)end_addr); 399 dev->pf("... Erase from %p-%p: ", (void*)block, (void*)end_addr);
385 #endif 400 #endif
386 401
388 FLASH_Enable(block, end_addr); 403 FLASH_Enable(block, end_addr);
389 while (block <= end_addr) { 404 while (block <= end_addr) {
390 int i; 405 int i;
391 unsigned char *dp; 406 unsigned char *dp;
392 bool erased = true; 407 bool erased = true;
408
409 block_size = flash_block_size(dev, addr);
393 410
394 // If there is a read function it probably means the flash 411 // If there is a read function it probably means the flash
395 // cannot be read directly. 412 // cannot be read directly.
396 if (!dev->funs->flash_read) { 413 if (!dev->funs->flash_read) {
397 dp = (unsigned char *)block; 414 dp = (unsigned char *)block;
410 } 427 }
411 if (CYG_FLASH_ERR_OK != stat && err_address) { 428 if (CYG_FLASH_ERR_OK != stat && err_address) {
412 *err_address = block; 429 *err_address = block;
413 break; 430 break;
414 } 431 }
415 block += flash_block_size(dev, block); 432 block += block_size;
416 #ifdef CYGSEM_IO_FLASH_CHATTER 433 #ifdef CYGSEM_IO_FLASH_CHATTER
417 dev->pf("."); 434 dev->pf(".");
418 #endif 435 #endif
419 } 436 }
420 FLASH_Disable(block, end_addr); 437 FLASH_Disable(block, end_addr);
486 size = length; 503 size = length;
487 // Only one block at once 504 // Only one block at once
488 if (size > block_size) size = block_size; 505 if (size > block_size) size = block_size;
489 506
490 // Writing from the middle of a block? 507 // Writing from the middle of a block?
491 offset = (size_t)addr & (block_size-1); 508 offset = (size_t)addr % block_size;
492 if (offset) 509 if (offset)
493 size = MIN(block_size - offset, size); 510 size = MIN(block_size - offset, size);
494 stat = dev->funs->flash_program(dev, addr, ram, size); 511 stat = dev->funs->flash_program(dev, addr, ram, size);
495 stat = dev->funs->flash_hwr_map_error(dev,stat); 512 stat = dev->funs->flash_hwr_map_error(dev,stat);
496 #ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM 513 #ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
574 size = length; 591 size = length;
575 // Only one block at once 592 // Only one block at once
576 if (size > block_size) size = block_size; 593 if (size > block_size) size = block_size;
577 594
578 // Reading from the middle of a block? 595 // Reading from the middle of a block?
579 offset = (size_t)addr & (block_size-1); 596 offset = (size_t)addr % block_size;
580 if (offset) 597 if (offset)
581 size = MIN(block_size - offset, size); 598 size = MIN(block_size - offset, size);
582 if (dev->funs->flash_read) { 599 if (dev->funs->flash_read) {
583 stat = dev->funs->flash_read(dev, addr, ram, size); 600 stat = dev->funs->flash_read(dev, addr, ram, size);
584 stat = dev->funs->flash_hwr_map_error(dev,stat); 601 stat = dev->funs->flash_hwr_map_error(dev,stat);
649 end_addr = flash_base + len - 1; 666 end_addr = flash_base + len - 1;
650 if (end_addr > dev->end) { 667 if (end_addr > dev->end) {
651 end_addr = dev->end; 668 end_addr = dev->end;
652 } 669 }
653 670
654 block_size = flash_block_size(dev, addr); 671 block = flash_block_begin(addr, dev);
655 block = (cyg_flashaddr_t)((size_t)addr & ~(block_size - 1));
656 672
657 #ifdef CYGSEM_IO_FLASH_CHATTER 673 #ifdef CYGSEM_IO_FLASH_CHATTER
658 dev->pf("... Locking from %p-%p: ", (void*)block, (void*)end_addr); 674 dev->pf("... Locking from %p-%p: ", (void*)block, (void*)end_addr);
659 #endif 675 #endif
660 676
683 #endif 699 #endif
684 if (stat != CYG_FLASH_ERR_OK) { 700 if (stat != CYG_FLASH_ERR_OK) {
685 return stat; 701 return stat;
686 } 702 }
687 703
688 if (flash_base + len - 1 > dev->end) { // Off by one? 704 if (flash_base + len - 1 > dev->end) {
689 // The region to erase if bigger than this driver handles. Recurse 705 // The region to erase if bigger than this driver handles. Recurse
690 return cyg_flash_lock(dev->end+1, 706 return cyg_flash_lock(dev->end+1,
691 len - (dev->end - flash_base) - 1, 707 len - (dev->end - flash_base) - 1,
692 err_address); 708 err_address);
693 } 709 }
726 end_addr = flash_base + len - 1; 742 end_addr = flash_base + len - 1;
727 if (end_addr > dev->end) { 743 if (end_addr > dev->end) {
728 end_addr = dev->end; 744 end_addr = dev->end;
729 } 745 }
730 746
731 block_size = flash_block_size(dev, addr); 747 block = block = flash_block_begin(addr, dev);
732 block = (cyg_flashaddr_t)((size_t)addr & ~(block_size - 1));
733 748
734 #ifdef CYGSEM_IO_FLASH_CHATTER 749 #ifdef CYGSEM_IO_FLASH_CHATTER
735 dev->pf("... Unlocking from %p-%p: ", (void*)block, (void*)end_addr); 750 dev->pf("... Unlocking from %p-%p: ", (void*)block, (void*)end_addr);
736 #endif 751 #endif
737 752
760 #endif 775 #endif
761 if (stat != CYG_FLASH_ERR_OK) { 776 if (stat != CYG_FLASH_ERR_OK) {
762 return stat; 777 return stat;
763 } 778 }
764 779
765 if (flash_base + len - 1 > dev->end) { // Off by one? 780 if (flash_base + len - 1 > dev->end) {
766 // The region to erase if bigger than this driver handles. Recurse 781 // The region to erase if bigger than this driver handles. Recurse
767 return cyg_flash_lock(dev->end+1, 782 return cyg_flash_lock(dev->end+1,
768 len - (dev->end - flash_base) - 1, 783 len - (dev->end - flash_base) - 1,
769 err_address); 784 err_address);
770 } 785 }