📄 flash_nor.c
字号:
{ uint32 page_address; uint32 page_ptr; if (page > last_page_id) { return NULL; } (void)self; page_address = page << FS_NOR_PAGE_ADDR_BITS; page_ptr = page_address; page_ptr += nv_byte_offset;#ifdef FSND_DEBUG printf("\tpageptr: page address 0x%x\n", page_address); printf("\tpageptr: absolute page address 0x%x\n", page_ptr);#endif return (void *)page_ptr;}/***********************************************************************FUNCTION fs_nor_device_read_pageDESCRIPTION This function read page data of the given page into the given buffer DEPENDENCIES NoneRETURN VALUE FS_DEVICE_DONE if read read was successful else FS_DEVICE_FAIL**********************************************************************/intfs_nor_device_read_page (fs_device_t self, page_id page, void *data){ uint32 page_address; flash_status status; page_address = page << FS_NOR_PAGE_ADDR_BITS;#ifdef FSND_DEBUG printf("\tread: page address 0x%x\n", page_address); printf("\tread: absolute address 0x%x\n", (page_address + (nv_byte_offset)));#endif status = fs_nor_device_worded_read ((byte *)data, (dword)page_address, (dword)(self->page_size (self))); if (status != FLASH_SUCCESS) return FS_DEVICE_FAIL; else return FS_DEVICE_DONE;} /* End of fs_nor_device_read_page *//***********************************************************************FUNCTION fs_nor_device_bad_block_checkDESCRIPTION This function should be called to determine whether a block is bad or notDEPENDENCIES NoneRETURN VALUE FS_DEVICE_OK always, as there is no such thing as a bad block in NOR flash.SIDE EFFECTS None**********************************************************************/intfs_nor_device_bad_block_check (fs_device_t self, block_id block){ (void) self; (void) block; return FS_DEVICE_OK;} /* End of fs_device_nor_bad_block_check *//***********************************************************************FUNCTION fs_nor_device_mark_block_badDESCRIPTION Mark a block as badDEPENDENCIES NoneRETURN VALUE FS_DEVICE_FAIL always, as this cannot be done on NOR flash.SIDE EFFECTS None**********************************************************************/intfs_nor_device_mark_block_bad (fs_device_t self, block_id block){ (void) self; (void) block; return FS_DEVICE_FAIL;} /* End of fs_device_nor_mark_block_bad *//***********************************************************************FUNCTION fs_nor_device_write_partial_pageDESCRIPTION This function writes a partial page of dataDEPENDENCIES NoneRETURN VALUE FS_DEVICE_DONE if write was successful else FS_DEVICE_FAILSIDE EFFECTS None**********************************************************************/int fs_nor_device_write_partial_page (fs_device_t self, page_id page, void *data, int offset, int length){ uint32 page_address; flash_status status; uint32 write_addr; page_address = page << FS_NOR_PAGE_ADDR_BITS; write_addr = page_address + offset; //lint !e737 offset is always +ve /* check to make sure the write does not go off the page */ if ((offset + length) > (self->page_size (self))) //lint !e574 !e737 sign/unsigned mix rel ok { return FS_DEVICE_FAIL; }#ifdef FSND_DEBUG printf("\twritepp: page address 0x%x length 0x%x\n", page_address, length); printf("\twritepp: absolute address 0x%x\n", (write_addr + nv_byte_offset));#endif /* Verify that the requested data is in range. The user see's the component as starting at zero, so we only need to check the end. */ if ((write_addr + length) > (nor_device->efs_info.efs_bsize)) { MSG_MED ("fs_dev: write request out of range", 0, 0, 0); return FS_DEVICE_FAIL; } /* We cannot write while an erase is happening. */ if (fsi_erase_state != FSI_READ_MODE && fsi_erase_state != FSI_ERASE_SUSPENDED) { MSG_MED ("fs_dev: attempt to write while device is erasing", 0, 0, 0); return FS_DEVICE_FAIL; } status = (*nor_device->ops->write) ((byte *)data, &fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)], (dword)write_addr, (dword)length); if (status != FLASH_SUCCESS) return FS_DEVICE_FAIL; else return FS_DEVICE_DONE;}/*===========================================================================FUNCTION FS_NOR_DEVICE_START_ERASE_BLOCKDESCRIPTION Starts an erase operation on a block of the flash.DEPENDENCIES NoneRETURN VALUE FS_DEVICE_DONE if erase was successful else FS_DEVICE_FAILSIDE EFFECTS An erase operation is begun upon the flash. This operation must be suspended before writes can occur.===========================================================================*/intfs_nor_device_start_erase_block (fs_device_t self, block_id block){ flash_status status; uint32 block_address; int block_size_shift; uint16 no_of_shifts = 1; uint32 block_count = self->block_count(self); /* bail out early if block is invalid */ if (block >= block_count) { return FS_DEVICE_FAIL; } block_size_shift = self->block_size (self); while (block_size_shift != 2) { block_size_shift >>= 1; no_of_shifts++; } /* Set the block address */ block_address = block << (FS_NOR_PAGE_ADDR_BITS + no_of_shifts); /* Determine if we have to check if an erase has terminated or not. */ switch (fsi_erase_state) { case FSI_READ_MODE: break; /* Easy. */ case FSI_ERASING: /* Must check to see if this erase is still running. */ ERR_FATAL ("not yet written 123", 0, 0, 0); break; case FSI_ERASE_SUSPENDED: MSG_MED ("fsi_dev: Attempt to start erase while erase is suspended", 0, 0, 0); return FS_FAIL_S; } /* If we made it here, then the component is now sitting in read mode. Our offset is in bytes from the beginning of EFS, get a pointer to the real data. */ fsi_erase_location = (nor_device->efs_info.efs_boffset >> 1) + (block_address >> 1); status = (*nor_device->ops->erase_start) (&fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)], (dword)block_address); if (status != FLASH_SUCCESS) return FS_DEVICE_FAIL; fsi_erase_state = FSI_ERASING; return FS_DEVICE_DONE;} /* End of fs_nor_device_start_erase_block *//*===========================================================================FUNCTION fs_nor_device_suspend_eraseDESCRIPTION This function suspends the current erase.DEPENDENCIES NoneRETURN VALUE FS_DEVICE_DONE if the erase has completed early. FS_DEVICE_BUSY if the erase is suspended. FS_DEVICE_FAIL if the suspend failed.===========================================================================*/int fs_nor_device_suspend_erase (fs_device_t self){ flash_status status; status = (*nor_device->ops->suspend_erase) (&fs_dev_base[fsi_erase_location]); if(status == FLASH_SUCCESS) { /* Erase complete */ fsi_erase_state = FSI_READ_MODE; return FS_DEVICE_DONE; } else if (status == FLASH_OP_NOT_COMPLETE) { /* Suspended */ fsi_erase_state = FSI_ERASE_SUSPENDED; return FS_DEVICE_BUSY; } return FS_DEVICE_FAIL;}/*===========================================================================FUNCTION fs_nor_device_resume_eraseDESCRIPTION This function resumes the suspended erase.DEPENDENCIES NoneRETURN VALUE FS_DEVICE_BUSY if the erase is running again. FS_DEVICE_FAIL if the resume failed.===========================================================================*/int fs_nor_device_resume_erase (fs_device_t self){ flash_status status; status = (*nor_device->ops->resume_erase) (&fs_dev_base[fsi_erase_location]); if(status != FLASH_SUCCESS) { return FS_DEVICE_FAIL; } fsi_erase_state = FSI_ERASING; return FS_DEVICE_BUSY;}/*===========================================================================FUNCTION fs_nor_device_erase_block_statusDESCRIPTION This function checks and returns the status of the flash device.DEPENDENCIES NoneRETURN VALUE FS_DEVICE_DONE if the erase has completed. FS_DEVICE_BUSY if the erase is still running.===========================================================================*/int fs_nor_device_erase_block_status(fs_device_t self){ flash_status status; if(fsi_erase_state == FSI_ERASING || fsi_erase_state == FSI_ERASE_SUSPENDED) { status = (*nor_device->ops->erase_status)(&fs_dev_base[fsi_erase_location]); if (status != FLASH_SUCCESS) return FS_DEVICE_BUSY; else fsi_erase_state = FSI_READ_MODE; } return FS_DEVICE_DONE;}/*===========================================================================FUNCTION FSI_RAM_PROBEDESCRIPTION Probes the given address location to see if it is a writable RAM space.DEPENDENCIES NoneRETURN VALUE True if a writable area is found, False otherwise.SIDE EFFECTS None===========================================================================*/boolean fsi_ram_probe (void){#ifdef FS_DEV_UNIT_TEST return FALSE;#else volatile word *base; word saved_val; extern word stamp_md5_hash; /* Location to probe, use stamp_md5_hash */ base = fs_dev_base +(((int)&stamp_md5_hash/2)); saved_val = base[0]; base[0] = 0xAA; if ( (base[0] & 0x00FF) != 0xAA) { return( FALSE ); } base[0] = 0xFF; if ( (base[0] & 0x00FF) != 0xFF ) { return( FALSE ); } base[0] = saved_val; return( TRUE );#endif}/*===========================================================================FUNCTION FS_NOR_DEVICE_WORDED_READDESCRIPTION Read a sequence of bytes from a word oriented device. This is generic to any word sized device.DEPENDENCIES NoneRETURN VALUE FS_FAIL_S if the read couldn't be done. FS_OKAY_S if it succeeded.SIDE EFFECTS None===========================================================================*/flash_statusfs_nor_device_worded_read (byte *buffer, dword offset, dword count){#ifndef DO_READ_WITH_MEMMOVE volatile word *wptr; volatile byte *bptr;#endif /* not DO_READ_WITH_MEMMOVE */ /* Verify that the requested data is in range. The use see's the component as starting at zero, so we only need to check the end. */ if ((offset + count) > (nor_device->efs_info.efs_bsize)) { MSG_MED ("fs_dev: read request out of range", 0, 0, 0); return FS_FAIL_S; } /* We cannot read while an erase is happening. */ if (fsi_erase_state == FSI_ERASING) { MSG_MED ("fs_dev: attempt to read while device is erasing", 0, 0, 0); return FS_FAIL_S; }#ifdef DO_READ_WITH_MEMMOVE memmove (buffer, ((byte *) (fs_dev_base + (nor_device->efs_info.efs_boffset >> 1)) + offset), count);#else /* not DO_READ_WITH_MEMMOVE */ /* Quickly handle the 0 byte read case. */ if (count == 0) return FLASH_SUCCESS; /* The ARM processor doesn't handle misaligned data accesses, so we must account for that here. */ /* The easy case is if the alignment of the two is the same. */ if (((dword) buffer & 1) == (offset & 1)) { /* Is there a "byte" at the beginning? */ if ((offset & 1) == 1) { *buffer = *((volatile byte *) (fs_dev_base + (nor_device->efs_info.efs_boffset >> 1)) + offset); buffer++; offset++; count--; } /* Copy over any appropriatly aligned data. */ wptr = &fs_dev_base[(nor_device->efs_info.efs_boffset >> 1) + (offset >> 1)]; while (count > 1) { *((word *) buffer) = *wptr; buffer += 2; wptr += 1; count -= 2; } /* There may be one additional byte to copy. */ if (count) { *buffer = *((byte *) wptr); //lint !e794 } } /* Otherwise, the two sections of data are misaligned. There are two options, either copy the data in byte mode, or perform word operations and scramble the bytes around manually. Because both RAM and the component are 16 bits wide, we gain much by doing the scrambling. */ else { /* Simple byte copy. */ bptr = ((byte *) &fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)]) + offset; while (count-- > 0) { *buffer++ = *bptr++; } }#endif /* not DO_READ_WITH_MEMMOVE */ return FLASH_SUCCESS;}/*********************************************************************** Functions that return hardcoded device values**********************************************************************/char *fs_nor_device_name (fs_device_t self){ (void)self; return (char *)nor_device->name;}uint32fs_nor_device_block_count (fs_device_t self){ (void)self; return nor_device->efs_info.efs_blk_count;}uint32fs_nor_device_block_size (fs_device_t self){ (void)self; return (nor_device->efs_info.efs_blk_bsize/512);}uint32fs_nor_device_page_size (fs_device_t self){ (void)self; return 512;}static fs_device_write_style_tfs_nor_device_get_write_style (fs_device_t self){ (void) self; return nor_device->efs_info.efs_write_style;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -