> Sure! I'm out of town right now, but I'll see what I can do tomorrow when > I get back. I'm doing this on a pic32. What processor are you using? > > Harold > Here's some of my code. This is for logging to an external 2MB SPI flash chip. I hope you can make sense of it. One thing that is unique here is we're using PMP addresses driving an external decoder to generate the chip selects. Good luck! Harold' void LogRead(UINT32 LogRecordNum){ // Read the specified record from external flash and store in LogRecord. void *pVoid; // generic pointer if(SLEEPn=3D=3D0){ // system sleeping, can't access flash since spi = is shut down LogRecord.time=3D(INT64)RtcReadTime(); // show current time LogRecord.source=3DLogSourceInternal; LogRecord.EventCode=3DError; strncpy(LogRecord.text,"No log access during system sleep.",sizeof(LogRecord.text)); }else{ // not sleeping pVoid=3D&LogRecord; // point to log record ReadExtFlashArray(Flash0BaseAddr, LogRecordNum<<6, pVoid, 64); if(LogRecord.time=3D=3D-1) LogRecord.text[0]=3D0; // put null text if unfilled log record requested } } void LogWrite(INT16 source, UINT16 EventCode, UINT8 *pText){ // Write a log record with the current time and advance the NextLogRecord count void *pVoid; // generic pointer #if 1 // disable logging for test if(SLEEPn!=3D0){ // only log if not sleeping. During sleep, spi is shut down, so we can't get to external flash pVoid=3D&LogRecord; // point to log record LogRecord.time=3D(INT64)RtcReadTime(); // get current time and convert to int64 LogRecord.source=3Dsource; // source of this action (local, usb, web, tcp, etc. LogRecord.EventCode=3DEventCode; strncpy(LogRecord.text,pText,sizeof(LogRecord.text)); // copy over text StreamProgramExtFlash(Flash0BaseAddr, NextLogRecord<<6, sizeof(LogRecord),pVoid); NextLogRecord++; if(NextLogRecord>32767) NextLogRecord=3D0; // wrap around if we ran off= end if(EventCode=3D=3DFaderChange) LoggedFader=3DCurrentLevel; // keep tra= ck of this so we know if it's been logged } #endif } void LoggingInit(void){ // set NextLogRecord and log powerup UINT8 buf[8]; UINT8 n; UINT16 n16; //char sbuf[50]=3D"Reset due to "; char sbuf[100]; NextLogRecord=3D0; do{ ReadExtFlashArray(Flash0BaseAddr,(NextLogRecord<<6), buf, 8); // read 8 bytes which would be time if this is not erase n16=3D0; // start with sum of 0 for(n=3D0;n<8;n++){ n16+=3Dbuf[n]; // add up the values we read } if(n16=3D=3D(8*255)) break; // We found unprogrammed flash get out befo= re advancing log record number NextLogRecord++; // point to next record if(NextLogRecord>32767){ // looks like all of memory is written NextLogRecord=3D0; break; // get out with value of 0 } }while(1); sprintf(sbuf,"ErrorEPC=3D0x%lx, EPC=3D0x%lx",_CP0_GET_ERROREPC(), _CP0_GET_EPC()); LogWrite(LogSourceInternal,Reset,sbuf); sprintf(sbuf,"Reset due to "); if(RCONbits.POR) strcat(sbuf,"power on, "); else if(RCONbits.BOR) strcat(sbuf,"brownout, "); if(RCONbits.EXTR) strcat(sbuf,"hardware reset, "); if(RCONbits.SWR) strcat(sbuf,"software reset, "); if(RCONbits.CMR) strcat(sbuf,"config mismatch, "); if(RCONbits.WDTO) strcat(sbuf,"watchdog timeout, "); if(RCONbits.SLEEP) strcat(sbuf,"sleep, "); if(RCONbits.IDLE) strcat(sbuf,"idle, "); RCON=3D0; // clear the reset flags LogWrite(LogSourceInternal,Reset,sbuf); } void ChipSelectHigh(void){ // Force chip select high by setting PMADDR to 0x8000, making sure PMP is on, and delaying at least 100ns. UINT16 n=3D4; PMADDR=3D0x8000; // make suure chip is deselected PMCONbits.ON=3D1; // and PMP is on while(n--); } void WaitForExtFlashReady(UINT16 BaseAddr){ UINT32 LoopCount=3D100000; // increased by 10 times 8/27/10 while(ReadExtFlashStatus(BaseAddr) & 0x01){ // loop here until write completes if(0=3D=3D(LoopCount--)){ Uart1TxPolled('a'); // output lower case a as error indication. break; // get out of while loop } } } void SectorEraseExtFlash(UINT16 BaseAddr, UINT32 addr){ // Erase the sector containing addr. A sector is 256 pages, and a page is 256 bytes. So, a sector is 64kBytes. // We can program a page at a time, but erase a sector at a time. BaseAddr is the decoded address we'll use to select the particular flash chip. // For example, pass in Flash0 (0x5400) to select Flash0. union{ UINT32 u32; UINT8 u8[4]; }LocalAddr; UINT16 n; UINT8 dummy; // a dummy byte to put received spi data in so we do not get a receive overflow ChipSelectHigh(); // make suure chip is deselected WaitForExtFlashReady(BaseAddr); // wait here while write in progress WriteExtFlashStatus(BaseAddr,0b10); // enable write and remove any block protection WaitForExtFlashReady(BaseAddr); // wait here while write in progress LocalAddr.u32=3Daddr; // local copy of address PMADDR=3DBaseAddr; // chip select low SwSpiExchange(0x06); // enable write ChipSelectHigh(); // CS high PMADDR=3DBaseAddr; // CS low SwSpiExchange(0xd8); // sector erase instruction for(n=3D1;n<4;n++){ // send the address (24 bits) big endian SwSpiExchange(LocalAddr.u8[3-n]); // send byte. Byte sent as index 2, 1, 0 or msb to lsb } ChipSelectHigh(); // chip select high } UINT32 StreamProgramExtFlash(UINT16 BaseAddr, UINT32 addr, UINT32 NumBytes, UINT8 *pdata){ // Program a stream of data to external flash. Breaks in to 256 byte pages and 65kByte sectors. Returns the next available address in external flash UINT16 BytesLeftOnPage; while(NumBytes){ if((addr & 0xffff)=3D=3D0){ // we're on a 64k boundary, erase the sec= tor ChipSelectHigh(); // make suure chip is deselected WaitForExtFlashReady(BaseAddr); // wait here while write in progress SectorEraseExtFlash(BaseAddr,addr); WaitForExtFlashReady(BaseAddr); // wait here while write in progress } BytesLeftOnPage=3D256-(UINT16)(addr&0xff); // if(NumBytes>BytesLeftOnPage){ // more than will fit on this pag= e PageProgramExtFlash(BaseAddr,addr,BytesLeftOnPage,pdata); // program the rest of the page addr+=3D(UINT32)BytesLeftOnPage; // increment address to point t= o next one we'll program pdata+=3DBytesLeftOnPage; // move data pointer that many bytes also NumBytes-=3DBytesLeftOnPage; }else{ PageProgramExtFlash(BaseAddr,addr,NumBytes,pdata); addr+=3D(UINT32)NumBytes; // advance the address pdata+=3DNumBytes; // advance data pointer (not really needed, but be constent) NumBytes=3D0; // we just sent the last of the= m } }//end while return(addr); // send back the next available address } void PageProgramExtFlash(UINT16 BaseAddr, UINT32 addr, UINT16 NumBytes, UINT8 *pdata){ // a number of bytes to external flash. Max clock is 75MHz. Clock i= dles low. Input and output data change on negative edges and are captured on positive edges (mode 0,0). // Data exchanges are 8 bits. BaseAddr is the decoded address we'll use to select the particular flash chip. For example, pass in Flash0 (0x5400) to select Flash0. UINT8 dummy; // a dummy byte to put received spi data in so we do not get a receive overflow union{ UINT32 u32; UINT8 u8[4]; }LocalAddr; UINT16 n; ChipSelectHigh(); // make suure chip is deselected WaitForExtFlashReady(BaseAddr); // wait here while write in progress WriteExtFlashStatus(BaseAddr,0b10); // enable write and remove any block protection WaitForExtFlashReady(BaseAddr); // wait here while write in progress LocalAddr.u32=3Daddr; // local copy of address PMADDR=3DBaseAddr; // chip select low SwSpiExchange(0x06); // enable write ChipSelectHigh(); // CS high PMADDR=3DBaseAddr; // CS low SwSpiExchange(0x02); // page program instruction for(n=3D1;n<4;n++){ // send the address (24 bits) big endian SwSpiExchange(LocalAddr.u8[3-n]); // send byte. Byte sent as index 2, 1, 0 or msb to lsb } n=3DNumBytes; while(n--){ // send n bytes SwSpiExchange(*pdata++); // send the data and bump the pointer } ChipSelectHigh(); // chip select high } -- FCC Rules Updated Daily at http://www.hallikainen.com - Advertising opportunities available! -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .