📄 amdsbdrv.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: amdsbdrv.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"
// Due to long branches, we disable all tracing and led function calls.
#undef tlw
#define tlw(contents)
#undef ttw
#define ttw(contents)
asm(" .label _ffsdrv_ram_amd_begin");
asm(" .def _ffsdrv_ram_amd_begin");
// IMPORTANT! Apparently, placing the int_disable/enable() function code
// here instead of at the bottom of the file, makes the code crash or
// freeze. Reason is as of yet unknown.
uint32 amd_int_disable(void);
void amd_int_enable(uint32 tmp);
/******************************************************************************
* AMD Single Bank Driver Functions
******************************************************************************/
void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value)
{
volatile char *flash = dev.base;
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 = amd_int_disable();
tlw(led_on(LED_WRITE));
flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
flash[0x5555] = 0x55; // AMD unlock cycle 2
flash[0xAAAA] = 0xA0;
*addr = value;
while ((*addr ^ value) & 0x80)
;
tlw(led_off(LED_WRITE));
amd_int_enable(cpsr);
}
// This VERY simple way of erase suspension only works because we run under
// a pre-emptive operating system, so whenever an interrupt occurs, another
// task takes the CPU, and at the end of the interrupt, FFS gets the CPU
// again.
void ffsdrv_ram_amd_sb_erase(uint8 block)
{
volatile char *flash = dev.base;
volatile char *addr;
uint32 cpsr;
uint16 flashpoll;
addr = block2addr(block);
ttw(ttr(TTrDrvEra, "e(%d)" NL, block));
cpsr = amd_int_disable();
tlw(led_on(LED_ERASE));
flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
flash[0x5555] = 0x55; // AMD unlock cycle 2
flash[0xAAAA] = 0x80;
flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
flash[0x5555] = 0x55; // AMD unlock cycle 2
*addr = 0x30; // AMD erase sector command
// 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;
// wait for erase suspend to finish
while ((*addr & 0x80) == 0)
;
tlw(led_off(LED_ERASE_SUSPEND));
amd_int_enable(cpsr);
// Other interrupts and tasks run now...
cpsr = amd_int_disable();
tlw(led_on(LED_ERASE_SUSPEND));
// Before resuming erase we must? check if the erase is really
// suspended or if it did finish
flashpoll = *addr;
*addr = 0x30;
tlw(led_off(LED_ERASE_SUSPEND));
}
}
tlw(led_on(LED_ERASE));
tlw(led_off(LED_ERASE));
amd_int_enable(cpsr);
}
/******************************************************************************
* Interrupt Enable/Disable
******************************************************************************/
uint32 amd_int_disable(void)
{
asm(" .state16");
asm(" mov A1, #0xC0");
asm(" ldr A2, tct_amd_disable");
asm(" bx A2 ");
asm("tct_amd_disable .field _TCT_Control_Interrupts+0,32");
asm(" .global _TCT_Control_Interrupts");
}
void amd_int_enable(uint32 cpsr)
{
asm(" .state16");
asm(" ldr A2, tct_amd_enable");
asm(" bx A2 ");
asm("tct_amd_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_amd_end");
asm(" .def _ffsdrv_ram_amd_end");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -