lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2300回复:12

高分 求三星FLASH读写方面的有关资料

楼主#
更多 发布于:2004-05-22 21:58
   希望大家能够支持.

[编辑 -  6/1/04 by  lixiaojun_001]
leexiogn 倚天而行 任意而为
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-08-23 11:01
进行写操作时,先发送写命令,然后是地址,在是数据,最后发确认命令,这里的数据,我应该送多少个呢?如果是A区,需要送256个,我送两百个,结果会怎么样呢?能出现什么问题。
leexiogn 倚天而行 任意而为
xulingfei
驱动牛犊
驱动牛犊
  • 注册日期2004-06-13
  • 最后登录2009-03-09
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-06-21 21:40
我师兄上学期将三星的kf2808的程序调通,16MB的!其实,程序很简单的,你看一下芯片的技术文档就行了,里面的编程流程都有!但是不同的单片机作控制,程序就不一样,这主要是时序的问题,不过这很费时的。有一点,很关键,就是单片机和flash芯片之间的驱动要配合好,这是最关键的!只要将这一点把握好,什么问题都迎刃而解。还有,别人给你的程序,要是单片机不一样,程序给你也没有用。自己下一点工夫吧!!!
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-06-21 19:52
资源越多 就越好啊
对大家都有利 同意的就发贴吧
让这个帖子成为精华 还需要各位的鼎立支持啊
leexiogn 倚天而行 任意而为
SUNSHANGXIN
驱动老牛
驱动老牛
  • 注册日期2002-11-19
  • 最后登录2009-08-01
  • 粉丝0
  • 关注0
  • 积分21分
  • 威望19点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-06-18 15:03
我给你个
呵呵
不过没写的很全
只有单字节写的
你自己慢慢的玩ba 兄弟
TC58v32 K9F3208 呵呵 兼容的
附件名称/大小 下载次数 最后更新
2004-06-18_TC58V32.C (3KB)  14
[b]苍白的,不是文字,是人的思想 虚伪的,不是网络,是人的灵魂 伤心的,不是爱情,是人的心灵 难忘的,不是容貌,是人的思诀 黎明的曙光早已不见了夕日的辉煌 东方的日出早就失去了往日的灿烂 而我也尽脱了昨日的笑容去迎接明天的枯涩 [/b]
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-06-18 13:28
各位兄弟姐妹 帮帮忙吧 !
能否贴个三星的存储器的程序来瞧瞧。
就差一步了。
leexiogn 倚天而行 任意而为
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-06-16 21:01
对各位无私的大无畏的精神,表示崇高的敬意。并保证想你们学习。
谢谢。非常感谢。
leexiogn 倚天而行 任意而为
liuzq
驱动小牛
驱动小牛
  • 注册日期2003-05-25
  • 最后登录2004-06-19
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-06-15 21:15
在本站的源代码下摘区有个DSP做的U盘+MP3的固件,里面肯定有FLASH读写的源代码,你用MP3关键字搜
whmjack
驱动小牛
驱动小牛
  • 注册日期2003-09-17
  • 最后登录2007-04-26
  • 粉丝0
  • 关注0
  • 积分290分
  • 威望29点
  • 贡献值0点
  • 好评度29点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-06-15 08:49
给你一段东芝flash的读写代码吧!没有什么难的!!

void Read_Flash_16(LBA lba)
{
char idata temp;
int  xdata i;
// //printf("\nInter the flash read program");
i=0;
LED=0;
//SEND THE COMMAND 00  TO THE FLASH
CE=0;
CLE=1;
XBYTE[FLASH]=0X50;
CLE=0;
//SEND ADDRESS TO THE FLASH
ALE=1;
XBYTE[FLASH]=(unsigned char)lba.A1;
XBYTE[FLASH]=(unsigned char)lba.A2;//low
XBYTE[FLASH]=(unsigned char)lba.A3;//high
ALE=0;
while(RY!=READY);
//READ DATA FROM THE FLASH TO THE DATABUF
for(i=0;i<=15;i++)
{
temp=XBYTE[FLASH];
buffer_16=temp;
}
CE=1;
LED=1;
set_flash_point();
}
dragon_hn
驱动中牛
驱动中牛
  • 注册日期2002-05-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分297分
  • 威望40点
  • 贡献值0点
  • 好评度32点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-06-14 17:58
俺给你一个汇编的程序,其中有你要的代码,CYPRESS的U盘用的


;/////////////////////////////////////////////////////////////////////////
; Supports Bulk ONLY Transport
; Supports UFI Commands
;  Simon:   Jul/10/2000  Initial Create to Support CF/SSFDC
;  Simon:   Sep/11/2000  Support two Icons in WinME and Win2K
;  Simon:   Oct/20/2000  Support multi-devices for combo (ver. 0.61)
;  Simon:   Nov/02/2000  Support Suspend mode
;  Simon:   Nov/20/2000  Support Write Protect for Mac
;           Apr/11/2000  Fix Microdrive on Mac; Release firmware into VC
;  Simon:   Aug/15/2001  Add support for TD: Used GPIO18 as the Write Protect
;                        fix 128MB SM bug in the Build_Table
;                        Add work arround Bug fix for TI-HUB (Primax)
;  Michael: Mar/01/2002  Fix write protect, eject issues for NAND flash
;  Michael: Apr/19/2002  Clean-up NAND Flash code for production release
;  Michael: May/21/2002  Implemented boot loader for compliance to USBCV
;  Michael: Jun/11/2002  Added LOW_POWER flag
;/////////////////////////////////////////////////////////////////////////

;/////////////////////////////////////////////////////////////////////////
; Compiler flags:
;        NOECC -- Disables ECC algorithms for throughput boost
;  DEVELOPMENT -- Allows multiple devices to be plugged into a host by
;                 changing last digit of serial number; FOR DEVELOPMENT ONLY
;    LOW_POWER -- Use this switch if the device's suspend current is less
;                 than 500uA
;      HD_ICON -- Makes device non-removable: must be partitioned before
;                 format allowed; Eject option disappears from "My Computer"
;                 in Windows; Changes device's icon in Win98/Me.
;     USE_SLOW -- Setup wait states for slower SRAM memory
;       USE_12 -- Setup processor for 12MHz crystal
;/////////////////////////////////////////////////////////////////////////
.xlist
    include nandflsh.inc
.list
cDevSel  equ 0xe0
;**********************************************************************
; Software Init: Default Setting to Rec command From Host
; Using Scan for Enhancement code
;**********************************************************************
   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    0xc006                   ;mov [0xc006],0 setup processor at 48MHz
#ifdef USE_12
   dw    0x40                     ;setup for 12MHz oscillator
#else
   dw    0                        ;setup for 48MHz oscillator
#endif

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    0xc03a
#ifdef USE_SLOW
   dw    0x00b                    ;ext=16-bit,0-wait|rom=16,bit-0wait|ram=8-bit,3-wait
#else
   dw    0x009                    ;ext=16-bit,0-wait|rom=16,bit-0wait|ram=8-bit,1-wait
#endif

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    (83*2)
   dw    std_class

   dw    0xc3b6                   ;enhancement signature
   dw    6                        ;length of stuff
   db    0                        ;COPY opcode
   dw    (91*2)                   ;string descriptor loc
   dw    conf_desc
   dw    string_desc

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    (USB_DELTA_CONFIG_INT*2)
   dw    New_Delta

   dw    0xc3b6                   ;enhancement signature
   dw    ((IRAM0_E-IRAM0_S)+2)    ;length of IRAM0
   db    0                        ;memory copy
   dw    IRAM0
   reloc IRAM0
IRAM0_S:
;**********************************************************************
; Arm Setup for Endpoint1/Endpoint
;**********************************************************************
ArmSetup:
   mov   [r10],64
ArmSetup0:
   mov   [pkg_cnt],(cMAXSIZE/128)
   int   ARM_INT
   ret
;**********************************************************************
; Initialize and arm endpoint 1 to send USB Status packets
;**********************************************************************
_InitEP1:
   mov   [USB_EP1_ADDR],SCMD      ;setup to send command
   mov   [USB_EP1_CNT],0xd        ;Command Block size
ArmEP1:
   mov   [LastAddr1],[USB_EP1_ADDR]
   mov   [LastCnt1],[USB_EP1_CNT]
   mov   [USB_EP1_CNTRL],cDMA1ENA
   ret
;**********************************************************************
; Require r9=pointer to 32-bit length
;**********************************************************************
dUpdate64:
   mov   r0,cBUFFSIZE             ;input expected len, return r0=remainder
   mov   r9,_xLenLSB
