SD卡升级实现方法之UBOOT+WINCE应用

来源:互联网 发布:天空表白墙源码 编辑:程序博客网 时间:2024/06/07 18:45

/************************************************************************/
/* Copyright(c)  ?, ?              */
/* Created By ztg                                      */
/* File: efDlg.cpp                    */
/* Ver: 1.0.1               */
/* Project:                */
/* Description:                                                    */
/************************************************************************/

 

#include "stdafx.h"
#include "ef.h"
#include "efDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
volatile NANDreg *s2440NAND = (NANDreg *)NAND_BASE;
volatile CLKPWRreg *s2440CLKPWR = (CLKPWRreg *)CLKPWR_BASE;

//#define NFChipEn()  (s2440NAND->rNFCONT &= ~(1<<1))
#define EnNandFlash() (s2440NAND->rNFCONT |= 1)
#define DsNandFlash() (s2440NAND->rNFCONT &= ~1)
#define NFChipEn()  (s2440NAND->rNFCONT &= ~(1<<1))
#define NFChipDs()  (s2440NAND->rNFCONT |= (1<<1))
#define InitEcc()  (s2440NAND->rNFCONT |= (1<<4))
#define MEccUnlock() (s2440NAND->rNFCONT &= ~(1<<5))
#define MEccLock()  (s2440NAND->rNFCONT |= (1<<5))
#define SEccUnlock() (s2440NAND->rNFCONT &= ~(1<<6))
#define SEccLock()  (s2440NAND->rNFCONT |= (1<<6))

//#define WrNFDat8(dat) (s2440NAND->rNFDATA = (dat))//rNFDATA8
#define WrNFDat8(dat) (s2440NAND->rNFDATA8 = (dat))
//#define WrNFDat32(dat) (s2440NAND->rNFDATA = (dat))
//#define RdNFDat8()  (s2440NAND->rNFDATA) //byte access//rNFDATA8
#define RdNFDat8()  (s2440NAND->rNFDATA8) //byte access
//#define RdNFDat32()  (s2440NAND->rNFDATA) //word access

#define WrNFCmd(cmd) (s2440NAND->rNFCMMD = (cmd))
#define WrNFAddr(addr) (s2440NAND->rNFADDR = (addr))
#define WrNFDat(dat) WrNFDat8(dat)
#define RdNFDat()  RdNFDat8() //for 8 bit nand flash, use byte access

#define RdNFMEcc()  (s2440NAND->rNFMECC0) //for 8 bit nand flash, only use NFMECC0
#define RdNFSEcc()  (s2440NAND->rNFSECC) //for 8 bit nand flash, only use low 16 bits

#define RdNFStat()  (s2440NAND->rNFSTAT)
#define NFIsBusy()  (!(s2440NAND->rNFSTAT&1))
#define NFIsReady()  (s2440NAND->rNFSTAT&1)

#define READCMD0 0
#define READCMD1 1
#define READCMD2 0x50
#define ERASECMD0 0x60
#define ERASECMD1 0xd0
#define PROGCMD0 0x80
#define PROGCMD1 0x10
#define QUERYCMD 0x70
#define RdIDCMD  0x90

static U16 NandAddr;
// CefDlg 对话框

