예제 #1
0
static bool do_flash_init(void)
{
	int stat;

	ram_start = (unsigned char *)CYGMEM_REGION_ram;
	ram_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
#ifdef CYGMEM_SECTION_heap1
	workspace_start = (unsigned char *)CYGMEM_SECTION_heap1;
	workspace_end = (unsigned char *)(CYGMEM_SECTION_heap1+CYGMEM_SECTION_heap1_SIZE);
	workspace_size = CYGMEM_SECTION_heap1_SIZE;
#endif
	if (!__flash_init) 
	{
		if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), 
														 FLASH_MIN_WORKSPACE, (_printf *)fisPrintf)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "FLASH: driver init failed: %s\n\r", flash_errmsg(stat));
			return false;
		}
		flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
		// Keep 'end' address as last valid location, to avoid wrap around problems
		flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
		flash_get_block_info(&flash_block_size, &flash_num_blocks);

		workspace_end = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE);
#ifdef CYGOPT_REDBOOT_FIS
#ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
		fis_work_block = fis_zlib_common_buffer;
		if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < flash_block_size)
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "FLASH: common buffer too small\n\r");
								workspace_end += FLASH_MIN_WORKSPACE;
			return false;
		}
#else
		workspace_end = (unsigned char *)(workspace_end-flash_block_size);
		fis_work_block = workspace_end;