dChkSize:
   sub   [r9++],r0                ;sub low word
   subb  [r9],0                   ;dec the high word
   rnc
   xor   [r9],[r9]                ;MSB = 0
   subi  r9,2
   add   r0,[r9]                  ;return r0 = remainder
   xor   [r9],[r9]                ;LSB = 0
   ret
;**********************************************************************
; UpdateBuff: Updates dual USB buffer (512 bytes * 2) and wraps if at end
;**********************************************************************
UpdateBuff:
   mov   r10,nBuff                ;Update USB Buffer DATA ptr
   mov   r7,[r10]                 ;return current ptr in r8
   add   [r10],r0                 ;next block, r0=512
ChkWrap:
   cmp   [r10],(DATA0+cMAXSIZE)
   rl
   mov   [r10],DATA0              ;check buffer wrap arround
   ret
pkg_cnt:     dw 0
page_cnt:    dw 0
IRAM0_E:
   err<z (IRAM0Size-(IRAM0_E-IRAM0_S))  ; check if go over limited range

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    USB_RESET_VEC
   dw    USB_reset

   dw    0xc3b6                   ;enhancement signature
   dw    ((IRAM1_E-IRAM1_S)+2)    ;length of stuff
   db    0                        ;memory copy
   dw    IRAM1
   reloc IRAM1
IRAM1_S:
std_class:
   mov   [(90*2)],dev_desc        ; new device descriptor
#ifdef DEVELOPMENT
   cmp   [sse1],0x30              ; check sse1 for '0' (0x30)
   jne   @f
   mov   r0,[USB_ADDR_REG]        ; load the word with USB address
   and   r0,0x7                   ; pull off the USB address
   add   [sse1],r0                ; digit is ASCII '0'- add r0
@@:
#endif
   jmpl  USB_Stand
;**********************************************************************
; new_71: Replace ISR for interrupt 71
;**********************************************************************
new_71:
   addi  r15,2                    ;adjust the stack
   int   70
   int   71                       ;incase main execute return
IRAM1_E:
   err<z (IRAM1Size-(IRAM1_E-IRAM1_S))   ; check if go over limited range

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    USB_EP1_VEC              ;mov [USB_EP1_VEC],endp_1_int
   dw    endp_1_int

   dw    0xc3b6                   ;enhancement signature
   dw    ((IRAM2_E-IRAM2_S)+2)    ;length of stuff
   db    0                        ;memory copy
   dw    IRAM2
   reloc IRAM2
IRAM2_S:
_gIdeState:    dw 0
;**********************************************************************
; RegSetup: Sets up registers to default states
;**********************************************************************
RegSetup:
   mov   rCNTRL,gHighOut          ; 0xc024
   mov   rCMD,_gCmd               ; Read/Write Command
   mov   rSTATE,_gIdeState        ; Setup register 12
   ret
;**********************************************************************
; Endpoint 1 ISR: Send Command Status/Data to host
; use registers: r14-r12, r10, r7: should not use in other subroutines
; Host Read from Peripheral
;**********************************************************************
endp_1_int:
   push  [flags]
   int   SAVE_REGS                ;save all registers to stack
   test  [_gIdeState],eSndData    ;send data
   jz    SetDefault               ;no set Default Buffer
ep1_data:
   mov   r10,USB_EP1_ADDR
ep_common:
   call  dUpdate64                ;xLen -= 64
   and   r0,r0
   jnz   @f
   mov   [_gIdeState],eSndStatus
   jmp   exit_isr
@@:
   mov   [r10+2],r0               ;update xfer length on USB_EPx_CNT
   call  ChkWrap                  ;check buffer wrap arround
   dec   [pkg_cnt]                ;kick off Read/Write in the MainTask
   jz    exit_isr
   int   ARM_INT
exit_isr:
   int   REST_REGS                ;restore all registers
pop_exit:
   pop   [flags]
   sti
   ret
IRAM2_E:
   err<z (IRAM2Size-(IRAM2_E-IRAM2_S))   ; check if go over limited range

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    USB_EP2_VEC              ;mov [USB_EP2_VEC],endp_2_int
   dw    endp_2_int

   dw    0xc3b6         ;enhancement signature
   dw    ((IRAM3_E-IRAM3_S)+2)    ;length of IRAM3
   db    0  ;memory copy
   dw    IRAM3
   reloc IRAM3
IRAM3_S:
;//////////////////////////////////////////////////////////////////////
;// Code required for device startup
;//////////////////////////////////////////////////////////////////////
New_Delta:
   call USB_DELTA_SUB             ;it will be called in USB_reset
;**********************************************************************
; Call this when This delta config is setup to avoid BIOS reset the endpoint
;**********************************************************************
HwInit:
   mov   [0xc03e],2               ;Debug mode disable (reduces power)
   mov   [0xc00e],0x21            ;enable only USB must removed UART int
   mov   [0x2d2],MainTask         ;Use UART_TASK for main program
   or    [gHighOut],cOutData      ;setup default output control signals
   or    [gHighEn],cCtrlEna       ;Setup Control signals
   mov   [_gCmd],0                ;04/04/2000 add for MAC support
   mov   [(87*2)],Class_Int       ;Class Int sub
   mov   [TIMER0_VEC],Timer_0_int  
   ; *** Begin WP_status init here ***
   mov   r0,[gHighIn]             ;Store power-on status of WP
   and   r0,cGPIO18               ;mask the bit
   mov   [WP_flag],r0             ;move it to status variable
   ; *** End WP_status init here ***
   test  [startup],1
   jz    SwInit
   ret

startup: dw 1
MainTask:
   test  [startup],1              ;Check startup
   jz    MainTask2                ;Jump to MainTask2 if startup completed
   mov   r1,xIRAM4                ;Load IRAM4 from location on EEPROM
   mov   r11,IRAM3_E              ;Place IRAM4 at IRAM3_E
   mov   r9,IRAM4Size             ;Copy IRAM4Size bytes
@@:
   xor   r0,r0                    
   int   65                       ;Use INT 65 to read the EEPROM
   mov   b[r11++],r0
   dec   r9
   jnz   @b
   mov   [startup],0              ;Clear startup for next time
   jmp   SwInit

;**********************************************************************
; Timer_0_int ISR: Handles LED, USB Suspend functions
;**********************************************************************
Timer_0_int:
   push [flags]
   add  [uTimer],0xffff           ; 64ms timer0
   test [_gIdeState],7            ; check for idle time
   jnz  @f
   or   [gHighOut],cCS0           ; turn LED off only not BUSY
@@:
   inc  [0x272]         ; hardcode sof_tic
   cmp  [0x272],4
   jne  @f
   and  [gHighEn],!(cCF_Pins|cPWC) ;remove CF power
   push [0xc00e]                  ; push Interrupt Enable
   mov  [0xc00e],0         ; disable all hardware interrupts
   mov  [0xc00a],0x26             ; suspend chip
   pop  [0xc00e]                  ; restore
   or   [gHighEn],(cCF_Pins|cPWC) ;apply power
@@:
   jmp  pop_exit

;**********************************************************************
; USB_reset ISR: Bug fix for MAC OS reset timing
;**********************************************************************
USB_reset:
   mov   [0xc080],0
   mov   [0xc080],1
   jmpl  USB_RESET_SUB            ; jmp to BIOS USB_reset

;**********************************************************************
; Class_Int ISR: Handles USB Class interrupt
;**********************************************************************
Class_Int:
   cmp   b[r8+bRequestP],254
   je    SendLUN            
   int   USB_FINISH_INT           ; Finish the interrupt
   ret                          
SendLUN:
   xor   [r8],[r8]                ; Only SSFDC support
   mov   r7, 1              
   jmp   SEND_DATA_SUB
      
;//////////////////////////////////////////////////////////////////////
;// Descriptors and data required for startup
;//////////////////////////////////////////////////////////////////////
conf_desc:
   db    9         ;len of config
   db    2         ;type of config
   dw    (end_all-conf_desc)
   db    1         ;one interface
   db    1         ;config #1
   db    0         ;index of string describing config
   db    0xc0      ;bus + self power
#ifdef LOW_POWER
   db    50        ;100mA
#else
   db    51        ;102mA
#endif
interface_desc:
   db    9
   db    4
   db    0         ;base #
   db    0         ;alt
   db    2         ;# endpoints
   db    0x08      ;0xff=vendor, 0=Composite 8=(Mass Storage)
   db    0x05      ;subclass for SFF8070i compliant devices
   db    0x50      ;bulk only class, interface proto (vendor)
   db    0         ;index of string describing interface  
ep2:
   db    7         ;len
   db    5         ;type (endpoint)
   db    0x02      ;Host Write
   db    2
   dw    cBUFFSIZE ;64
   db    0         ;interval