CefDlg::CefDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CefDlg::IDD, pParent)
{
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CefDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CefDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
 ON_WM_SIZE()
#endif
 //}}AFX_MSG_MAP
 ON_BN_CLICKED(IDC_UpData, &CefDlg::OnBnClickedUpdata)
 ON_BN_CLICKED(IDC_BUTTON1, &CefDlg::OnBnClickedButton1)
 ON_BN_CLICKED(IDC_UpDateWINCE, &CefDlg::OnBnClickedUpdatewince)
 ON_BN_CLICKED(IDOK, &CefDlg::OnBnClickedOk)
 ON_BN_CLICKED(IDC_AUTO, &CefDlg::OnBnClickedAuto)
END_MESSAGE_MAP()


// CefDlg 消息处理程序
CProgressCtrl myCtrl;

BOOL CefDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
 //  执行此操作
 SetIcon(m_hIcon, TRUE);   // 设置大图标
 SetIcon(m_hIcon, FALSE);  // 设置小图标
 
 this->SetWindowPos(&CWnd::wndBottom, 0, 0, 315, 190,SWP_SHOWWINDOW);
 this->SetWindowText(_T("UpData"));
 CenterWindow(GetDesktopWindow()); // center to the hpc screen

    volatile NANDreg *s2440NAND = (NANDreg *)NAND_BASE;
    volatile CLKPWRreg *s2440CLKPWR = (CLKPWRreg *)CLKPWR_BASE;
 s2440NAND = (volatile NANDreg *)VirtualAlloc(0, sizeof(NANDreg), MEM_RESERVE, PAGE_NOACCESS); 
 s2440CLKPWR = (volatile CLKPWRreg *)VirtualAlloc(0, sizeof(CLKPWRreg), MEM_RESERVE, PAGE_NOACCESS);
 InitNandFlash(1);
 //VirtualFree((PVOID) s2440NAND, 0, MEM_RELEASE);
 //VirtualFree((PVOID) s2440CLKPWR, 0, MEM_RELEASE);

 myCtrl.Create(WS_CHILD|WS_VISIBLE,CRect(10,90,303,110),this,1);

 // TODO: 在此添加额外的初始化代码
 
 return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CefDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
 DRA::RelayoutDialog(
  AfxGetInstanceHandle(),
  this->m_hWnd,
  DRA::GetDisplayMode() != DRA::Portrait ?
   MAKEINTRESOURCE(IDD_EF_DIALOG_WIDE) :
   MAKEINTRESOURCE(IDD_EF_DIALOG));
}
#endif
int pri=1;
void CefDlg::OnBnClickedButton1()//update bootloader
{
 // TODO: 在此添加控件通知处理程序代码
 WrFileToNF(0); 
 s2440NAND->rNFCONT &= ~1;  //disable nand flash interface
 AfxMessageBox(L"UpDate BootLoader Ok");
 myCtrl.SetPos(0);
}
void CefDlg::OnBnClickedUpdatewince()//update wince
{
 // TODO: 在此添加控件通知处理程序代码
 
 WrFileToNF(1);
 s2440NAND->rNFCONT &= ~1;  //disable nand flash interface
 AfxMessageBox(L"UpDate Wince Ok");
 myCtrl.SetPos(0);

}

void CefDlg::OnBnClickedUpdata()//update logo

 WrFileToNF(2);
 s2440NAND->rNFCONT &= ~1;  //disable nand flash interface
 AfxMessageBox(L"UpDate Logo Ok");
 myCtrl.SetPos(0);

}


/************************************************************/
static int have_nandflash;
void InitNandFlash(int info)

 U32 i;
 //RETAILMSG(1, (_T("SALCD2: DisplayInit: can't open '%s'/r/n"), gszBaseInstance));
 //RETAILMSG(1, (_T("NandFlash Init+/r/n")));
 InitNandCfg();
 
 i = ReadChipId();//Read chip id = ec76
 
 //if(info)
 //RETAILMSG(1, (_T("Read chip id = %x/n"), i));

 if((i==0x9873)||(i==0xec75)) 
  NandAddr = 0;
 else if(i==0xec76)
  NandAddr = 1;
 else {
  if(info) 
   //puts("Chip id error!!!/n");
  have_nandflash = 0;
  return;
 }
 have_nandflash = 1;
 //if(info)
  //RETAILMSG(1, (_T("Nand flash status = %x/n"), ReadStatus()));

  
}


static void InitNandCfg(void)
{
 s2440CLKPWR->rCLKCON |= (1<<4);
 s2440NAND->rNFCONF = (0<<12)|(6<<8)|(0<<4)|(0<<0); 
 s2440NAND->rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
 s2440NAND->rNFSTAT = 0;

}

static U32 ReadChipId(void)
{
 U32 id;
 
 NFChipEn();
 WrNFCmd(RdIDCMD);
 WrNFAddr(0);
 while(NFIsBusy()); 
 id  = RdNFDat()<<8;
 id |= RdNFDat();  
 NFChipDs();  
 return id;
 
}

static U16 ReadStatus(void)
{
 U16 stat;
 
 NFChipEn(); 
 WrNFCmd(QUERYCMD);  
 stat = RdNFDat(); 
 NFChipDs();
 
 return stat;
}

//0xAEC00000
U32 downloadAddress=0xAE200000, downloadFileSize=0x0;//(B0000000-AE00000=2000000~~~32M)
static U32 StartPage1;
static U32 BlockCnt;

