Exemple #1
0
int32_t flash_program2(const uint32_t &addr, const uint32_t &len, const uint8_t *data)
{
	uint32_t i, laddr = addr;

	// add offset
	if (laddr>=FLASH_BEGIN && laddr<=FLASH_END)
		laddr += FLASH_OFFSET;

	// check range
	if (laddr<FLASH_BEGIN_B || laddr>FLASH_END_B || laddr+len>FLASH_END_B)
		return -1;

	// erase all sectors spanned by this segment
	for (i=FLASH_SECTOR_MASK(laddr); i<laddr+len; i+=FLASH_SECTOR_SIZE)
	{
		if (erase(i)<0)
			return -3;
	}
	
	if (flash_program(laddr, data, len)<0)
		return -2;

	// verify
	for (i=0; i<len; i++)
	{
		if (*(uint8_t *)(laddr+i) != data[i])
			return -4;
	}

	return 0;
}
Exemple #2
0
int store_iap(const void *pbuf,unsigned short len)
{
	unsigned int addr;
	if(icount.size+len>CODE_SIZE){
		//PrintLog(LOGTYPE_SHORT,"iap flash overflow\n");
		return -1;
	}
	if(icount.records>=UPDATE_RECORDS){
		//PrintLog(LOGTYPE_SHORT,"iap records overflow\n");
		return -1;
	}
	
	//代码写到Flash-------------------------------------------------------------
	addr = UPDATE_CODE_ADDR+icount.size;
	flash_program(addr,pbuf,len);
	
	
	//写记录数据----------------------------------------------------------------
	irecord.offset = icount.size;
	irecord.bytes = len;
	irecord.codecrc = calculate_crc(pbuf,len);
	addr = UPDATE_RECORD_ADDR;
	addr = UPDATE_RECORD_ADDR+UPDATE_RECORD_SIZE*icount.records;
	f_program(addr,&irecord,sizeof(irecord));
	
	icount.size+=len;
	icount.records++;
	//PrintLog(LOGTYPE_SHORT,"save code frame:%d,size:%d",icount.records,icount.size);
	return 0;
}
Exemple #3
0
int
hal_flash_program(void *addr, void *data, int len, void **err)
{
    int swabbed = 0;
    cyg_uint32 *p;
    int i, retval;

    if (is_swabbed_redboot(addr, data)
#if (CYG_BYTEORDER == CYG_LSBFIRST) && defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_MSBFIRST)
#ifdef CYGOPT_REDBOOT_FIS
	|| addr == fis_addr
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
	|| addr == cfg_base
#endif
#endif
	) {
	swabbed = 1;
	for (i = 0, p = data; i < len; i += 4, ++p)
	    *p = CYG_SWAP32(*p);
    }

    retval = flash_program(addr, data, len, err);

    if (swabbed) {
	for (i = 0, p = data; i < len; i += 4, ++p)
	    *p = CYG_SWAP32(*p);
    }

    return retval;
}
Exemple #4
0
static Cyg_ErrNo
flashiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
                   cyg_uint32 pos )
{   
	struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
	struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;

    Cyg_ErrNo err = ENOERR;
    void *erraddr;
    char *startpos = dev->start + pos;

#ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time
    char *endpos = startpos + *len - 1;
    char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1);
    if ( startpos < dev->start )
        return -EINVAL;
    if ( endpos > flashend )
        return -EINVAL;