ep1:
   db    7         ;len
   db    5         ;type (endpoint)
   db    0x81      ;Host Read
   db    2         ;bulk mode
   dw    cBUFFSIZE ;64
   db    0         ;interval
end_all:

string_desc:
   db    STR0_LEN
   db    3
   dw    0x409     ;english language id
STR0_LEN equ ($-string_desc)
str0:
   db    STR1_LEN
   db    3
str2:
   dw    'CYPRESS FLASH DISK      ' ;Leave 24 characters for Mfg. Utility
STR1_LEN equ ($-str0)
str1:
   db    STR2_LEN
   db    3
   dw    'FEDCBA987654321' ;Serial number for Mfg. Utility
sse1: dw '0'               ;Last digit of ser # changed by DEVELOPMENT flag
STR2_LEN equ ($-str1)

dev_desc:
   db    0x12      ;length
   db    1         ;desc type
   dw    0x0110    ;USB spec 1.1
   db    0x00      ;device class
   db    0         ;device subclass
   db    0         ;should be 0x8
   db    8         ;max packet size for endpoint 0
   dw    0x04B4    ;VID
   dw    0x4616    ;PID
   dw    0x0082    ;device release number
   db    1         ;index of manufacture string
   db    1         ;index of product string
   db    2         ;index of serial number string (Unix need GUID)
   db    1         ;number of configurations
WP_flag:
   dw    0x0004                   ; Assume that WP is off at startup
IRAM3_E:
   err<z (IRAM3Size-(IRAM3_E-IRAM3_S)) ; check if go over limited range

   dw    0xc3b6                   ;enhancement signature
   dw    4                        ;length of stuff
   db    0                        ;COPY opcode
   dw    (2*71)
   dw    new_71

   dw 0xc3b6
   dw 2
   db 4
   dw HwInit

   reloc_off
IRAM4Size equ (IRAM4_E-IRAM4_S)
xIRAM4:
   reloc IRAM3_E
IRAM4_S:
SwInit:
   call  _InitEP1
   mov   [_gIdeState],eRecCommand ;default set to receive the command
   mov   [USB_EP2_ADDR],SCMD      ;setup to receive command
   mov   [USB_EP2_CNT],31         ;Command Block size
ArmEP2:
   mov   [LastAddr2],[USB_EP2_ADDR]
   mov   [LastCnt2],[USB_EP2_CNT]
   mov   [USB_EP2_CNTRL],cDMA2ENA
   ret

;**********************************************************************
; Endpoint 2 ISR (Rec Command)
; Host Write to Peripheral
;**********************************************************************
endp_2_int:
   push  [flags]
   int   SAVE_REGS                ;save all registers to stack
   mov   [USB_EP1_CNTRL],cDMA1DIS ;disable EP1 to prevent host read????
   call  RegSetup
   mov   r10,USB_EP2_ADDR
   test  [rSTATE],eRecData        ;check data phase transfer
   jnz   ep_common

   mov   r9,(SCMD+2)
   cmp   [r9],cCookie             ;check if it is a command block
   jne   SetDefault               ;setup to get command again

   mov   [r9++],0x5342
   addi  r9,4                     ;skip dCBWTag
   mov   r7,[r9++]                ;r7= Length LSB
   mov   [_xLenLSB],r7            ;copy working length
   mov   [_xLenMSB],[r9++]        ;[r8] = Length MSB
   and   [r9],0x180
   xor   [r9],0x80                ;change direction

   mov   b[rCMD],[r9]
   xor   [r9++],[r9]              ;Set Return status = 0, r9=pointer to length and CDB
   mov   [r10],DATA0
   mov   [nBuff],[r10++]          ;setup DATA pointer
   call  SS_ChkOpCode             ;SSFDC ChkOpcode: need to reserved r7, r10

@@:
   or    r7,[_xLenMSB]            ;check data
   jnz   DoDATA

SetDefault:
   call  SwInit                   ;reset to default
ep2_exit:
   jmp   exit_isr

DoDATA:
   call  dUpdate64
   and   b[rCMD],b[rCMD]          ;test r4,0x80 check direction
   jnz   DoWrite
DoRead:
   mov   [(ARM_INT*2)],ArmEP1
   mov   r10,USB_EP1_ADDR
   mov   [r10++],DATA0
   mov   [r10],r0
   addi  [rSTATE],eSndData        ;send data to host
   call  Xfer512
   call  ArmSetup0
   call  Xfer512
   jmp   ep2_exit

DoWrite:
   mov   [(ARM_INT*2)],ArmEP2
   addi  [rSTATE],eRecData        ;wait for USB send 64 data from host
   call  ArmSetup
   jmp   ep2_exit

;**********************************************************************
; MainTask for NAND Flash
;**********************************************************************
MainTask2:
   mov   [(90*2)],0xf756          ;restore dev_desc
   call  RegSetup
ChkDATA:
   test  [rSTATE],eSndStatus      ;check if need to send STATUS pharse
   jz    @f
 
ssfd_chk:
   test  [bStatus],0x100          ;check if all transfer then set done
   jz    DoXfer
sw_init:
   jmp   SwInit
@@:
   cmp   [pkg_cnt],0              ;Buffer not ready
   rnz
   test  [rSTATE],(eSndData|eRecData)
   rz
   mov   r10,USB_EP1_CNT
   test  [rSTATE],eSndData
   jnz   @f
   mov   r10,USB_EP2_CNT          ;Concurrent Kick off SIE DMA
@@:
   call  ArmSetup

Xfer512:
   test  [bStatus],0x100          ;xfer done
   rnz
DoXfer:
   mov   r0,512
   mov   r9,LenLSB                ;update Host Xfer Length on the SCMD
   call  dChkSize                 ;r0==0 means no more data to transfer
   call  UpdateBuff

   add   [_gLBA_L],1              ;inc sector cnt
   addc  b[_gLBA_H],0
   and   b[rCMD],b[rCMD]          ;check Read/Write
   jz    chk_ecc
set_ecc:                          ;WRITE TO FLASH
   mov   r8,r7
#ifndef NOECC
   call  _set_ecc                 ;Compute ECC
#endif
   call  _sSetAdd0
   mov   r8,r7
   call  _Write512                ;Write DATA
   call  _Write16                 ;Write redundant DATA
   call  sWritePage               ;Enable the Write Command
   add   [_gSectorPN_L],1         ;Updated PN Sector
   addc  b[_gSectorPN_H],0
   dec   [_gBLK]
   jnz   @f
   call  SS_FinalStatus

   test  [_gLBA_L],b[_gPageMask]  ; check if need to do Tail Copy
   jz    DoErase                  ;every done just erase and return
    
   call  DoTailCopy               ;copy tail data then erase
   jmp   DoErase

@@:
   test  [_gLBA_L],b[_gPageMask]
   rnz
   call  DoErase                  ;erase previous block
   jmp   _SetupWrite

DoErase:
   mov   r0,[_gSrcBlkPN]          ;if erase block is valid
   cmp   r0,[_gDstBlkPN]
   rz
   mov   r8,[_gEraseBlk]          ;Set block status erased
   or    [r8],0xf000              ;BLOCK is Free now
   call  _Blk2Pages               ;get PN address
   call  _sWaitBusy
   jmp   sEraseBlock              ;Erase this Block

chk_ecc:                          ;READ from FLASH
   call  _sWaitBusy               ;wait for busy
   mov   r8,r7
   call  _Read512                 ;read DATA
   call  _Read16                  ;read Redundant data
   mov   r8,r7
#ifndef NOECC
   call  _chk_ecc
#endif
   dec   [_gBLK]
   jz    SS_FinalStatus
   mov   r3,b[_gPageMask]         ;check if need to Remap
   and   r3,[_gLBA_L]             ;get Page Offset
   rnz
   jmp  _SetupRead                ;SetupRead (r3=offset)
;**********************************************************************
; Read commands
;**********************************************************************