static int NandSelPart(int update)
{
// U16 i, max_sel;
 struct Partition *ptr = NandPart;
if(0==update)
 {
 //printf("Write to nand flash part_3: offset 0x%-8x, size 0x%-8x [%s]/n", ptr->offset, ptr->size, ptr->name);
 StartPage1 = NandPart[0].offset>>9;
 BlockCnt  = NandPart[0].size>>14;
 return 0;
    }
if(1==update)
 {
  ptr+=1;
  //printf("Write to nand flash part_3: offset 0x%-8x, size 0x%-8x [%s]/n", ptr->offset, ptr->size, ptr->name);
  StartPage1 = NandPart[1].offset>>9;
  BlockCnt  = NandPart[1].size>>14;
  return 1;
 }

if(2==update)
{
 ptr+=3;
 //printf("Write to nand flash part_3: offset 0x%-8x, size 0x%-8x [%s]/n", ptr->offset, ptr->size, ptr->name);
 StartPage1 = NandPart[3].offset>>9;
 BlockCnt  = NandPart[3].size>>14;
 return 3;
}

 return -1;  
}

//update:0--Update bootloader
//update:1--Update WINCE
//update:2--Update LOGO
void WrFileToNF(int update)
{

 int nf_part, i ,size, skip_blks;
 int retval;
 U32 ram_addr;
 char cpath[80];
 char*  szFilePath;

 nf_part = NandSelPart(update);
 if(nf_part<0)
  return;
 
 if(0==update)
  {
  szFilePath = "//SDMEM//UpData//Uboot.bin/0";
     myCtrl.SetRange(1,10);
  }
    if(1==update)
     {
  szFilePath = "//SDMEM//UpData//NK.nb0/0";
     myCtrl.SetRange(1,293);
     }
 if(2==update)
  {
     szFilePath = "//SDMEM//UpData//LOGO480234.bin/0";
     myCtrl.SetRange(1,10);
  }
 //downloadFileSize=NandPart[nf_part].size -= 32<<9;;
 downloadFileSize=NandPart[nf_part].size -= 32<<9;;
 
 strcpy(cpath,szFilePath);
 FILE * fp1;
 fp1  = fopen(cpath, "rb" );
 if(!fp1)
  {
     //printf("fopen flase[%x]/n",fp1); 
  AfxMessageBox(L"fopen flase");
  return;
  }
 retval = fread((void*)downloadAddress, 1 , downloadFileSize, fp1);
 fclose(fp1);


  if(downloadFileSize>NandPart[nf_part].size) {
   //puts("Download file size is more large than selected partition size!!!/n");
   ;//return;
  }
 //printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d/n", StartPage1, downloadAddress, downloadFileSize);
 skip_blks = 0;
 ram_addr = downloadAddress;
 size = downloadFileSize;//0x187b6e0;//
    //printf("size=[%d],part[%d]/n",size,nf_part);
 
 for(i=0; size>0; ) { 
  if(!(i&0x1f)) {
   if(EraseBlock(i+StartPage1)) {
    NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
    if(downloadFileSize>NandPart[nf_part].size) {
     //puts("Program nand flash fail/n");
     ;//return;
    }
    MarkBadBlk(i+StartPage1);
    skip_blks++;    
    i += 32;    
    continue;
   }
  }
  //*
  if(WritePage(i+StartPage1, (U8 *)ram_addr)) {
   ram_addr -= (i&0x1f)<<9;
   size += (i&0x1f)<<9;
   i &= ~0x1f;
   NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
   if(downloadFileSize>NandPart[nf_part].size) {
    //puts("Program nand flash fail/n");
    ;//return;
   }   
   MarkBadBlk(i+StartPage1);
   skip_blks++;   
   i += 32;   
   continue;
  }
  //*/
  ram_addr += 512;
  size -= 512;
  i++;
 }

 //puts("Program nand flash partition success/n");
 //if(skip_blks)
  //printf("Skiped %d bad block(s)/n", skip_blks);
}

static U32 EraseBlock(U32 addr)
{
 
 U8 stat;
 //printf("EraseBlock+/n"); 

 addr &= ~0x1f;
  
 NFChipEn(); 
 WrNFCmd(ERASECMD0);  
 WrNFAddr(addr);
 WrNFAddr(addr>>8);
 if(NandAddr)
  WrNFAddr(addr>>16);
 WrNFCmd(ERASECMD1);  
 stat = WaitNFBusy();
 NFChipDs();
 //putch(".");
 //printf(".");
  pri++;
 if(pri>290)pri=1;
  {
   myCtrl.SetPos(pri);
   //Sleep(10);
  }
 //printf("Erase block 0x%x %s/n", addr, stat?"fail":"ok"); 
 //printf("EraseBlock-/n"); 
 return stat;
 
}