#endif
    err = flash_program( startpos, 
                         (void *)buf, *len, &erraddr );

    if ( err )
        err = -EIO; // just something sane
    return err;
} // flashiodev_bwrite()
Exemple #5
0
/* program data_addr[0-data_size] to dev, starting addr's offset is flash_offset*/
int flash_write(struct flash_device *dev, u32 flash_offset, char *data_addr, size_t data_size)
{
	int ret;
	u8  *tmp_buf; // for store flash content which will be use later
	size_t pre_size;	
	ulong real_start_addr;
	ulong start_addr = dev->vaddr + flash_offset;
	
	real_start_addr = head_erase_align(dev, start_addr);  	
	pre_size = start_addr - real_start_addr;
	
	tmp_buf = malloc(pre_size + data_size); 
	if(tmp_buf == NULL)	{
		printf("out of memory!\n");
		return -ENOMEM;
	}
	/*save the pre data, clear the following data in tht sector*/
	memcpy((void *)tmp_buf, (void *)real_start_addr, pre_size);
	memcpy((void *)tmp_buf + pre_size, (void *)data_addr, data_size);

	ret = flash_erase(dev, real_start_addr, (start_addr + data_size -1));
	if(ret <= 0){
		printf("erase failed, exit!");
		return 0;
	}
	flash_program(dev, real_start_addr, (start_addr + data_size -1), tmp_buf);	
	return 0;
}
Exemple #6
0
int32_t prm_setChirp(const char *id, const uint32_t &valLen, const uint8_t *val)
{
	ParamRecord *rec;
	uint8_t *buf;
	uint32_t offset;
	void *sector;
	int32_t res = 0;

	rec = prm_find(id);

	if (rec==NULL)
	{
		// Good god this is an ugly hack.  But, creating parameters should only be handled from within the firmware, so that the correct
		// description can be inserted.  There may be other parameters like this, such that when these parameters are lost, we want to resave,
		// in which case, we should formalize this hack somehow.
		if (strncmp(id, "Signature label", 15)==0)
		{
			char desc[100];
			sprintf(desc, "@c Signature_Labels Sets the label for objects that match signature%s.", id+15);
			prm_add(id, 0, desc, val[0], val+1, END);
			return 0;
		}
		return -1;
	}

	buf = (uint8_t *)malloc(FLASH_SECTOR_SIZE);
   	
	if (buf==NULL)
		return -2;

	sector = (void *)FLASH_SECTOR_MASK((uint32_t)rec);
	memcpy(buf, sector, FLASH_SECTOR_SIZE);

	rec = prm_find(id, buf);

	if (rec==NULL)
	{
		res = -1;
		goto end;
	}

	offset = prm_getDataOffset(rec);	
	if (memcmp((uint8_t *)rec+offset, val, valLen)==0)
		goto end;
	memcpy((uint8_t *)rec+offset, val, valLen);
	 	
	rec->len = valLen;
	rec->crc = prm_crc(rec);
	
	flash_erase((uint32_t)sector, FLASH_SECTOR_SIZE); 
	flash_program((uint32_t)sector, buf, FLASH_SECTOR_SIZE);


end:
	free(buf); 	
	return res;
}
Exemple #7
0
int
write_eeprom(ADDR start_addr, const void *data_arg, int data_size)
{
    void *err_addr;

    if (flash_program((void *)start_addr, data_arg, data_size, &err_addr) != 0) {
	cmd_stat = E_EEPROM_FAIL;
	return ERR;
    }
    return OK;
}
Exemple #8
0
int prm_add(const char *id, uint32_t flags, const char *desc, ...)
{
	char buf[PRM_MAX_LEN];
	int len;
    uint32_t freeLoc, offset=PRM_HEADER_LEN;
    va_list args;
	ParamRecord *rec = (ParamRecord *)buf;

	// if it already exists, 
	if (prm_find(id))
		return -2;

	memset((void *)rec, 0, PRM_MAX_LEN);

	strcpy((char *)rec+offset, id);
	offset += strlen(id) + 1;
	if (desc!=NULL)
	{
		strcpy((char *)rec+offset, desc);
		offset += strlen(desc) + 1;
	}
	else
	{
		*(char *)(rec+offset) = '\0';
	 	offset++;
	}

	// data section should be aligned to 4 bytes	
	ALIGN(offset, 4);

    va_start(args, desc);
    len = Chirp::vserialize(NULL, (uint8_t *)rec+offset, PRM_MAX_LEN-offset, &args);
    va_end(args);

	if (len<0)
		return -3;

	rec->flags = flags;
	rec->len = len;
	rec->crc = prm_crc(rec); 

	if ((freeLoc=prm_nextFree())==NULL)
		return -4;
	
	return flash_program(freeLoc, (uint8_t *)rec, len+prm_getDataOffset(rec));	
}
/** Program a set of addresses of the STM32F4 flash memory.
 * Note : sector containing addresses must be erased before addresses can be
 * programmed.
 *
 * \param address Starting address of set to program
 * \param data    Data to program addresses with
 * \param length  Length of set of addresses to program - counts up from
 *                starting address
 * \return Error code
 */
