⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash_intel.c

📁 Hermit-at-1.1.3,一款bootloader
💻 C
字号:
/* * Copyright (c) 2000 Blue Mug, Inc.  All Rights Reserved. * * Commands to program the Intel 28F320B3 flash chips on the Cirrus * Logic CDB89712 evaluation board.  These are 32 Mbit "bottom boot" * (boot and param blocks at low end of address space) flash chips. * * The CDB89712 has two 8Mbyte flash banks, each using two flash chips. * The flash chips are 16 bits wide; one occupies the 16 high lines on * the data bus, the other the low lines.  So when we write commands * to the flash, we have to duplicate each command across each half of * the data bus: * * 	*addr = 0x00FF00FF; * * This is seen as a word-wide write of 0x00FF by each 16-bit flash * chip.  Such an arrangement should be familiar to embedded * developers who have worked with flash in 32-bit systems. * * Two of the boot blocks in each flash are write protected.  We don't * provide any way of circumventing that protection here.  From a * quick look at the CDB89712 schematics, it looks like the write * protect line is held at logic high, so the blocks are always * writeable on this board. * * Even in other configurations (e.g. WP line wired to a GPIO output) * I expect that I'll want to avoid automatic disabling of write * protect here, since the consequences of writing garbage into the * boot blocks can be grave.  In the infrequent case in which you're * writing over the boot loader itself, it's not too onerous to have * to fire up the command line and do a little register prodding. */#include <target/buffer.h>#include <target/io.h>#include <target/herrno.h>#include <target/scan.h>#include "flash.h"/* download buffer for the flash programmer */#define DLBUFSIZE (8*1024)unsigned char dlbuf [DLBUFSIZE];word_t dlbufsize = DLBUFSIZE;/* timeout for auto-boot, in seconds */#define FL_WORD(addr) (*(volatile unsigned long*)(addr))/* command user interface (CUI) */#define CUI_READ_ARRAY		0x00FF00FF;#define CUI_READ_IDENTIFIER	0x00900090;#define CUI_READ_STATUS		0x00700070;#define CUI_CLEAR_STATUS	0x00500050;#define CUI_PROGRAM		0x00400040;#define CUI_BLOCK_ERASE		0x00200020;#define CUI_PROG_ERASE_SUSPEND	0x00B000B0;#define CUI_PROG_ERASE_RESUME	0x00D000D0;/* status register bits */#define SR7_WSMS	(1<<7)	/* Write State Machine Status */#define SR6_ESS		(1<<6)	/* Erase-Suspend Status */#define SR5_ES		(1<<5)	/* Erase Status */#define SR4_PS		(1<<4)	/* Program Status */#define SR3_VPPS	(1<<3)	/* V_PP (program voltage) Status */#define SR2_PSS		(1<<2)	/* Program Suspend Status */#define SR1_BLLK	(1<<1)	/* Block Lock Status *//* bit 0 is reserved */#define SR_MASK (SR7_WSMS|SR6_ESS|SR5_ES|SR4_PS|SR3_VPPS|SR2_PSS|SR1_BLLK)#define SR_ERASE_ERR (SR5_ES|SR4_PS|SR3_VPPS|SR1_BLLK)#define SR_BOTH_MASK (SM_MASK | (SM_MASK << 16))#define SR_BOTH_WSMS (SR7_WSMS | (SR7_WSMS << 16))#define SR_BOTH_ERASE_ERR (SR_ERASE_ERR | (SR_ERASE_ERR << 16))/* handy flash functions */static void flash_print_chip_error_string(unsigned char status);static void flash_print_error_string(void);static word_t flash_status_wait(addr_t addr);static int flash_status_full_check(addr_t addr);static void flash_print_chip_error_string(unsigned char status){	if (status & SR3_VPPS)		hprint("VPPRange");	else if ((status & SR5_ES) && (status & SR4_PS))		hprint("CommandSequence");	else if (status & SR5_ES)		hprint("BlockErase");	else if (status & SR1_BLLK)		hprint("LockedBlock");	else		hprint("NoError");}/* * Come up with an error string representing the flash error; we can * have distinct errors for the two chips.  Get the status from * errdata, since this is used for error output. */static void flash_print_error_string(void){	hprint("lowbank:");	flash_print_chip_error_string(errdata.word & SR_MASK);	hprint(" highbank:");	flash_print_chip_error_string((errdata.word >> 16) & SR_MASK);}/* * Loop until both write state machines complete. */static word_t flash_status_wait(addr_t addr){	word_t status;	do {		status = FL_WORD(addr);	} while ((status & SR_BOTH_WSMS) != SR_BOTH_WSMS);	return status;}/* * Loop until the Write State machine is ready, then do a full error * check.  Clear status and leave the flash in Read Array mode; return * 0 for no error, -1 for error. */static int flash_status_full_check(addr_t addr){	word_t status;	status = flash_status_wait(addr) & SR_BOTH_ERASE_ERR;	if (status) {		errdata.word = status;		errfunc = &flash_print_error_string;	}	FL_WORD(addr) = CUI_CLEAR_STATUS;	FL_WORD(addr) = CUI_READ_ARRAY;	return status ? -1 : 0;}/* * Program the contents of the download buffer to flash at the given * address.  Size is also specified; we shouldn't have to track usage * of the download buffer, since the host side can easily do that. * * We write words without checking status between each; we only go * through the full status check procedure once, when the full buffer * has been written. * * Alignment problems are errors here; we don't automatically correct * them because in the context of this command they signify bugs, and * we want to be extra careful when writing flash. */static int flash_program_cmdfunc(int argc, char *argv[]){	addr_t addr;	size_t size;	word_t *ptr;	if (argc != 3)		return -H_EUSAGE;	if (scan(*++argv, &addr)) return -H_EADDR;	if (scan(*++argv, &size)) return -H_EADDR;	if (addr & UNALIGNED_MASK) return -H_EALIGN;	if (size & UNALIGNED_MASK) return -H_EALIGN;	size >>= BYTE_TO_WORD_SHIFT;	for (ptr = (word_t*)dlbuf; size--; addr += sizeof(word_t)) {		FL_WORD(addr) = CUI_PROGRAM;		FL_WORD(addr) = *ptr++;		flash_status_wait(addr);	}	return flash_status_full_check(addr);}const command_t flash_program_command =	{ "program", "<addr> <size>",	  "program flash from download buffer",	  &flash_program_cmdfunc };/* * Erase a flash block.  Single argument is the first address in the * block (actually, it can be anywhere in the block, but the host-side * hermit downloader gives the first address). */static int flash_erase_cmdfunc(int argc, char *argv[]){	addr_t addr;	if (argc != 2)		return -H_EUSAGE;	if (scan(*++argv, &addr)) return -H_EADDR;	addr &= ~(addr_t)UNALIGNED_MASK;	/* word align */	FL_WORD(addr) = CUI_BLOCK_ERASE;	FL_WORD(addr) = CUI_PROG_ERASE_RESUME;	return flash_status_full_check(addr);}const command_t flash_erase_command =	{ "erase", "<addr>", "erase flash block", &flash_erase_cmdfunc };

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -