您的位置: OpenADSP社区论坛 -> Blackfin专区 -> 技术讨论区 -> 牛人哪里去了 有人能解答我的问题吗 关于BF... 
本帖共有729个阅读者
发表帖子 发表投票 回复主题
牛人哪里去了 有人能解答我的问题吗 关于BF533移植spi读写nandflash的驱动
qq138243366(论坛新手)
qq138243366
头衔:社区公民
帮派:无帮无派
帖数:3
金钱:131
积分:5
注册时间:2012/9/24
楼主信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
牛人哪里去了 有人能解答我的问题吗 关于BF533移植spi读写nandflash的驱动

我把代码贴出来 还请专家帮忙看看如何修改

现在主要的问题就是刚配置完中断 中断处理函数就会被执行 根本等不到数据到来 而且会影响到其他任务无法继续执行 即使在中断处理函数里把中断关闭并清中断

// ST serial flash commands
#define ST_WREN   0x06 // write enable
#define ST_WRDI   0x04 // write disable
#define ST_RDSR   0x05 // read status register
#define ST_WRSR   0x01 // write status register
#define ST_READ   0x03 // read data bytes
#define ST_FAST_READ 0x0B // read data bytes at higher speed
#define ST_PP   0x02 // page program
#define ST_SE   0xD8 // sector erase
#define ST_BE   0xC7 // bulk erase
#define ST_RES   0xAB // release from deep power-down and read electronic signature
#define ST_RMD   0x90 // read manufaction and device code

// status flags
#define ST_WIP   0x01 // write in progress

#define TIMOD_RX  0x00
#define TIMOD_TX  0x01
#define TIMOD_DMA_RX 0x02
#define TIMOD_DMA_TX 0x03
#define SELECT()  *pFIO_FLAG_C = SF_CS
#define DESELECT()  *pFIO_FLAG_S = SF_CS


INT32u giSfPage;
INT16u giSfCtr;
INT32u giSfSpiBaud;

#define SPI_DMA_INT_MODE 0
#define SPI_DMA_QUERY_MODE 1


#define DMA5_READ 0
#define DMA5_WRITE 1

OS_EVENT         *OSStRxSignal;
OS_EVENT         *OSStTxSignal;

int RUNNING;

#if SPI_DMA_INT_MODE
INT8U  StRxPostSignal (void)
{
    INT8U  err;

    err = OSSemPost(OSStRxSignal);
    return (err);
}

INT8U StRxCreateSignal (void)
{
INT8U  err;
    OSStRxSignal = OSSemCreate(0);
    
#if OS_EVENT_NAME_SIZE > 10
    OSEventNameSet(OSStRxSignal, (INT8U *)"OS-STRX",          &err);
#endif
    return (err);
}

INT8U  StRxPendSignal (void)
{
INT8U  err;
    OSSemPend(OSStRxSignal, 0, &err);  
    return (err);
}

INT8U  StTxPostSignal (void)
{
    INT8U  err;

    err = OSSemPost(OSStTxSignal);
    return (err);
}

INT8U StTxCreateSignal (void)
{
INT8U  err;
    OSStTxSignal = OSSemCreate(0);
    
#if OS_EVENT_NAME_SIZE > 10
    OSEventNameSet(OSStTxSignal, (INT8U *)"OS-STTX",          &err);
#endif
    return (err);
}

INT8U  StTxPendSignal (void)
{
INT8U  err;
    OSSemPend(OSStTxSignal, 0, &err);  
    return (err);
}

void SPI_DMA5_ISR(void)
{
printf("\nSPI_DMA5_ISR HAPPEN RUNNING = %d\n",RUNNING);

*pSPI_CTL &=  ~SPE;
*pDMA5_CONFIG = 0;
if(RUNNING == DMA5_READ)
{
  StRxPostSignal();
}
else if(RUNNING == DMA5_WRITE)
{
  StTxPostSignal();
}
}

void Init_SPI_Interrupts(void)
{
StRxCreateSignal();
*pSIC_IAR0 = *pSIC_IAR0 & 0xffffffff | 0x00000000;
*pSIC_IAR1 = *pSIC_IAR1 & 0xff0fffff | 0x00300000;  
*pSIC_IAR2 = *pSIC_IAR2 & 0xffffffff | 0x00000000;              
OS_CPU_RegisterHandler(IVG10, SPI_DMA5_ISR, NOT_NESTED);
//*pDMA5_CONFIG &= ~DI_EN;
    *pSIC_IMASK |=0x00002000;  
}
#endif
// This function will check what the system clock is based
// on the _MSEL, _DF, and _SSEL values in the PLL_CTL and PLL_DIV registers.
INT32u GetSCLK(void)
{
INT16u tempPLLCTL,tempPLLDIV;
INT16u _MSEL,_SSEL,_DF,_VCO,_SCLK;
INT16u clkin = CLKIN;

tempPLLCTL = *pPLL_CTL;
tempPLLDIV = *pPLL_DIV;

//get _MSEL, _SSEL, _DF
_MSEL = ((tempPLLCTL & 0x7E00) >> 9);
_SSEL = tempPLLDIV & 0x000f;
_DF   = tempPLLCTL & 0x0001;

if(_DF == 1) clkin = clkin/2;

_VCO  = _MSEL * clkin;
_SCLK = _VCO/_SSEL;  

return  _SCLK * 1000000;
}

void SfInit(void)
{
INT32u _SCLK = GetSCLK();

// calculate divisor constant
giSfSpiBaud = (_SCLK / 2 / SF_MAX_CLOCK) + 1; // max. 20 MHz
///********************************************************************************
*pFIO_DIR = *pFIO_DIR & 0xFFFB | 0x0004;  // set output direction for PF2 SPI select lines
*pFIO_INEN = *pFIO_INEN & 0xFFFB | 0x0000;    // ensable input buffers for PF2 GPIO lines
*pFIO_FLAG_D = *pFIO_FLAG_D &0xFFFB | 0x0004;       // set PF2 output bits to '1' (deselect SPI)
//*********************************************************************************/
*pSPI_FLG = *pSPI_FLG & 0xFBFB | 0x0400;
}

void _SfOpen(void)
{
*pSPI_BAUD = giSfSpiBaud;
// configure spi port:
//   transfer on write, 8-bit data, MSB first,
//   master, CPOL = CPHA = 1 (mode 3)
*pSPI_CTL = TIMOD_TX | MSTR | CPOL | CPHA | SPE;
}

void _SfClose(void)
{
DESELECT();
// disable SPI
*pSPI_CTL = 0;
}

BYTEu _SpiSendRcv(BYTEu data)
{
// while ((*pSPI_STAT & TXS));   // wait for transfer buffer empty
*pSPI_TDBR = data;     // send data

while ((*pSPI_STAT & TXS));   // wait for transfer buffer empty
while (!(*pSPI_STAT & RXS));  // wait for receive buffer full
// while ((*pSPI_STAT & SPIF) == 0); // wait for transfer complete
return *pSPI_RDBR;     // get input
}

// wait while write in progress
void _SfWaitWhileWIP(void)
{
SELECT();
_SpiSendRcv(ST_RDSR);
while (_SpiSendRcv(0) & ST_WIP);
DESELECT();
}


void _SfSendCmd(BYTEu cmd)
{
// _SfWaitWhileWIP();
SELECT();
_SpiSendRcv(cmd);
DESELECT();
}

void _SfSendCmdAddr(BYTEu cmd, INT32u addr)
{
// _SfWaitWhileWIP();
SELECT();
_SpiSendRcv(cmd);
_SpiSendRcv((addr >> 16) & 0xff);
_SpiSendRcv((addr >>  8) & 0xff);
_SpiSendRcv((addr      ) & 0xff);
}


void SfBWriteStart(INT32u addr)
{
_SfOpen();
_SfSendCmd(ST_WREN);
_SfSendCmdAddr(ST_PP, addr);
giSfPage = addr & ~(SF_PAGESIZE - 1);
giSfCtr = SF_PAGESIZE - (addr & (SF_PAGESIZE - 1)); // remaining bytes to the page boundary
}

void SfBWriteEnd(void)
{
DESELECT();
_SfWaitWhileWIP();
_SfClose();
}

void SfBWrite(BYTEu data)
{
if (giSfCtr IS 0) { // reached page boundary: start internal write cycle
  DESELECT();      // release chip select to initiate write cycle
  giSfCtr = SF_PAGESIZE - 1;  // we will send one byte in this cycle already, so start from PAGESIZE - 1!
  giSfPage += SF_PAGESIZE;
  _SfWaitWhileWIP();
  _SfSendCmd(ST_WREN);
  _SfSendCmdAddr(ST_PP, giSfPage); // start new block
} else {
  giSfCtr--;
}
_SpiSendRcv(data);
}


// high level communication
void SfWrite(INT32u addr, BYTEu data)
{
_SfOpen();
_SfSendCmdAddr(ST_PP, addr);
_SpiSendRcv(data);
_SfClose();
}


BYTEu SfRead(INT32u addr)
{
BYTEu data;
_SfOpen();
_SfSendCmdAddr(ST_READ, addr);
data = _SpiSendRcv(0);
_SfClose();
return data;
}

void SfBReadStart(INT32u addr)
{
_SfOpen();
_SfSendCmdAddr(ST_READ, addr);
}

BYTEu SfBRead(void)
{
return _SpiSendRcv(0);
}

void SfBReadEnd(void)
{
_SfClose();
}

void SfEraseSector(INT32u addr)
{
_SfOpen();
_SfSendCmd(ST_WREN);
_SfSendCmdAddr(ST_SE, addr); // sector erase
DESELECT();
_SfWaitWhileWIP();
_SfClose();
}