u8 stm_flash_program(u32 address, u8 data[], u8 length)
{
  /* Check that arguments are valid. */
  if (address > STM_FLASH_MAX_ADDR)
    return FLASH_INVALID_ADDR;
  if (address < STM_FLASH_MIN_ADDR)
    return FLASH_INVALID_ADDR;
  if (address+length-1 > STM_FLASH_MAX_ADDR)
    return FLASH_INVALID_RANGE;

  /* Program specified addresses with data */
  flash_unlock();
  flash_program(address, data, length);
  flash_lock();

  return FLASH_OK;
}
//! Запись файла.
modbus_rtu_error_t boot_modbus_rtu_on_write_file_record(uint16_t file, uint16_t record, uint16_t count, const uint16_t* values)
{
    switch(file){
        default:
            return MODBUS_RTU_ERROR_INVALID_ADDRESS;
        case BOOT_MODBUS_FILE_PAGE:{
            if((record + count) > (flash_page_size_bytes() / 2)) return MODBUS_RTU_ERROR_INVALID_ADDRESS;
            if(!flash_unlock()) return MODBUS_RTU_ERROR_NONRECOVERABLE;
            uint32_t address = flash_page_address(boot_modbus.page_number) + (uint32_t)record * sizeof(uint16_t);
            uint16_t i;
            for(i = 0; i < count; i ++, address += 2){
                if(!flash_program(address, values[i])){
                    flash_lock();
                    return MODBUS_RTU_ERROR_NONRECOVERABLE;
                }
            }
            flash_lock();
            }break;
    }
    
    return MODBUS_RTU_ERROR_NONE;
}
// Program the current page into flash.
void flash_load_finish(void)
{
  cyg_uint32 retcode = FLASH_ERR_OK;
  void * err_addr;
  
  if (init_done && flash_page_init) {
    flash_page_init = false;
    
    retcode = flash_erase(current_flash_page, flash_block_size, &err_addr);
    if (retcode != FLASH_ERR_OK){
      diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode));
    } else {
      retcode = flash_program(current_flash_page, flash_buffer, 
                              flash_block_size, &err_addr);
      if (retcode != FLASH_ERR_OK){ 
        diag_printf("Error writing at %p: %s\n", 
                    err_addr, flash_errmsg(retcode));
      }
    }
  }
  flash_init(diag_printf);
}
// Write a byte into flash. We maintain a copy in RAM of the FLASH
// page we are currently "writing" into. This copy is loaded with the
// current contents of the FLASH page when the first byte is "written"
// to the page. The "writes" are then made into the RAM copy. We only
// write to FLASH when there is a "write" outside of the current page,
// or the flash_load_finish function is called.
void flash_load_write(cyg_uint8 *flash_addr, cyg_uint8 value)
{
  
  cyg_uint32 retcode = FLASH_ERR_OK;
  void * err_addr;
  cyg_uint32 addr = (cyg_uint32)flash_addr;
  cyg_uint32 offset;
  
  if (!flash_page_init) { 
    /* First Byte for the current flash block. Read the current contents */
    current_flash_page = flash_block_begin(addr);
    flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); 
    flash_page_init = true;
  } 
  if (flash_block_begin(addr) != current_flash_page) { 
    /* We have moved into the next flash page. Write the current
       page so we can move on */
    retcode = flash_erase(current_flash_page, flash_block_size, &err_addr);
    if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
      diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode));
      return;
    }
    
    retcode = flash_program(current_flash_page, flash_buffer, 
                            flash_block_size, &err_addr); 
    if (retcode != FLASH_ERR_OK){ 
      diag_printf("Error writing at %p: %s\n", 
                  err_addr, flash_errmsg(retcode));
      return;
    }
    current_flash_page = flash_block_begin(addr);
    flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr);
  }
  
  offset = flash_addr - current_flash_page;
  CYG_ASSERT(offset < flash_block_size, "offset not inside flash block");
  
  flash_buffer[offset] = value;
}
Exemple #13
0
void main(void) 
{
   /* Port F Bit 1 active when error occurs */
   PTFDD |= 0x01;
   PTFD |= 0x01;

   EnableInterrupts;

   flash_init();
  
   copyinRAM();                       /* Copy flash routine to RAM */
  
   if (flash_erase( 0xF800))          /* Erase flash sector */
      PTFD &= ~0x01;
   if (flash_program( 0xF800, data))  /* Program single byte*/
      PTFD &= ~0x01;
  
  for( ; ; ) {
    __RESET_WATCHDOG();

  }  /* Loop always */
}
Exemple #14
0
int32_t prm_setChirp(const char *id, const uint32_t &valLen, const uint8_t *val)
{
	ParamRecord *rec;
	uint8_t *buf;
	uint32_t offset;
	void *sector;

	buf = (uint8_t *)malloc(FLASH_SECTOR_SIZE);

	if (buf==NULL)
		return -2;

	rec = prm_find(id);

	if (rec==NULL)
		return -1;

	sector = (void *)FLASH_SECTOR_MASK((uint32_t)rec);
	memcpy(buf, sector, FLASH_SECTOR_SIZE);

	rec = prm_find(id, buf);

	if (rec==NULL)
		return -1;

	offset = prm_getDataOffset(rec);	
	memcpy((uint8_t *)rec+offset, val, valLen);
	 	
	rec->len = valLen;
	rec->crc = prm_crc(rec);
	
	flash_erase((uint32_t)sector, FLASH_SECTOR_SIZE); 
	flash_program((uint32_t)sector, buf, FLASH_SECTOR_SIZE);

	free(buf); 	
	return 0;
}
Exemple #15
0
void doFlash(){
	uint32_t addr=0x0;
	uint32_t sw=0x1;
	uint8_t data[256];
	uint8_t x=0;

	flashInit();

	lcdClear(0xff);
	lcdPrint("xxd @ "); lcdPrint(IntToStr(addr,8,F_HEX));lcdNl();
	lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();
	lcdDisplay();

	while(1){
		TOGGLE(LED1);
		switch(getInput()){
			case BTN_UP:
				/* addr-=sw;
				lcdClear(0xff);
				lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl();
				lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();
				lcdDisplay(); */
				flash_write_enable();
				lcdPrint("WE done.");
				lcdDisplay();
				break;
			case BTN_DOWN:
				addr+=sw;
				lcdClear(0xff);
				lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl();
				lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();
				lcdDisplay();
				break;
			case BTN_LEFT:
				/*sw<<=1;
				lcdClear(0xff);
				lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl();
				lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();
				lcdDisplay(); */
				lcdPrint(IntToStr(flash_status1(),2,F_HEX));
				lcdPrint(" ");
				lcdPrint(IntToStr(flash_status2(),2,F_HEX));
				lcdNl();lcdDisplay();
				break;
			case BTN_RIGHT:
				/*sw>>=1;
				lcdClear(0xff);
				lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl();
				lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();
				lcdDisplay(); */
				data[0]=0xfe;
				data[1]=0xf8;
				flash_program(addr,0x2,data);
				lcdPrint("done.");
				lcdNl();
				lcdDisplay(); 
				break;
			case BTN_ENTER:
				lcdClear(0xff);
				lcdPrint("xxd @ "); lcdPrint(IntToStr(addr,8,F_HEX));lcdNl();
				lcdPrint("      "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl();

				flash_read(addr,0x100,data);

				int ctr;
				for (ctr=0x00;ctr<0x024;ctr++){
					if (ctr%4==0){
						lcdNl();
						lcdPrint(IntToStr(ctr,2,F_HEX));
						lcdPrint(":");
					};
					lcdPrint(" ");
					lcdPrint(IntToStr(data[ctr],2,F_HEX));
				};
				lcdNl();
				lcdDisplay(); 
				break;
		};
	};
};
Exemple #16
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");
}
Exemple #17
0
static void cmd_handler(uint8_t dlci, struct msgb *msg)
{
	if (msg->data_len < 1) {
		return;
	}

	uint8_t command = msgb_pull_u8(msg);

	int res = 0;

	flash_lock_t lock;

	void *data;

	uint8_t chip;
	uint8_t nbytes;
	uint16_t crc, mycrc;
	uint32_t address;

	struct msgb *reply = sercomm_alloc_msgb(256);	// XXX

	if (!reply) {
		printf("Failed to allocate reply buffer!\n");
		goto out;
	}

	switch (command) {

	case LOADER_PING:
		loader_send_simple(reply, dlci, LOADER_PING);
		break;

	case LOADER_RESET:
		loader_send_simple(reply, dlci, LOADER_RESET);
		device_reset();
		break;

	case LOADER_POWEROFF:
		loader_send_simple(reply, dlci, LOADER_POWEROFF);
		device_poweroff();
		break;

	case LOADER_ENTER_ROM_LOADER:
		loader_send_simple(reply, dlci, LOADER_ENTER_ROM_LOADER);
		device_enter_loader(1);
		break;

	case LOADER_ENTER_FLASH_LOADER:
		loader_send_simple(reply, dlci, LOADER_ENTER_FLASH_LOADER);
		device_enter_loader(0);
		break;

	case LOADER_MEM_READ:

		nbytes = msgb_pull_u8(msg);
		address = msgb_pull_u32(msg);

		crc = osmo_crc16(0, (void *)address, nbytes);

		msgb_put_u8(reply, LOADER_MEM_READ);
		msgb_put_u8(reply, nbytes);
		msgb_put_u16(reply, crc);
		msgb_put_u32(reply, address);

		memcpy(msgb_put(reply, nbytes), (void *)address, nbytes);

		sercomm_sendmsg(dlci, reply);

		break;

	case LOADER_MEM_WRITE:

		nbytes = msgb_pull_u8(msg);
		crc = msgb_pull_u16(msg);
		address = msgb_pull_u32(msg);

		data = msgb_pull(msg, nbytes) - nbytes;

		mycrc = osmo_crc16(0, data, nbytes);

		if (mycrc == crc) {
			memcpy((void *)address, data, nbytes);
		}

		msgb_put_u8(reply, LOADER_MEM_WRITE);
		msgb_put_u8(reply, nbytes);
		msgb_put_u16(reply, mycrc);
		msgb_put_u32(reply, address);

		sercomm_sendmsg(dlci, reply);

		break;

	case LOADER_JUMP:

		address = msgb_pull_u32(msg);

		msgb_put_u8(reply, LOADER_JUMP);
		msgb_put_u32(reply, address);

		sercomm_sendmsg(dlci, reply);

		device_jump((void *)address);

		break;

	case LOADER_FLASH_INFO:

		msgb_put_u8(reply, LOADER_FLASH_INFO);
		msgb_put_u8(reply, 1);	// nchips

		// chip 1
		msgb_put_u32(reply, (uint32_t)the_flash.f_base);
		msgb_put_u32(reply, the_flash.f_size);
		msgb_put_u8(reply, the_flash.f_nregions);

		unsigned i;
		for (i = 0; i < the_flash.f_nregions; i++) {
			msgb_put_u32(reply, the_flash.f_regions[i].fr_bnum);
			msgb_put_u32(reply, the_flash.f_regions[i].fr_bsize);
		}

		sercomm_sendmsg(dlci, reply);

		break;

	case LOADER_FLASH_ERASE:
	case LOADER_FLASH_UNLOCK:
	case LOADER_FLASH_LOCK:
	case LOADER_FLASH_LOCKDOWN:

		chip = msgb_pull_u8(msg);
		address = msgb_pull_u32(msg);

		if (command == LOADER_FLASH_ERASE) {
			res = flash_block_erase(&the_flash, address);
		}
		if (command == LOADER_FLASH_UNLOCK) {
			res = flash_block_unlock(&the_flash, address);
		}
		if (command == LOADER_FLASH_LOCK) {
			res = flash_block_lock(&the_flash, address);
		}
		if (command == LOADER_FLASH_LOCKDOWN) {
			res = flash_block_lockdown(&the_flash, address);
		}

		msgb_put_u8(reply, command);
		msgb_put_u8(reply, chip);
		msgb_put_u32(reply, address);
		msgb_put_u32(reply, (res != 0));

		sercomm_sendmsg(dlci, reply);

		break;

	case LOADER_FLASH_GETLOCK:

		chip = msgb_pull_u8(msg);
		address = msgb_pull_u32(msg);

		lock = flash_block_getlock(&the_flash, address);

		msgb_put_u8(reply, command);
		msgb_put_u8(reply, chip);
		msgb_put_u32(reply, address);

		switch (lock) {
		case FLASH_UNLOCKED:
			msgb_put_u32(reply, LOADER_FLASH_UNLOCKED);
			break;
		case FLASH_LOCKED:
			msgb_put_u32(reply, LOADER_FLASH_LOCKED);
			break;
		case FLASH_LOCKED_DOWN:
			msgb_put_u32(reply, LOADER_FLASH_LOCKED_DOWN);
			break;
		default:
			msgb_put_u32(reply, 0xFFFFFFFF);
			break;
		}

		sercomm_sendmsg(dlci, reply);

		break;

	case LOADER_FLASH_PROGRAM:

		nbytes = msgb_pull_u8(msg);
		crc = msgb_pull_u16(msg);
		msgb_pull_u8(msg);	// XXX align
		chip = msgb_pull_u8(msg);
		address = msgb_pull_u32(msg);

		data = msgb_pull(msg, nbytes) - nbytes;

		mycrc = osmo_crc16(0, data, nbytes);

		if (mycrc == crc) {
			res = flash_program(&the_flash, address, data, nbytes);
		}

		msgb_put_u8(reply, LOADER_FLASH_PROGRAM);
		msgb_put_u8(reply, nbytes);
		msgb_put_u16(reply, mycrc);
		msgb_put_u8(reply, 0);	// XXX align
		msgb_put_u8(reply, chip);
		msgb_put_u32(reply, address);

		msgb_put_u32(reply, (uint32_t) res);	// XXX

		sercomm_sendmsg(dlci, reply);

		break;

	default:
		printf("unknown command %d\n", command);

		msgb_free(reply);

		break;
	}

 out:

	msgb_free(msg);
}
Exemple #18
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");
    }
}