;**********************************************************************
; DATA TABLE
;**********************************************************************
; initial permutation IP
IP_Table:
DB 58,50,42,34,26,18,10,2
DB 60,52,44,36,28,20,12,4
DB 62,54,46,38,30,22,14,6
DB 64,56,48,40,32,24,16,8
DB 57,49,41,33,25,17, 9,1
DB 59,51,43,35,27,19,11,3
DB  61,53,45,37,29,21,13,5
DB  63,55,47,39,31,23,15,7
; final permutation IP^-1
IPR_Table:
DB 40, 8, 48, 16, 56, 24, 64, 32
DB  39, 7, 47, 15, 55, 23, 63, 31
DB  38, 6, 46, 14, 54, 22, 62, 30
DB  37, 5, 45, 13, 53, 21, 61, 29
DB  36, 4, 44, 12, 52, 20, 60, 28
DB  35, 3, 43, 11, 51, 19, 59, 27
DB  34, 2, 42, 10, 50, 18, 58, 26
DB  33, 1, 41,  9, 49, 17, 57, 25
; expansion operation matrix
E_Table:
DB  32, 1,  2,  3,  4,  5,  4,   5
DB  6,  7,  8,  9,  8,  9, 10,  11
DB  12, 13, 12, 13, 14, 15, 16, 17
DB  16, 17, 18, 19, 20, 21, 20, 21
DB  22, 23, 24, 25, 24, 25, 26, 27
DB  28, 29, 28, 29, 30, 31, 32,  1
; 32-bit permutation function P used on the output of the S-boxes
P_Table:
DB  16,  7, 20, 21, 29, 12, 28, 17
DB   1, 15, 23, 26,  5, 18, 31, 10
DB   2,  8, 24, 14, 32, 27,  3,  9
DB  19, 13, 30, 6,  22, 11,  4,  25
; permuted choice table (key)
PC1_Table:
DB 57, 49, 41, 33, 25, 17,  9,  1
DB  58, 50, 42, 34, 26, 18, 10,  2
DB  59, 51, 43, 35, 27, 19, 11,  3
DB  60, 52, 44, 36, 63, 55, 47, 39
DB  31, 23, 15,  7, 62, 54, 46, 38
DB  30, 22, 14,  6, 61, 53, 45, 37
DB  29, 21, 13,  5, 28, 20, 12,  4
; permuted choice key (table)
PC2_Table:
DB  14, 17, 11, 24,  1,  5,  3, 28
DB  15,  6, 21, 10, 23, 19, 12,  4
DB  26,  8, 16,  7, 27, 20, 13,  2
DB  41, 52, 31, 37, 47, 55, 30, 40
DB  51, 45, 33, 48, 44, 49, 39, 56
DB  34, 53, 46, 42, 50, 36, 29, 32
; number left rotations of pc1
LOOP_Table:
DB  1, 1, 2, 2, 2, 2, 2, 2
DB  1, 2, 2, 2, 2, 2, 2, 1
; The (in)famous S-boxes
;const static char S_Box[8][4][16] = {
S_Box1:
DB 14, 4, 13, 1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7
DB 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8
DB 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0
DB  15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
S_Box2:
DB   5,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10
DB 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5
DB 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15
DB   13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14, 9
S_Box3:
DB  10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8
DB 13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1
DB 13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7
DB   1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
S_Box4:
DB 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15
DB 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9
DB 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4
DB   3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
S_Box5:
DB   2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9
DB 14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6
DB 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14
DB  11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
S_Box6:
DB  12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11
DB 10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8
DB 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6
DB   4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
S_Box7:
DB   4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1
DB 13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6
DB   1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2
DB   6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
S_Box8:
DB  13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7
DB 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2
DB 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8
DB   2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
; static bool SubKey[16][48];// 16&Egrave;&brvbar;×&Oacute;&Atilde;&Uuml;&Ocirc;&iquest;
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
DESR_EC:
push    r8
push    r7
push r0
mov [SZ_Li],SZ_M
mov [SZ_Ri],(SZ_M+32)
mov r0,64
mov r7,SZ_M
call    ByteToBit
mov r7,SZ_M
mov r9,IP_Table
mov r0,64
call Transform
mov r0,16
@@:
push r0
mov r8,SZ_Tmp
mov r7,SZ_Ri
mov r0,32
call    memcpy
mov r8,SZ_Ri
mov r7,SubKey
pop r0
add r7,r0
push r0
call    F_func
mov r8,SZ_Ri
mov r7,SZ_Li
mov     r0,32
call    Xor
mov r8,SZ_Li
mov r7,SZ_Tmp
mov r0,32
call memcpy
pop     r0
dec     r0
jnz @b
jmp DESR_END
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
DESR_EC:
push r8
push r7
push r0
mov [SZ_Li],SZ_M
mov [SZ_Ri],(SZ_M+32)
mov r0,64
mov r7,SZ_M
call ByteToBit
mov r7,SZ_M
mov r9,IP_Table
mov r0,64
call Transform
mov r0,16
@@:
push r0
mov r8,SZ_Tmp
mov r7,SZ_Li
mov r0,32
call memcpy
mov r8,SZ_Li
mov r7,SubKey
pop r0
add r7,r0
push r0
call F_func
mov r8,SZ_Li
mov r7,SZ_Ri
mov r0,32
call Xor
mov r8,SZ_Ri
mov r7,SZ_Tmp
mov r0,32
call memcpy
pop r0
dec r0
jnz @b
DESR_END:
mov r8,SZ_M
mov r7,SZ_N
mov r9,IRP_Table
mov r0,64
call Transform
pop r8
push r8
mov r7,SZ_M
mov r0,64
call Bit2Byte
pop r7
pop r8
ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
Des_SetKey:
; static bool K[64], *KL = &K[0], *KR = &K[28];
mov [SZ_KL],SZ_K
mov r0,SZ_K
add r0,28
mov [SZ_KR],r0
mov r7,r8
push r8
mov r8,SZ_K
mov r0,64
call ByteToBit
mov r8,SZ_K
mov r7,SZ_K
mov r9,PC1_Table
mov r0,56
call Transform
mov r0,16
@@:
push    r0
mov r8,SZ_KL
mov r7,28
mov r9,LOOP_Table
pop r0
push r0
add r9,r0
call RotateL
mov r8,SZ_KR
mov r7,28
mov r9,LOOP_Table
pop r0
push r0
add r9,r0
CALL RotateL
mov r8,SubKey
pop r0
push r0
add r8,r0
mov r7,SZ_K
mov r9,PC2_Table
mov r0,48
call Transform
pop r0
dec r0
jnz @b
pop r8
ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
F_func:
push r8
mov r7,r8
mov r8,SZ_MR
mov r9,E_Table
mov r0,48
call Transform
mov r8,SZ_MR
mov r7,SZ_Ki
mov r0,48
call Xor
pop r8
push r8
mov r7,SZ_MR
call S_func
pop r8
push r8
mov r7,r8
mov r9,P_Table
mov r0,32
call Transform
pop r8
ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
S_func:
push r8
push r7
mov r0,8
mov [SZ_S_BOX],S_Box1
@@
push r0
pop r9
push    r9
add     r9,5
pop     r7
push    r7
rr      r7
add     r9,r7

pop     r0
push    r0
add     r0,4
mov     r0,[r0]

pop     r7
push    r7
inc     r7
mov     r7,[r7]
rr r7
rr r7
rr r7
add     r0,r7

pop     r7
push    r7
add     r7,2
mov r7,[r7]
rr r7
rr      r7
add     r0,r7

pop     r7
push    r7
add     r7,3
mov r7,[r7]
rr r7
add     r0,[r7]

pop     r8
push    r8
add [SZ_S_BOX],64
add [SZ_S_BOX],r9
add [SZ_S_BOX],r0
mov r7,[SZ_S_BOX]
mov r0,4
call ByteToBit
pop r0
dec r0
jnz @b
pop r7
pop     r8
ret

;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
Transform:
push r8
push r7
push r9
@@:
  push r0
  add  r9,r0
  mov  r7,[r9]
  pop  r0
  pop  r9
  push r9
  push r0
  add  r9,r7
  mov  r7,[r9]
  mov  r9,SZ_Tmp
  pop  r0
  push r0
  add  r9,r0
  mov  [r9],[r7]
  pop  r0
  dec  r0
  jnz  @b
  pop  r9
  pop  r7
  pop  r8
  push r8
  push r7
  push r9
  pop  r0
  push r0
  call memcpy
pop  r9
pop  r7
pop  r8
ret

;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
Xor:
push r8
push r7
@@:
push r0
pop  r0
pop  r7
pop  r8
push r8
push r7
push r0
add  r8,r0
add  r7,r0
xor  [r8],[r7]
pop  r0
dec  r0
jnz  @b
pop  r7
pop  r8
ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
RotateL:
push r8
push r7
push r0
mov  r8,SZ_Tmp
pop  r0
push r0
pop  r8
push r8
mov  r7,r8
call memcpy
pop  r0
pop  r8
push r8
push r0
mov  r7,r8
add  r7,r0
call memcpy
pop  r0
pop  r7
push r7
push r0
mov  r8,r7
add  r8,r0
call memcpy
pop  r0
pop  r7
pop  r8
ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
ByteToBit:
push  r8
push  r7
mov   r9,1
@@:
    push  r0
    pop   r7
    add   r7,r0
    test  r0,r9
jz    BTB01
pop   r8
push  r8
add   r8,r9
mov   [r8],1
rl  [r8]
rl  r9
jmp   BTB02
BTB01:
pop   r8
push  r8
add   r8,r9
rl  r9
mov   [r8],0
rl  [r8]
BTB02:
    pop   r0
    dec   r0
    jnz   @b
    pop   r7
    pop   r8
    ret
;**********************************************************************
; R8:input R7:output R0:cnt R9
;**********************************************************************
ByteToBit:
push  r8
push  r7
mov   r9,1
@@:
push  r0
pop   r7
add   r7,r0
test  r0,r9
jz  BTB01
pop   r8
push  r8
add   r8,r9
rl  r9
or    [r8],1
jmp   BTB02
BTB01:
pop   r8
push  r8
add   r8,r9
rl  r9
mov   [r8],0
BTB02:
pop   r0
dec   r0
jnz   @b
pop   r7
pop   r8
ret





;**********************************************************************
; Read commands
;**********************************************************************
_Read16:
   mov   r0, 16
_Read:
   mov   r8,_gRedunt
   jmp   RdCommon
_Read512:
   mov   r0, 512                  ; Read 512 bytes
RdCommon:
   mov   r11, gLowIn              ; Set the R11 ptr to Data IN
   mov   r2, cDATA_H  
   mov   r1, cDATA_RD
@@:
   mov   [rCNTRL], r1             ; Assert Read
   mov   b[r8++], [r11]           ; Read Data
   mov   [rCNTRL], r2             ; De-assert Read
   mov   [rCNTRL], r1             ; Assert Read
   mov   b[r8++], [r11]           ; Read Data
   mov   [rCNTRL], r2             ; De-assert Read
   mov   [rCNTRL], r1             ; Assert Read
   mov   b[r8++], [r11]           ; Read Data
   mov   [rCNTRL], r2             ; De-assert Read
   mov   [rCNTRL], r1             ; Assert Read
   mov   b[r8++], [r11]           ; Read Data
   mov   [rCNTRL], r2             ; De-assert Read
   subi  r0, 4                    ; Decrement the counter
   jnz   @b                       ; Loop back
   ret

;**********************************************************************
; Write commands
;**********************************************************************
_Write16:
   mov   r0,16
_Write:
   mov   r8,_gRedunt
   jmp   WrCommon
_Write512:
   mov   r0, 512                  ; Write 512 bytes
_WriteData:
   mov   [gLowEn],0xff            ; set Output mode
WrCommon:
   mov   r11, gLowOut             ; Set the R11 ptr to Data OUT
   mov   r2, cDATA_H
   mov   r1, cDATA_WR
@@:
   mov   [r11], b[r8++]           ; Write Data
   mov   [rCNTRL], r1             ; Assert Write
   mov   [rCNTRL], r2             ; De-assert Write
   mov   [r11], b[r8++]           ; Write Data
   mov   [rCNTRL], r1             ; Assert Write
   mov   [rCNTRL], r2             ; De-assert Write
   mov   [r11], b[r8++]           ; Write Data
   mov   [rCNTRL], r1             ; Assert Write
   mov   [rCNTRL], r2             ; De-assert Write
   mov   [r11], b[r8++]           ; Write Data
   mov   [rCNTRL], r1             ; Assert Write
   mov   [rCNTRL], r2             ; De-assert Write
   subi  r0, 4                    ; Decrement the counter
   jnz   @b                       ; Loop back
   ret

;**********************************************************************
; SS_ChkOpcode: Decodes and responds to MSC requests
; r9 pointer to length, CDB, r7=length
;**********************************************************************
SS_ChkOpCode:
   inc   r9                       ;skip length
   mov   r0,b[r9]                 ;r0=CDB[0]
   and   r0,r0                    ;check TUR
   jz    SS_TUR
   call  Save_LBA                 ;sets r8 to point at DATA0
   cmp   r0,s_READ                ;special handling for READ/WRITE
   je    SS_Read
   mov   r1,s_WRITE
   cmp   r0,r1
   je    SS_Write
   cmp   r0,0x2e                  ;write and verify
   je    SS_Write
   mov   r9,LenLSB                ;Clear LenLSB, LenMSB and Data
@@:
   xor   [r9++],[r9]              ;clear buffer
   dec   r1
   jnz   @b
   inc   b[(bStatus+1)]           ;set done flag
   cmp   r0,s_INQUIRY
   je    SS_Inquiry
   cmp   r0,s_FORMAT
   je    SS_Format
   cmp   r0,s_READ_FORMAT_CAPACITY
   je    SS_Read_Format_Capacity
   cmp   r0,s_READ_CAPACITY
   je    SS_Read_Capacity
   cmp   r0,s_START_STOP
   je    SS_StartStop
   cmp   r0,s_MODE_SENSE                
   je    SS_Mode_Sense
   cmp   r0,s_REQUEST_SENSE
   je    SS_Request_Sense
   cmp   r0,s_VERIFY              ;return Status Success for now
   rle

;**********************************************************************
; SS_Err: Completes failed commands
;**********************************************************************
SS_Err:
   addi  [bStatus],1
   ret

;**********************************************************************
; SS_StartStop: Responds to request to eject media
;**********************************************************************
SS_StartStop:
   test  b[(_gLBA_L+1)],6
   rz
   or    [rCMD],(cEject0|cMedia0) ; set EJECT media
   ret
  
;**********************************************************************
; SS_Mode_Sense: Returns status of WP bit
;**********************************************************************
SS_Mode_Sense:
   mov   b[r8++],0x00             ; DATA[0]
   mov   b[r8++],0x06             ; DATA[1] length = 6, in v.77 was incorrectly length = 8
   mov   b[r8++],0x00             ; DATA[2]
   test  [gHighIn],cGPIO18        ; WP=0
   rnz
   mov   b[r8],0x80               ; set write protect bit in DATA[3]
   ret

;**********************************************************************
; SS_Request_Sense: Returns error codes of previous command.
;      Scans for:
;        1. Eject
;        2. Media Change (triggered on write protect change)
;**********************************************************************
SS_Request_Sense:
   mov   [r8++],0x70              ; Error Code = 0x70h
   mov   b[(DATA0+7)],0x06        ; Additional Sense Length = 0x06h
   test  [rCMD],cEject0           ; Flag set until device unplug
   jz    @f
   mov   [r8],0x02                ; Return sense key ILLEGAL REQUEST
   mov   [(DATA0+12)],0x3A        ; Return ASC & ASCQ MEDIA REMOVAL PREVENTED
   ret
@@:
   test  [rCMD],cMedia0           ; Check for media change or eject
   jz    @f
   mov   [r8],0x06                ; Return sense key UNIT ATTENTION
   mov   [(DATA0+12)],0x28        ; Return ASC NOT READY TO READY TRANSISTION - MEDIA CHANGED
   and   [rCMD],!cMedia0          ; Clear cMedia0 status flag
   ret
@@:
   ret                            ; No more known errors detected, add additional errors here if needed

read_capacity_hdr:
   test  [rCMD],(cEject0|cRemoved0)   ;SSFDC detect insert
   jnz   SS_FinalStatus
   and   [rCNTRL],!(cPWC|cWP|cCLE|cALE|cCS0)
   or    [gHighEn],cPWC           ; insert power
   call  Delay
   call  SM_Reset
   call  sReadID                  ; read ID and get Capacity
   push  r5                       ; save actual blk count
   call  _Build_Table             ; uses r8
   pop   r0                       ; restore in r0 for sector count
   call  _BlkShft                 ; computed total sectors size
   ret
;**********************************************************************
; SS_Read_Format_Capacity: RETURNS THE TOTAL NUMBER OF BLOCKS
;**********************************************************************
SS_Read_Format_Capacity:
   call  read_capacity_hdr
   mov   r2,r1
   shr   r2,8
   mov   r8,DATA0                 ; put r8 back at DATA[0]
   mov   b[r8++],0
   mov   b[r8++],0
   mov   b[r8++],0
   mov   b[r8++],8
   mov   b[r8++],r2               ; BYTE3
   mov   b[r8++],r1               ; BYTE2
   mov   r2,r0
   shr   r2,8
   mov   b[r8++],r2               ; BYTE1
   mov   b[r8],r0                 ; BYTE0
   addi  b[(DATA0+10)],2          ; BYTE10 for 512 bytes per page
   jmp   SS_FinalStatus
            
;**********************************************************************
; SS_Read_Capacity: Returns the last LBA address (NUM BLOCKS - 1)
;**********************************************************************
SS_Read_Capacity:
   call  read_capacity_hdr
   subi  r0,1                     ; subtract one
   subb  r1,0                     ; subtract w/ carry bit
   mov   r2,r1
   shr   r2,8
   mov   r8,DATA0
   mov   b[r8++],r2               ; BYTE3
   mov   b[r8++],r1               ; BYTE2
   mov   r2,r0
   shr   r2,8
   mov   b[r8++],r2               ; BYTE1
   mov   b[r8],r0                 ; BYTE0
   addi  b[(DATA0+6)],2           ; BYTE6 for 512 bytes per page
   jmp   SS_FinalStatus

;**********************************************************************
; SS_TUR (TEST_UNIT_READY) checks for the following error(s):
;        1. WP switch change
; If an error is detected then jump to SS_Err.
; If no errors are present then jump to SS_FinalStatus.
;**********************************************************************
SS_TUR:
   mov   r0,[gHighIn]             ; Test WP
   and   r0,cGPIO18
   cmp   r0,[WP_flag]             ; Compare to last known state
   je    SS_FinalStatus           ; If no change in WP then finish command
   mov   [WP_flag],r0             ; Update WP status
   or    [rCMD],cMedia0           ; Set flag so media change error reported before write protect error
   jmp   SS_Err

;**********************************************************************
; SS_FinalStatus: Completes successful commands
;**********************************************************************
SS_FinalStatus:
   mov   [bStatus],0x100
   mov   r0,[rCMD]
   and   [rCMD],!cRemoved0        ; clear error
   test  r0,(cRemoved0|cEject0)   ; cMedia0| ?
   jnz   SS_Err
   ret

;**********************************************************************
; This will be used in Head/Tail Copy data
;   r3,r4 = Source Sector
;   r5,r6 = Dest   Sector
;   gLen  = Sector Count
;**********************************************************************
DoTailCopy:
   mov   r5,[_gSectorPN_L]        ; save current Dest sector
   mov   r6,b[_gSectorPN_H]  

   mov   r0,[_gSrcBlkPN]          ; read Source Data
   call  _Blk2Pages               ; Blk to Sector
   mov   r3,r0
   mov   r4,r1

   mov   r0,[_gLBA_L],
   and   r0,b[_gPageMask]
   add   r3,r0
   mov   [_gLen],b[_gPageSize]
   sub   [_gLen],r0               ; Tail Len to be copied
   jmp   CopyData

;**********************************************************************
; SS_Read: Sets up read from NAND Flash
;**********************************************************************
SS_Read:
   test  [rCMD],(cEject0|cRemoved0)   ;SSFDC detect insert
   jnz   SS_FinalStatus
   mov   r3,b[_gPageMask]
   and   r3,[_gLBA_L]
_SetupRead:
   call  Sector2PN                ;new page map
   call  _Blk2Pages               ;Sector LN to Sector PN
   or    [_gSectorPN_L],r3        ;add offset
   jmp   _sSetAdd0                ;setup address

;**********************************************************************
; SS_Write: Sets up write from NAND Flash
;**********************************************************************
SS_Write:
   test  [rCMD],(cEject0|cRemoved0)   ;SSFDC detect insert
   jnz   SS_FinalStatus
   call  _SetupWrite              ; Remap and get new PN block
   mov   [_gLen],[_gLBA]
   and   [_gLen],b[_gPageMask]    ; check for HEAD copy DATA
   rz

   mov   r5,r0                    ; need to copy Head
   mov   r6,r1
   mov   r0,[_gSrcBlkPN]          ; read Source Data
   call  _Blk2Pages               ; Blk to Sector
   mov   r3,r0
   mov   r4,r1

;**********************************************************************
; This will be used in Head/Tail Copy data
;   r3,r4 = Source Sector
;   r5,r6 = Dest   Sector
;   gLen  = Sector Count
;**********************************************************************
CopyData:
   push  [_gLBA_L]
cp_lp:
   mov   [_gSectorPN_L],r3
   mov   b[_gSectorPN_H],r4
   xor   r0,r0
   call  _sSetAddr                ; read source data
   call  _sWaitBusy
   mov   r8,[nBuff]               ; user buffer DATA0
   call  _Read512                 ; read DATA
   call  _Read16                  ; read Redundant data
   call  _SetBlkAddr              ; update Redundant area
   mov   [_gSectorPN_L],r5
   mov   b[_gSectorPN_H],r6
   call  _sSetAdd0                ; Set Address for Writing
   mov   r8,[nBuff]               ; user buffer DATA0

   call  _Write512
   call  _Write16
   call  sWritePage
   inc   r3
   inc   r5
   mov   [_gSectorPN_L],r5        ; updated it
   dec   [_gLen]
   jnz   cp_lp
   pop   [_gLBA_L]
   ret
    
;**********************************************************************
; Write:
; Copy Head if lba not align
;     len = lba & 0xf;
; When finish writing all the data:
; Copy Tail when (lba + blk) is not aligned, then erase
;**********************************************************************
_SetupWrite:
   test  [gHighIn],cGPIO18        ; WP=0
   jnz   @f
   or    [rCMD],cMedia0           ; Set media changed error on WP change
   call  SS_FinalStatus
   jmp   SS_Err
@@:
   call  Sector2PN                ; LBA -> PN
   mov   r1,r0
   mov   r9,r8                    ; save current gLog2Phys[zone][gBlockLN]
   mov   [_gSrcBlkPN],r1          ; Head Src Blk
   mov   r6,b[_gZones]

   test  r1,cUSED_MASK            ; check if block is used
   jnz   @f
   call  _SetBlkUsed              ; if used, need to erase
   mov   [_gEraseBlk],r8          ; save erase address
@@:
   call  _GetFreeBlk              ; get dest free block
   mov   [_gDstBlkPN],r0
   and   [r9],0xf000
   or    [r9],r0                  ; gLog2Phys[zone][gBlockLN] = r0
   mov   r1,r0
   call  _SetBlkUsed              ; set this block is used
   call  _SetBlkAddr              ; update Redundant area
   test  [_gSrcBlkPN],cUSED_MASK  ; set src=dest if addr is invalided
   jz    @f
   mov   [_gSrcBlkPN],[_gDstBlkPN] ; make sure to have valid SRC BLK
@@:
   mov   r0,[_gDstBlkPN]          ; fall though to Blk2Page
;**********************************************************************
;  _Blk2Pages: Block Address to 512 sector page
;  Blk2Pages(Blkaddr)
;**********************************************************************
_Blk2Pages:
   mov   r1,b[_gZones]
   ror   r1,6                     ; r1 * Zone
   or    r0,r1
_BlkShft:
   xor   r1,r1                    ; 32-bit shift
   add   r0,r0
   addc  r1,r1
   add   r0,r0
   addc  r1,r1
   add   r0,r0
   addc  r1,r1
   add   r0,r0
   addc  r1,r1
   test  b[_gPageMask],0x10
   jz    b2p_ret
   add   r0,r0
   addc  r1,r1
b2p_ret:
   mov   [_gSectorPN_L],r0        ; save in SectorPN
   mov   b[_gSectorPN_H],r1
   ret

;**********************************************************************
; Write command to FLASH
;**********************************************************************
sCmdWrite:
   mov   [rCNTRL],cCMD_H
   mov   [gLowEn],0xff
sWRITE:
   mov   [gLowOut],r0
   and   [rCNTRL],!cWR            ; Assert cWR
   or    [rCNTRL],cWR             ; Negate cWR
   ret

;**********************************************************************
; Read data from FLASH interface
;**********************************************************************
sREAD:
   and   [rCNTRL], !cRD           ; Assert READ
   mov   r0, b[gLowIn]            ; Read data
   or    [rCNTRL], cRD            ; Negate READ
   ret                            ; Exit

;**********************************************************************
; r0 = 0x80 = Address Write, r0 = 0x00 = Address Read
; sSetAdd0()
; sSetAddr(short cmd)
; Address setting for FLASH
;**********************************************************************
_sSetAdd0:
   mov   r0,b[rCMD]
_sSetAddr:
   call  _sWaitBusy               ; need this for page read/write
   call  sCmdWrite                ; set CLE high
   xor   r0,r0
   mov   [rCNTRL],cALE_H          ; set ALE high
   call  sWRITE
sCommon:
   mov   r0,[_gSectorPN_L]        ; 24-bit address
   call  sWRITE                   ; ALE is high
   shr   r0,8
   call  sWRITE
   mov   r0,[_gSectorPN_H]
   test  r0,cThirdAddr            ; check if 64MB+
   jz    sDATA0
sWRITE0:
   call  sWRITE                   ; ALE is high
   jmp   sDATA0                   ; ALE low (DATA mode)

;**********************************************************************
; Erase Block: [_gSectorPN_H] [_gSectorPN_L]
;**********************************************************************
sWritePage:
   mov   r0,0x10                  ; Write Page
   jmp   sCmdWrite0
sEraseBlock:
   mov   r0,0x60                  ; Start Erase Command
   call  sCmdWrite
   mov   [rCNTRL],cALE_H
   mov   r0,[_gSectorPN_L]        ; 24-bit address
   call  sWRITE                   ; ALE is high
   shr   r0,8
   call  sWRITE
   mov   r0,[_gSectorPN_H]
   test  r0,cThirdAddr            ; check if 64MB+
   jz    sSetEndCmd
   call  sWRITE                   ; ALE is high
sSetEndCmd:
   mov   r0,0xd0                  ; end erase command
sCmdWrite0:
   call  sCmdWrite
sDATA0:
   mov   [rCNTRL],cDATA_H
   mov   [gLowEn],0               ; set INPUT mode
   ret
;**********************************************************************
; _sWaitBusy: Waits for BUSY pin on NAND Flash to go high
;**********************************************************************
_sWaitBusy:
   test  [gLowIn],cRB             ; Check BUSY
   jz    _sWaitBusy               ; Wait while BUSY is LO
   ret

;**********************************************************************
; void SetBlkAddr(addr)
; redundant: 0xffff, 0xffff, 0xffff, wAddr1, bECC2[3], wAddr2, bECC1[3]
;**********************************************************************
_SetBlkAddr:
   mov   r0,[_gBlockLN]
   mov   r8,_gRedunt
   mov   [r8],-1                  ; set 0xffff, 0xffff, 0xffff
   mov   [r8],[r8++]
   mov   [r8++],[r8++]            ; set Status
   shl r0,0x1
   or r0,0x1000
BitCnt:
   xor   r2,r2                    ; r2 = 0
   mov   r1,1
bitloop:
   test  r0,r1                    ; count the number of bits in word
   jz    @f
   inc   r2                       ; r2++
@@:
   shl   r1,1
   jnz   bitloop
   test  r2,0x1                   ; check if odd/even parity bit
   jz  @f
   inc   r0
@@:
   mov   r1,r0
   shr   r0,8
   mov   b[r8++],r0               ; MSB of Addr1
   mov   b[r8],r1                 ; LSB of Addr1
   addi  r8,4
   mov   b[r8++],r0               ; MSB of Addr2
   mov   b[r8],r1                 ; LSB of Addr2
   ret

;**********************************************************************
; _MapLog2Phys: Converts logical block to physical block
;   short MapLog2Phys()
;**********************************************************************
_MapLog2Phys:
   mov   r0,[_gLBA_L]
   mov   r1,[_gLBA_H]
   shr   r0,4                     ; 16 pages
   shl   r1,8
   and   r0,0x0fff        
   test  [_gPageMask],0x10        ; page=32
   jz    @f
   shr   r0,1
   shl   r1,3                     ; shift left 11
   jmp   p2b_exit
@@:
   shl   r1,4                     ; shift left 12
p2b_exit:
   or    r1,r0                    ; gBlockLN
   xor   r0,r0                    ; zone=0
   mov r2,[_gLogBlocks]         ; return remainder in r1
map_lp:
   cmp r1,r2
   jc @f
   sub r1,r2
   inc   r0                       ; inc zone
   jmp map_lp
@@:
   mov   [_gBlockLN],r1
   mov   b[_gZones],r0
;**********************************************************************
; short GetLog2Phys(short zone, short addr)
;**********************************************************************
_SetLog2Phys:
_GetLog2Phys:
   mov   r8,r1
   shl r8,0x1                   ; r8 = remainder
   ror   r0,0x5                   ; r0 * 32
   add r8,r0
   add r8,_gLog2Phys
   ret

;**********************************************************************
; need r1=blk addr
;**********************************************************************
_SetBlkUsed:
   mov   r0,r6
   call  _SetLog2Phys             ; BLK USE = 0x0xxx
   and   [r8],0xfff
   ret

;**********************************************************************
; short GetFreeBlk()
;**********************************************************************
_GetFreeBlk:
   mov   r1,[_gSrcBlkPN]
   mov   r3,[_gMaxBlocks]         ; for (i=addr; i<gMaxBlocks; i++)
   mov   r2,b[_gZones]            ; setup constant for zone
   ror   r2,5
   call  sGetFree
   rz
   xor   r1,r1
   mov   r3,[_gSrcBlkPN]          ; for (i=0; i<addr; i++)
sGetFree:
   cmp   r1,r3                    ; return if r1>r3
   rg
@@:
   mov   r8,r1
   shl   r8,1                     ; word
   add   r8,r2                    ; add zone
   mov   r0,[r8+_gLog2Phys]
   and   r0,cBLK_FREE             ; mark of
   cmp   r0,cBLK_FREE             ; return zero flag
   je    sFreeExit
   inc   r1
   cmp   r1,r3
   jb    @b
   or    r0,r8                    ; return non zero flag
sFreeExit:
   mov   r0,r1
   ret

;**********************************************************************
; return r0        -> PN Block Address
;        gBlockLN  -> contains logical block address
; return r8        -> pointer to address of gLog2Phys[zone][gBlockLN]
;**********************************************************************
Sector2PN:
   call  _MapLog2Phys             ; LN block to PN block
   mov   r0,[r8]
   and   r0,0x0fff                ; get PN block address
   ret

;**********************************************************************
; ECC code include
;**********************************************************************
   .xlist
   include secc.asm
   .list
_gLogBlocks:   dw  1000

;************************************************************************
SS_Inquiry:                       ; set byte0 = DIRECT_ACCESS_DEVICE = 0
Do_Inquiry:
   mov   r8,DATA0
#ifdef HD_ICON
   xor   [r8++],[r8]
#else
   mov   [r8++],0x8000         ; set Removable Media bit
#endif
   xor   [r8++],[r8]
   xor   [r8++],[r8]                  
   xor   [r8++],[r8]              ; point to o_VendorID at offset 8
   mov   r9,str2
   mov   r1,((STR1_LEN-2)/2)
@@:
   mov   b[r8++],[r9++]           ; copy Mfg and Prod String
   dec   r1
   jnz   @b
   mov   r1,40
@@:
   mov   b[r8++],0x20
   dec   r1
   jnz   @b
   ret

;**********************************************************************
; The time of delay generated by this function varies on clock frequency
; This code should not be directly ported to other platforms
;**********************************************************************
Delay:
   mov   r0,-1                  ;delay here
@@:
   dec   r0
   jnz   @b
   ret

;**********************************************************************
; Common code for both CF/SSFDC
;**********************************************************************
Save_LBA:
   addi  r9,2
   mov   b[(_gLBA_H+1)],b[r9++]   ;byte3
   mov   b[(_gLBA_H+0)],b[r9++]   ;byte2
   mov   b[(_gLBA_L+1)],b[r9++]   ;byte1
   mov   b[(_gLBA_L+0)],b[r9++]   ;byte0
   inc   r9                       ;CDB[7]
   mov   b[(_gBLK+1)],b[r9++]     ;MSB
   mov   b[(_gBLK+0)],b[r9]       ;LSB number of sector
   mov   r8,DATA0
   ret

;**********************************************************************
; _Build_Table: Build the Logical to Physical remap table
;**********************************************************************
_Build_Table:
   mov   r8,_gLog2Phys
   mov   r0,(cMaxBlocks*4)
   mov   r4,0xffff
@@:
   mov   [r8++],r4                ; mask all blocks erased
   mov   [r8++],r4                ; mask all blocks erased
   dec   r0
   jnz   @b
   xor   r6,r6                    ; initialize all remap table
   mov   [_gSectorPN_L],r6
   mov   b[_gSectorPN_H],r6
zone_lp:
   xor   r5,r5
blk_lp:
   mov   r0,0x50                  ; read redundant area
   call  _sSetAddr
   mov   r9,4                     ; try 4 pages
getlp:
   call  _sWaitBusy
   call  _Read16
   mov   r8,(_gRedunt+6)
   mov   r3,b[r8++]               ; addr1-MSB
   shl   r3,8
   or    r3,b[r8]                 ; addr1-LSB
   addi  r8,4
   mov   r2,b[r8++]               ; addr2-MSB
   shl   r2,8
   or    r2,b[r8]                 ; addr2-LSB
   cmp   r3,r2                    ; if (addr1 = addr2)
   jnz   next_page
   cmp   r3,r4                    ; check blank
   jz    ChkBlank
   and   r2,0xf000                ; r2 & 0xF000
   cmp   r2,0x1000                ; if (r2 = 0x1000)
   jnz   next_page              
   mov   r1,r3
   and   r1,0x0fff                ; return valid address
   shr   r1,1
   mov   r0,r6
   call  _SetLog2Phys             ; gLog2Phys[r0][r1]=r5
   and   [r8],0xf000              ; update Blk Address
   or    [r8],r5                
   xor   r2,r2                    ; set Blk Used
   jmp   SetBlkUsed
next_page:
   and   r6,r6                    ; other zone is OK
   jnz   @f
   cmp   r5,2                     ; only 1-time for block0-1
   jb    ChkBlank
@@:  
   dec   r9                       ; retry 4 times
   jnz   getlp
ChkBlank:
   mov   r8,_gRedunt
   mov  r0,4
chkloop:
   cmp   [r8++],r4                ; check for blank data = 0xffff
   jnz   SetBlkBad
   dec   r0
   jnz   chkloop
   jmp   SetInc                   ; skip set the bad block
SetBlkBad:
   mov   r2,cBLK_BAD
SetBlkUsed:
   mov   r1,r5
   call  _SetBlkUsed              ; gLog2Phys[r0][r5]=r2
   or    [r8],r2          
SetInc:
   add   [_gSectorPN_L],b[_gPageSize]
   addc  b[_gSectorPN_H],0

   inc   r5
   cmp   r5,[_gMaxBlocks]
   jb    blk_lp

   inc   r6
   cmp   r6,b[_gMaxZones]
   jb    zone_lp
SM_Reset:
   mov   r0,0xff
   call  sCmdWrite0
   jmp   _sWaitBusy               ; exit

;**********************************************************************
; sReadID: Reads ID and determines capacity
;   r8 = buffer
;**********************************************************************
sReadID:
   call  _sWaitBusy
   mov   r0,0x90                  ; ReadID command
   call  sCmdWrite
   mov   [rCNTRL],cALE_H          ; set ALE high
   xor   r0,r0
   call  sWRITE0
   call  sREAD                    ; maker code
   call  sREAD                    ; SSFD card ID
   mov   r1, 32                   ; Assume 32 Pages
   mov   r2, 8                    ; 8 zones  
   mov   r3, 1024                 ; Assume 1024 Log blocks/Zone
   mov   r4, 1000
   mov   r5, 8000
   mov   [_gSectorPN_H],cThirdAddr

   cmp   r0, 0x79                 ; 8192B/32P = 128MB
   je    sID_Exit            
   cmp   r0, 0xDA                 ; 8192B/32P
   je    sID_Exit            

   shr   r2,1                     ; 4 zones
   shr   r5,1
   cmp   r0, 0x76                 ; 4096B/32P = 64MB
   je    sID_Exit            
   cmp   r0, 0xD9                 ; 4096B/32P
   je    sID_Exit            
   mov   [_gSectorPN_H],r2        ; clear cThirdAddr and 2MB device

   shr   r2,1                     ; Assume 2 Zones
   shr   r5,1
   cmp   r0, 0x75                 ; 2048B/32P = 32MB
   je    sID_Exit                 ; Yep    
   cmp   r0, 0x58                 ; 2048B/32P
   je    sID_Exit                 ; Yep

   shr   r2, 1                    ; Assume 1 Zones
   shr   r5, 1
   cmp   r0, 0x73                 ; 1024B/32P = 16MB
   je    sID_Exit                 ; Yep    
   cmp   r0, 0x57                 ; 1024B/32P
   je    sID_Exit                 ; Yep

   shr   r1, 1                
   cmp   r0, 0xE6                 ; 1024B/16P = 8MB
   je    sID_Exit                 ; Yep    
   cmp   r0, 0xD6                 ; 1024B/16P
   je    sID_Exit                 ; Yep

   shr   r3,1                     ; check 4MB
   shr   r4,1
   shr   r5,1

sID_Exit:
   mov   b[_gPageSize],r1         ; page size
   dec   r1
   mov   b[_gPageMask],r1         ; mask
   mov   b[_gMaxZones],r2         ; max zone
   mov   [_gMaxBlocks],r3
   mov   [_gLogBlocks],r4         ; max log block
   mov   r0, 0x70                 ; Send the command
   call  sCmdWrite0            
   call  sREAD
   test  r0,0x80                  ; check Write Protect bit
   rnz
   or    [_gSectorPN_H],cWP_Status
   ret

_gMaxZones:    db  0
_gZones:       db  0
_gPageSize     db  0
_gPageMask:    db  0
_gMaxBlocks:   dw  0

;**********************************************************************
; SS_Format: Erases entire FLASH and prepares for use
;**********************************************************************
SS_Format:
   call  sReadID
   xor   r0,r0
   mov   [_gSectorPN_L],r0        ;starting block 0
   mov   b[_gSectorPN_H],r0
   mov   r6,b[_gMaxZones]
   ror   r6,6                     ;get the number of zone
fm_lp:
   call  sEraseBlock              ;erase current block
   call  _sWaitBusy
   add   [_gSectorPN_L],b[_gPageSize]
   addc  b[_gSectorPN_H],0
   dec   r6                       ;whole flash device
   jnz   fm_lp

   mov   r5,56
   mov   r8,DATA0
   mov   r9,CIS
   mov   r11,(DATA0+0x100)
@@:
   mov   [r8++],[r9]
   mov   [r11++],[r9++]
   dec   r5
   jnz   @b
   mov   r5,72
@@:
   xor   [r8++],[r8]
   xor   [r11++],[r11]
   dec   r5
   jnz   @b
   mov   r8,_gRedunt
   mov   r9,CIS_r
   addi  r5,8
@@:
   mov   [r8++],[r9++]
   dec   r5
   jnz   @b
   mov   [_gSectorPN_L],r5
   mov   b[_gSectorPN_H],r5
   mov   b[rCMD],0x80             ;Set Address for Writing
   call  _sSetAdd0
   mov   r8,DATA0
   call  _Write512                ;Write DATA
   call  _Write16                 ;Write redundant DATA
   call  sWritePage               ;Enable the Write Command
   xor   r7,r7
   jmp   _sWaitBusy
CIS:
   dw    0x0301
   dw    0x01d9
   dw    0x18ff
   dw    0xdf02
   dw    0x2001
   dw    0x0004
   dw    0x0000
   dw    0x2100

   dw    0x0402
   dw    0x2201
   dw    0x0102
   dw    0x2201
   dw    0x0203
   dw    0x0704
   dw    0x051a
   dw    0x0301

   dw    0x0200
   dw    0x1b0f
   dw    0xc008
   dw    0xa1c0
   dw    0x5501
   dw    0x0008
   dw    0x1b20
   dw    0xc10a

   dw    0x9941
   dw    0x5501
   dw    0xf064
   dw    0xffff
   dw    0x1b20
   dw    0x820c
   dw    0x1841
   dw    0x61ea

   dw    0x01f0
   dw    0xf607
   dw    0x0103
   dw    0x1bee
   dw    0x830c
   dw    0x1841
   dw    0x61ea
   dw    0x0170

   dw    0x7607
   dw    0x0103
   dw    0x15ee
   dw    0x0514
   dw    0x2000
   dw    0x2020
   dw    0x2020
   dw    0x2020

   dw    0x2000
   dw    0x2020
   dw    0x0020
   dw    0x2e30
   dw    0x0030
   dw    0x14ff
   dw    0xff00
   dw    0x0000

CIS_r:
   dw    0xffff
   dw    0xffff
   dw    0xffff
   dw    0x0000
   dw    0xcc0c
   dw    0x00c3
   dw    0x0c00
   dw    0xc3cc
code_end:
IRAM4_E:
   err<z (IRAM3Size - (IRAM3_E-IRAM3_S)-(IRAM4_E-IRAM4_S)-(cMAXSIZE+cVars_Used)) ; check if go over limited
   reloc_off
   err<z (I2CSize - $)
www.dragon-2008.com 欢迎交流
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-06-14 16:04
各位大侠大都搞过U盘的开发,想来对FLASH的读写,有一定的心得。
为什么不能够给新手以指点,使其不在走弯路,恳请各位给于帮忙,不盛感激。
leexiogn 倚天而行 任意而为
flyhye
驱动小牛
驱动小牛
  • 注册日期2003-07-01
  • 最后登录2012-01-11
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-05-31 15:05
我刚开始写的时候就是看nand flash 的spec。
不过偶的代码不敢给,套用一句话:“那么多bug,能见人吗?”
:)

不过记得好像这里以前有人发过
千载奇逢,无如好书良友 一生清福,只在碗茗炉烟
lixiaojun_001
驱动牛犊
驱动牛犊
  • 注册日期2004-04-01
  • 最后登录2008-01-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-05-31 13:44
乱世当用重典,求资料我用重金.
leexiogn 倚天而行 任意而为
游客

返回顶部