#endif
		fisdir_size = flash_block_size;
		if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) 
		{
			fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
													(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
		} 
		else 
		{
			fis_addr = (void *)((CYG_ADDRESS)flash_start + 
													(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
		}
#endif
		__flash_init = 1;
	}
	return true;
}
예제 #2
0
파일: flash.c 프로젝트: cilynx/dd-wrt
bool
do_flash_init(void)
{
    int stat;

    if (!__flash_init) {
        __flash_init = 1;
        if ((stat = flash_init(diag_printf)) != 0) {
            diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
            return false;
        }
        flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
        // Keep 'end' address as last valid location, to avoid wrap around problems
        flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
        flash_get_block_info(&flash_block_size, &flash_num_blocks);
#ifdef CYGOPT_REDBOOT_FIS
        fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
        fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
# if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
	fis_work_block = fis_zlib_common_buffer;
	if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
            diag_printf("FLASH: common buffer too small\n");
            return false;
	}
# else
        workspace_end = (unsigned char *)(workspace_end-fisdir_size);
        fis_work_block = workspace_end;
# endif
        if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
            fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
        } else {
            fis_addr = (void *)((CYG_ADDRESS)flash_start + 
                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
        }
        if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
            diag_printf("FIS directory doesn't fit\n");
            return false;
        }
        fis_read_directory();
#endif
    }
    return true;
}
예제 #3
0
void cyg_user_start(void)
{
    int ret;
    char data[1024];
    void *flash_start, *flash_end;
    int block_size, blocks;
    char *prog_start;
    unsigned char * ptr;

    CYG_TEST_INIT();
  
    ret=flash_init(NULL,0,(_printf *)diag_printf);
  
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_init");

    flash_dev_query(data);
    CYG_TEST_PASS_FAIL(!strncmp(data,"Linux Synthetic Flash",sizeof(data)),
                       "flash_query"); 

    ret = flash_get_limits(NULL,&flash_start,&flash_end);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_get_limits");

    ret = flash_get_block_info(&block_size, &blocks);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_get_block_info");

    /* Erase the whole flash. Not recommended on real hardware since this
     will probably erase the bootloader etc!!! */
    ret=flash_erase(flash_start,block_size * blocks,NULL);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_erase1");

    /* check that its actually been erased, and test the mmap area */
    for (ptr=flash_start,ret=0; ptr < (unsigned char *)flash_end; ptr++) {
        if (*ptr != 0xff) {
            ret++;
        }
    }
  
    CYG_TEST_PASS_FAIL((ret == 0),"flash empty check");

    ret = flash_program(flash_start,&copyright,sizeof(copyright),NULL);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_program1");
  
    /* Check the contents made it into the flash */
    CYG_TEST_PASS_FAIL(!strncmp(flash_start,copyright,sizeof(copyright)),
                       "flash program contents");

    /* .. and check nothing else changed */
    for (ptr=(unsigned char *)flash_start+sizeof(copyright),ret=0; 
         ptr < (unsigned char *)flash_end; ptr++) {
        if (*ptr != 0xff) {
            ret++;
        }
    }
  
    CYG_TEST_PASS_FAIL((ret == 0),"flash program overrun check");

    /* Program over a block boundary */
    prog_start = (unsigned char *)flash_start + block_size - sizeof(copyright)/2;
    ret = flash_program(prog_start,&copyright,sizeof(copyright),NULL);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_program2");
  
    /* Check the first version is still OK */
    CYG_TEST_PASS_FAIL(!strncmp(flash_start,copyright,sizeof(copyright)),
                       "Original contents");
  
    CYG_TEST_PASS_FAIL(!strncmp(prog_start,copyright,sizeof(copyright)),
                       "New program contents");

    /* Check the bit in between is still erased */
    for (ptr=(unsigned char *)flash_start+sizeof(copyright),ret=0; 
         ptr < (unsigned char *)prog_start; ptr++) {
        if (*ptr != 0xff) {
            ret++;
        }
    }
    CYG_TEST_PASS_FAIL((ret == 0),"flash erase check1");
  
    /* Erase the second block and make sure the first is not erased */
    ret=flash_erase((void *)((unsigned)flash_start+block_size),
                    block_size,NULL);
    CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_erase2");

    /* Check the erase worked */
    for (ptr=(unsigned char *)flash_start+block_size,ret=0; 
         ptr < (unsigned char *)flash_start+block_size*2; ptr++) {
        if (*ptr != 0xff) {
            ret++;
        }
    }

    CYG_TEST_PASS_FAIL((ret == 0), "flash erase check2");
  
    /* Lastly check the first half of the copyright message is still there */
    CYG_TEST_PASS_FAIL(!strncmp(prog_start,copyright,sizeof(copyright)/2),
                       "Block 1 OK");

#if 0
    /* This test it fatal! Its not run by default!
     Check the flash is read only, by trying to write to it. We expect
     to get an exception */

    *(char *)flash_start = 'a';
#endif

    CYG_TEST_PASS_FINISH("flash1");
}
예제 #4
0
externC void
cyg_start( void )
{
    int stat;
    void *err_addr;
    CYG_ADDRWORD flash_start, flash_end;
    void **flash_start_addr = (void *)&flash_start;
    void **flash_end_addr = (void *)&flash_end;
    void *flash_test_start, *flash_addr;
    cyg_int32 flash_block_size, flash_num_blocks;
    CYG_ADDRWORD test_buf1, test_buf2;
    cyg_uint32 *lp1, *lp2;
    int i, len;
    cyg_bool passed, ok;

    CYG_TEST_INIT();

#if 0
    int j;
    
    diag_printf("Testing udelay: ");
    for (i = 0;  i < 30;  i++) {
        for (j = 0;  j < 1000;  j++) {
            CYGACC_CALL_IF_DELAY_US(1000);  // Should be 1 second
        }
        diag_printf(".");
    }
    diag_printf("\n");
#endif

    passed = true;

    if ((stat = flash_init(diag_printf)) != 0) {
        diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
        CYG_TEST_FAIL_FINISH("FLASH driver init failed");
    }
    flash_get_limits((void *)0, flash_start_addr, flash_end_addr);
    // Keep 'end' address as last valid location, to avoid wrap around problems
    flash_end = flash_end - 1;
    flash_get_block_info(&flash_block_size, &flash_num_blocks);

    diag_printf("FLASH: 0x%x - 0x%x, %d blocks of 0x%x bytes each.\n", 
                flash_start, flash_end + 1, flash_num_blocks, 
                flash_block_size);

    // Verify that the testing limits are within the bounds of the
    // physical device.  Also verify that the size matches with
    // the erase block size on the device
    if ((CYGNUM_IO_FLASH_TEST_OFFSET > (flash_end - flash_start)) ||
        ((CYGNUM_IO_FLASH_TEST_OFFSET + CYGNUM_IO_FLASH_TEST_LENGTH) > (flash_end - flash_start))) {
        CYG_TEST_FAIL_FINISH("FLASH test region outside physical limits");
    }
    if ((CYGNUM_IO_FLASH_TEST_LENGTH % flash_block_size) != 0) {
        CYG_TEST_FAIL_FINISH("FLASH test region must be integral multiple of erase block size");
    }

    // Allocate two buffers large enough for the test
    test_buf1 = (CYG_ADDRWORD)CYGMEM_SECTION_heap1;
    test_buf2 = test_buf1 + CYGNUM_IO_FLASH_TEST_LENGTH;
    if (CYGMEM_SECTION_heap1_SIZE < (CYGNUM_IO_FLASH_TEST_LENGTH * 2)) {
        CYG_TEST_FAIL_FINISH("FLASH not enough heap space - reduce size of test region");
    }
    diag_printf("... Using test buffers at %p and %p\n", (void *)test_buf1, (void *)test_buf2);
    flash_test_start = (void *)(flash_start + CYGNUM_IO_FLASH_TEST_OFFSET);

#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING    
    // Unlock test
    diag_printf("... Unlock test\n");
    ok = true;
    if ((stat = flash_unlock(flash_test_start, 
                             CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
#endif
    
    // Erase test
    diag_printf("... Erase test\n");
    ok = true;
    if ((stat = flash_erase(flash_test_start, 
                            CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: erase failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    if (ok && (stat = flash_read(flash_test_start, (void *)test_buf1,
                           CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: read/verify after erase failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    lp1 = (cyg_uint32 *)test_buf1;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        if (*lp1++ != 0xFFFFFFFF) {
            diag_printf("FLASH: non-erased data found at offset %x\n", (CYG_ADDRWORD)(lp1-1) - test_buf1);
            diag_dump_buf((void *)(lp1-1), 32);
            ok = false;
            break;
        }
    }
    // Try reading in little pieces
    len = CYGNUM_IO_FLASH_TEST_LENGTH;
    flash_addr = flash_test_start;
    while (len > 0) {
        if ((stat = flash_read(flash_addr, (void *)test_buf1, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) {
            diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat));
            ok = false;
            break;
        }    
        flash_addr = (cyg_uint8 *)flash_addr + 0x200;
        len -= 0x200;
        lp1 = (cyg_uint32 *)test_buf1;
        for (i = 0;  i < 0x200;  i += sizeof(cyg_uint32)) {
            if (*lp1++ != 0xFFFFFFFF) {
                diag_printf("FLASH: non-erased data found at offset %p\n", 
                            (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp1-1) - test_buf1));
                diag_dump_buf((void *)(lp1-1), 32);
                ok = false;
                len = 0;
                break;
            }
        }
    }
    
    if (!ok) {
        CYG_TEST_INFO("FLASH erase failed");
        passed = false;
    }

    // Simple write/verify test
    diag_printf("... Write/verify test\n");
    lp1 = (cyg_uint32 *)test_buf1;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        *lp1 = (cyg_uint32)lp1;
        lp1++;
    }
    ok = true;
    if (ok && (stat = flash_program(flash_test_start, (void *)test_buf1,
                                    CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: write failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    if (ok && (stat = flash_read(flash_test_start, (void *)test_buf2,
                                    CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: read/verify after write failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    lp1 = (cyg_uint32 *)test_buf1;
    lp2 = (cyg_uint32 *)test_buf2;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        if (*lp2++ != *lp1++) {
            diag_printf("FLASH: incorrect data found at offset %x\n", (CYG_ADDRWORD)(lp2-1) - test_buf2);
            diag_dump_buf((void *)(lp2-1), 32);
            ok = false;
            break;
        }
    }
    // Try reading in little pieces
    len = CYGNUM_IO_FLASH_TEST_LENGTH;
    flash_addr = flash_test_start;
    lp1 = (cyg_uint32 *)test_buf1;
    lp2 = (cyg_uint32 *)test_buf2;
    while (len > 0) {
        if ((stat = flash_read(flash_addr, lp2, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) {
            diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat));
            ok = false;
            break;
        }    
        flash_addr = (cyg_uint8 *)flash_addr + 0x200;
        len -= 0x200;
        for (i = 0;  i < 0x200;  i += sizeof(cyg_uint32)) {
            if (*lp2++ != *lp1++) {
                diag_printf("FLASH: incorrect data found at offset %p\n", 
                            (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp2-1) - test_buf2));
                diag_dump_buf((void *)(lp2-1), 32);
                ok = false;
                len = 0;
                break;
            }
        }
    }
    
    if (!ok) {
        CYG_TEST_INFO("FLASH write/verify failed");
    }

#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
    // Lock test
    diag_printf("... Lock test\n");
    ok = true;
    if ((stat = flash_lock(flash_test_start, 
                           CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
#endif
    
    if (passed) {
        CYG_TEST_PASS_FINISH("FLASH test1");
    } else {
        CYG_TEST_FAIL_FINISH("FLASH test1");
    }
}