void SfErase(void)
{
_SfOpen();
_SfSendCmd(ST_WREN);
_SfSendCmd(ST_BE);    // bulk erase
_SfWaitWhileWIP();
_SfClose();
}

BYTEu SfGetSignature(void)
{
BYTEu sig;

_SfOpen();
_SfSendCmdAddr(ST_RES, 0);
_SpiSendRcv(0); // send dummy byte to clock in signature
sig = *pSPI_RDBR;
_SfClose();
return sig;
}

INT16u SfGetManufactionAndDeviceCode(void)
{
INT16u md =0;
_SfOpen();
_SfSendCmdAddr(ST_RMD, 0);
_SpiSendRcv(0); // send dummy byte to clock in signature and give up the first 0x00
//测试结果与文档结果相反,文档中MD在前,DD在后
md =_SpiSendRcv(0);
md |=(_SpiSendRcv(0)<<8)&0xFF00;
_SfClose();
return md;
}

void SfMemWrite(INT32u addr, INT32u count, BYTEu *buf)
{
INT32u ctr = SF_PAGESIZE - (addr & (SF_PAGESIZE - 1)); // remaining bytes to the page boundary
// map DMA5 to SPI
*pDMA5_PERIPHERAL_MAP = 0x5000;
RUNNING = DMA5_WRITE;
while (count) {
  _SfOpen();
  _SfSendCmd(ST_WREN);
  _SfSendCmdAddr(ST_PP, addr);
  // reconfigure spi port for DMA transfer:
  //   DMA transmit, 8-bit data, MSB first, master, CPOL = CPHA = 1 (mode 3)
  *pSPI_CTL = TIMOD_DMA_TX | MSTR | CPOL | CPHA;
  
  // Configure DMA5
  // 8-bit memory read
  *pDMA5_CONFIG = WDSIZE_8;
  // Start address of data buffer
  *pDMA5_START_ADDR = buf;
  // DMA inner loop count
  *pDMA5_X_COUNT = ctr;
  // Inner loop address increment
  *pDMA5_X_MODIFY = 1;
  
  // enable DMA
  *pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN | DI_EN); // interrupt at the end of DMA
  //*pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN); // poll end of DMA
  // enable spi
  SELECT();
  *pSPI_CTL = (*pSPI_CTL | SPE);

  StTxPendSignal();

  // wait until dma transfers for spi are finished
  while ((*pSPI_STAT BITAND TXS) IS 0); // wait for data buffer full
  do {
   while (*pSPI_STAT BITAND TXS); // wait for data buffer empty
  } while (*pSPI_STAT BITAND TXS); // finished if still empty
  
  while ((*pSPI_STAT BITAND SPIF) IS 0); // wait for transfer complete

  // disable DMA
  *pDMA5_CONFIG = 0;
  _SfClose();   // initiate write cycle
  _SfOpen();
  _SfWaitWhileWIP(); // wait while write in progress
  _SfClose();
  
  count -= ctr;
  addr += ctr;
  buf += ctr;
  ctr = (count < SF_PAGESIZE) ? count : SF_PAGESIZE;
}
}

void SfMemRead(INT32u addr, INT32u count, BYTEu *buf)
{
printf(("\n SfMemRead HAPPEN!!!\n"));
RUNNING = DMA5_READ;
// map DMA5 to SPI
*pDMA5_PERIPHERAL_MAP = 0x5000;
_SfOpen();
_SfSendCmdAddr(ST_READ, addr);
// reconfigure spi port for DMA transfer:
//   DMA receive, 8-bit data, MSB first, master, CPOL = CPHA = 1 (mode 3), send zero
*pSPI_CTL = TIMOD_DMA_RX | MSTR | CPOL | CPHA | SZ;

// Configure DMA5
// 8-bit memory write
*pDMA5_CONFIG = WDSIZE_8 | WNR;
// Start address of data buffer
*pDMA5_START_ADDR = buf;
// DMA inner loop count
*pDMA5_X_COUNT = count;
// Inner loop address increment
*pDMA5_X_MODIFY = 1;

// enable DMA
*pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN | DI_EN); // interrupt at the end of DMA
//*pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN); // poll end of DMA
// enable spi
SELECT();
*pSPI_CTL = (*pSPI_CTL | SPE);

StRxPendSignal();

// wait until dma transfers from spi are finished
while (*pDMA5_IRQ_STATUS BITAND DMA_RUN); // wait for DMA done

// disable DMA
*pDMA5_CONFIG = 0;
_SfClose();
}



这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2012/9/27 16:21:37
尊贵身份标志
OpenADSP(管理员)
OpenADSP
头衔:社区公民
帮派:无帮无派
帖数:5187
金钱:34761
积分:6369
注册时间:2011/6/7
1信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线

我是OP...
等级:管理员 参考IP地址:*.*.*.*
2012/9/27 16:57:09
Powered by OpenADSP Copyright © 2010 www.Openadsp.com. All rights reserved.154239 Call, 1 Queries, Processed in 0.031250 second(s),