static U32 WaitNFBusy(void) // R/B 未接好?
{
 U8 stat;
 
 WrNFCmd(QUERYCMD);
 do {
  stat = RdNFDat();
  //printf("%x/n", stat);
 }while(!(stat&0x40));
 WrNFCmd(READCMD0);
 return stat&1;
}

static U32 WritePage(U32 addr, U8 *buf)
{
 U32 i, mecc;
 U8 stat, tmp[7];
 //volatile NANDreg *s2440NAND= (NANDreg *)NAND_BASE; ;
 //printf("WritePage+/n");
 NFChipEn();
 WrNFCmd(PROGCMD0);
 WrNFAddr(0);
 WrNFAddr(addr);
 WrNFAddr(addr>>8);
 //printf("WritePage+1/n");
 if(NandAddr)
  WrNFAddr(addr>>16);
 InitEcc(); //reset mecc and secc
 MEccUnlock();
 //printf("WritePage+2/n");
 for(i=0; i<512; i++)
  WrNFDat((U32)buf[i]);
 MEccLock();
 mecc = RdNFMEcc();
  
 tmp[0] = mecc&0xff;
    tmp[1] = (mecc>>8)&0xff;
    tmp[2] = (mecc>>16)&0xff;
    tmp[3] = (mecc>>24)&0xff;
    tmp[5] = 0xff; //mark good block
    //printf("WritePage+3/n");
    SEccUnlock();
 WrNFDat(tmp[0]);
 WrNFDat(tmp[1]);
 WrNFDat(tmp[2]);
 WrNFDat(tmp[3]);
 SEccLock();
 WrNFDat(tmp[4]);
 WrNFDat(tmp[5]);
     
 WrNFCmd(PROGCMD1);
 stat = WaitNFBusy();
 NFChipDs();
   
 if(stat)
  //printf("Write nand flash 0x%x fail/n", addr);
     AfxMessageBox(L"Write nand flash 0x%x fail");
 else { 
  U8 RdDat[512];
  
  ReadPage(addr, RdDat);  
  for(i=0; i<512; i++)
   if(RdDat[i]!=buf[i]) {
    //printf("Check data at page 0x%x, offset 0x%x fail/n", addr, i);
    stat = 1;
    break;
   }
 }
  
 //printf("WritePage-/n");
 return stat; 
}


//addr = page address
static void ReadPage(U32 addr, U8 *buf)
{
 U16 i;
 //printf("ReadPage+/n");
 
 NFChipEn();
 WrNFCmd(READCMD0);
 WrNFAddr(0);
 WrNFAddr(addr);
 WrNFAddr(addr>>8);
 if(NandAddr)
  WrNFAddr(addr>>16);
 InitEcc();
 WaitNFBusy();
 //printf("ReadPage++/n");
 for(i=0; i<512; i++)
  {
  buf[i] =RdNFDat();
  }
 NFChipDs(); 
 //printf("ReadPage-");
}

static void MarkBadBlk(U32 addr)
{
 addr &= ~0x1f;
 
 NFChipEn();
 
 WrNFCmd(READCMD2); //point to area c
 
 WrNFCmd(PROGCMD0);
 WrNFAddr(4);  //mark offset 4,5,6,7
 WrNFAddr(addr);
 WrNFAddr(addr>>8);
 if(NandAddr)
  WrNFAddr(addr>>16);
 WrNFDat(0);   //mark with 0
 WrNFDat(0);
 WrNFDat(0);   //mark with 0
 WrNFDat(0);
 WrNFCmd(PROGCMD1);
 WaitNFBusy();  //needn't check return status
 
 WrNFCmd(READCMD0); //point to area a
  
 NFChipDs();
}


void CefDlg::OnBnClickedButton2()
{
 // TODO: 在此添加控件通知处理程序代码
}


void CefDlg::OnBnClickedAuto()
{
 // TODO: 在此添加控件通知处理程序代码
 WrFileToNF(0); 
 myCtrl.SetPos(0);
 WrFileToNF(1); 
 myCtrl.SetPos(0);
 WrFileToNF(2);
 VirtualFree((PVOID) s2440NAND, 0, MEM_RELEASE);
 VirtualFree((PVOID) s2440CLKPWR, 0, MEM_RELEASE);
 AfxMessageBox(L"UpDate  Ok");
 myCtrl.SetPos(0);
}

void CefDlg::OnBnClickedOk()
{
 // TODO: 在此添加控件通知处理程序代码
 OnOK();
}

原创粉丝点击