In microcontroller whit smal RAM's can't load hole images in the RAM...
So RedBoot need's to be able to write images direct to flash, and run it direct in the flash... This patch will allow the RedBoot load-command to write imgaes direct to the flash, create FIS-entrys from the writen images and "load" images from flash (set the entry address for the go-command)...
Usage: Set the CDL option CYGSEM_REDBOOT_FLASH_LOADS and make a RedBoot-image.Use "load -f -m xmodem" (if RAM-validation is enabled) or "load -m xmodem" (otherwise) whit all possible option's to load images direct to flash.
Use then "fis create -o flash_chaes" to create an image-entry whit the name "flash_chaes".
Later after a few reset's use "fis load -o flash_chaes" to load the entry address of the image again. After that, the go-command will start the image "flash_chaes" direct in the flash...
There are two additional patches: flash_init(printf) shold be able to change the diag-print-function at runtime. Otherwise "flash.c" will write to the host, if the load-command works on the same channel, like the download...
RedBoot should test his memory-workspace via an ASSERT()... Regards Oliver Munz
pack 01.diff
Description: Binary data
#ifndef ____memory_write___ #define ____memory_write___ #include <redboot.h> cyg_uint32 memory_write_init(void); bool flash_valid_address(cyg_uint8 *addr); bool memory_write_valid_address(cyg_uint8 *addr); bool memory_write(cyg_uint8 *addr, cyg_uint8 value); void memory_write_fini(void); #endif
#include <memory_write.h>
#include <stdlib.h>
#include <cyg/io/flash.h>
static int flash_block_size;
static int flash_blocks;
//static cyg_uint8 *flash_buffer = 0; /* Buffer for one Flash-Sector */
static cyg_uint8 *current_flash_segment = 0;
static bool memory_write_init_done = false; /* Allocation of the flash-sector
size RAM-buffer is done */
static bool memory_write_init_flash_written = false; /* memory_write() has at
least one call in the flash speace */
static int dbg_f_c; /* debug counters */
static int dbg_w_c;
#define flash_buffer memory_write_flash_buffer
int dummy_printf(const char *fmt, ...){ /* The Flash should shut up! */
return 0;
}
static cyg_uint32 *flash_block_begin(cyg_uint32 *addr){
return (cyg_uint32 *)((((cyg_uint32) addr) / flash_block_size) *
flash_block_size);
}
bool flash_valid_address(cyg_uint8 *addr){
return flash_verify_addr((cyg_uint32 *) addr) == FLASH_ERR_OK;
}
cyg_uint32 memory_write_init(void){
dbg_f_c = 0;
dbg_w_c = 0;
flash_init(dummy_printf);
flash_get_block_info(&flash_block_size, &flash_blocks);
// if (!flash_buffer){
// flash_buffer = zcalloc(0, flash_block_size, sizeof(cyg_uint8));
// }
memory_write_init_done = true;
memory_write_init_flash_written = false;
return flash_block_size;
}
bool memory_write_valid_address(cyg_uint8 *addr){
if (!memory_write_init_done){
diag_printf("ERROR: memory_write_valid_address():
!memory_write_init_done\n"); /* ERROR */
return false;
}
return valid_address(addr) || flash_valid_address(addr);
}
bool memory_write(cyg_uint8 *addr, cyg_uint8 value){
cyg_uint32 retcode = FLASH_ERR_OK;
cyg_uint32 err_addr;
if (!memory_write_init_done || !flash_buffer){
diag_printf("ERROR: memory_write(): !memory_write_init_done ||
!flash_buffer\n"); /* ERROR */
return false;
}
if (valid_address(addr)){ /* If the target address is in RAM */
*addr = value;
} else if (flash_valid_address((cyg_uint32 *) addr)){ /* If it's in
Flash */
if (!memory_write_init_flash_written){ /* First Byte for the
flash-space */
memcpy(flash_buffer, flash_block_begin((cyg_uint32 *)
addr), flash_block_size); /* Init buffer with defaults */
current_flash_segment = addr;
memory_write_init_flash_written = true;
dbg_f_c++;
} else {
if (flash_block_begin((cyg_uint32 *) addr) !=
flash_block_begin((cyg_uint32 *) current_flash_segment)){ /* If we are in the
next segment */
retcode =
flash_erase(flash_block_begin(current_flash_segment), flash_block_size,
&err_addr);
if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
diag_printf("ERROR: memory_write():
flash_erase(): %08x; addr: %08x\n", retcode, err_addr);/* ERROR */
return false;
}
retcode =
flash_program(flash_block_begin(current_flash_segment), flash_buffer,
flash_block_size, &err_addr); /* Write buffer to flash */
if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
diag_printf("ERROR: memory_write():
flash_program(): %08x; addr: %08x\n", retcode, err_addr);/* ERROR */
return false;
}
memcpy(flash_buffer,
flash_block_begin((cyg_uint32 *) addr), flash_block_size); /* Init buffer with
defaults */
current_flash_segment = addr;
dbg_w_c++;
}
}
*(cyg_uint8 *)((cyg_uint32) flash_buffer + ((cyg_uint32) addr)
% flash_block_size) = value;
} else { /* Wrong Address */
diag_printf("ERROR: memory_write(): Wrong Address: %08x\n",
addr); /* ERROR */
return false;
}
return true;
}
void memory_write_fini(void){
cyg_uint32 retcode = FLASH_ERR_OK;
cyg_uint32 err_addr;
if (memory_write_init_done && memory_write_init_flash_written &&
flash_buffer){
retcode = flash_erase(flash_block_begin(current_flash_segment),
flash_block_size, &err_addr);
if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
diag_printf("ERROR: memory_write_fini(): flash_erase():
%08x; addr: %08x\n", retcode, err_addr);/* ERROR */
}
retcode = flash_program(flash_block_begin(current_flash_segment),
flash_buffer, flash_block_size, &err_addr); /* Write buffer to flash */
if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
diag_printf("ERROR: memory_write_fini(): flash_program():
%08x; addr: %08x\n", retcode, err_addr);/* ERROR */
}
}
memory_write_init_done = false;
memory_write_init_flash_written = false;
// if (flash_buffer){
// zcfree(0, flash_buffer);
// flash_buffer = 0;
// }
flash_init(diag_printf);
}
