Mercurial > flash_v2
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 } |
