📄 intelsbdrv.c
字号:
/******************************************************************************
* Flash File System (ffs)
* Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
*
* FFS AMD single bank low level flash driver RAM code
*
* $Id: intelsbdrv.c,v 1.1.1.1 2004/06/19 06:00:30 root Exp $
*
******************************************************************************/
#include "ffs.cfg"
#include "ffs.h"
#include "drv.h"
#include "ffstrace.h"
#define INTEL_UNLOCK_SLOW 1
#undef tlw
#define tlw(contents)
#undef ttw
#define ttw(contents)
// Status bits for Intel flash memory devices
#define INTEL_STATE_MACHINE_DONE (1<<7)
#define FLASH_READ(addr) (*(volatile uint16 *) (addr))
#define FLASH_WRITE(addr, data) (*(volatile uint16 *) (addr)) = data
asm(" .label _ffsdrv_ram_intel_begin");
asm(" .def _ffsdrv_ram_intel_begin");
uint32 intel_int_disable(void);
void intel_int_enable(uint32 tmp);
/******************************************************************************
* INTEL Single Bank Driver Functions
******************************************************************************/
// Actual we should have disabled and enable the interrupts in this
// function, but when the interrupt functions are used ffs don't run!
// Anyway, currently the interrupts are already disabled ad this point thus
// it dos not cause any problems.
int ffsdrv_ram_intel_sb_init(void)
{
uint32 cpsr, i;
volatile char *addr;
uint16 status;
for (i = 0; i < dev.numblocks; i++)
{
addr = block2addr(i);
*addr = 0x50; // Intel Clear Status Register
*addr = 0xFF; // Intel read array
*addr = 0x60; // Intel Config Setup
*addr = 0xD0; // Intel Unlock Block
// Wait for unlock to finish
do {
status = FLASH_READ(addr);
} while (!(status & INTEL_STATE_MACHINE_DONE));
*addr = 0x70; // Intel Read Status Register
status = FLASH_READ(addr);
// Is there an erase suspended?
if ((status & 0x40) != 0) {
*addr = 0xD0; // Intel erase resume
*addr = 0x70; // Intel Read Status Register
// wait for erase to finish
do {
status = FLASH_READ(addr);
} while (!(status & INTEL_STATE_MACHINE_DONE));
}
*addr = 0xFF; // Intel Read Array
}
return 0;
}
void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value)
{
uint32 cpsr;
ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value));
if (~*addr & value) {
ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
return;
}
cpsr = intel_int_disable();
tlw(led_on(LED_WRITE));
#if (INTEL_UNLOCK_SLOW == 1)
*addr = 0x60; // Intel Config Setup
*addr = 0xD0; // Intel Unlock Block
#endif
*addr = 0x50; // Intel Clear Status Register
*addr = 0x40; // Intel program byte/word
*addr = value;
while ((*addr & 0x80) == 0)
;
*addr = 0xFF; // Intel read array
tlw(led_off(LED_WRITE));
intel_int_enable(cpsr);
}
void ffsdrv_ram_intel_sb_erase(uint8 block)
{
volatile char *addr;
uint32 cpsr;
uint16 poll;
ttw(ttr(TTrDrvEra, "e(%d)" NL, block));
addr = block2addr(block);
cpsr = intel_int_disable();
tlw(led_on(LED_ERASE));
#if (INTEL_UNLOCK_SLOW == 1)
*addr = 0x60; // Intel Config Setup
*addr = 0xD0; // Intel Unlock Block
#endif
*addr = 0x50; // Intel Clear Status Register
*addr = 0x20; // Intel Erase Setup
*addr = 0xD0; // Intel Erase Confirm
*addr = 0x70; // Intel Read Status Register
// Wait for erase to finish.
while ((*addr & 0x80) == 0) {
tlw(led_toggle(LED_ERASE));
// Poll interrupts, taking interrupt mask into account.
if (INT_REQUESTED)
{
// 1. suspend erase
// 2. enable interrupts
// .. now the interrupt code executes
// 3. disable interrupts
// 4. resume erase
tlw(led_on(LED_ERASE_SUSPEND));
*addr = 0xB0; // Intel Erase Suspend
*addr = 0x70; // Intel Read Status Register
while (((poll = *addr) & 0x80) == 0)
;
// If erase is complete, exit immediately
if ((poll & 0x40) == 0)
break;
*addr = 0xFF; // Intel read array
tlw(led_off(LED_ERASE_SUSPEND));
intel_int_enable(cpsr);
// Other interrupts and tasks run now...
cpsr = intel_int_disable();
tlw(led_on(LED_ERASE_SUSPEND));
*addr = 0xD0; // Intel erase resume
// The following "extra" Read Status command is required because Intel has
// changed the specification of the W30 flash! (See "1.8 Volt Intel?// Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30
// Specification Update")
*addr = 0x70; // Intel Read Status Register
tlw(led_off(LED_ERASE_SUSPEND));
}
}
*addr = 0xFF; // Intel read array
tlw(led_on(LED_ERASE));
tlw(led_off(LED_ERASE));
intel_int_enable(cpsr);
}
// TODO: remove below function, not in use anymore.
void ffsdrv_ram_intel_erase(uint8 block)
{
uint32 cpsr;
uint16 status;
ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
tlw(led_on(LED_ERASE));
dev.addr = (uint16 *) block2addr(block);
cpsr = intel_int_disable();
dev.state = DEV_ERASE;
*dev.addr = 0x60; // Intel Config setup
*dev.addr = 0xD0; // Intel Unlock block
*dev.addr = 0x50; // Intel clear status register (not really necessary)
*dev.addr = 0x20; // Intel erase setup
*dev.addr = 0xD0; // Intel erase confirm
intel_int_enable(cpsr);
while ((*dev.addr & 0x80) == 0)
;
*dev.addr = 0xFF; // Intel read array
dev.state = DEV_READ;
tlw(led_off(LED_WRITE));
}
/******************************************************************************
* Interrupt Enable/Disable
******************************************************************************/
uint32 intel_int_disable(void)
{
asm(" .state16");
asm(" mov A1, #0xC0");
asm(" ldr A2, tct_intel_disable");
asm(" bx A2 ");
asm("tct_intel_disable .field _TCT_Control_Interrupts+0,32");
asm(" .global _TCT_Control_Interrupts");
}
void intel_int_enable(uint32 cpsr)
{
asm(" .state16");
asm(" ldr A2, tct_intel_enable");
asm(" bx A2 ");
asm("tct_intel_enable .field _TCT_Control_Interrupts+0,32");
asm(" .global _TCT_Control_Interrupts");
}
// Even though we have this end label, we cannot determine the number of
// constant/PC-relative data following the code!
asm(" .state32");
asm(" .label _ffsdrv_ram_intel_end");
asm(" .def _ffsdrv_ram_intel_end");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -