/** * Displays the content of the given buffer on the DBGU. * * \param pucBuffer Pointer to the buffer to dump. * \param dwSize Buffer size in bytes. * \param dwAddress Start address to display */ extern void DBGU_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) { uint32_t i ; uint32_t j ; uint32_t dwLastLineStart ; uint8_t* pucTmp ; for ( i=0 ; i < (dwSize / 16) ; i++ ) { printf( "0x%08X: ", (unsigned int )(dwAddress + ( i * 16) )) ; pucTmp = (uint8_t*)&pucBuffer[i*16] ; for ( j=0 ; j < 4 ; j++ ) { printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ; pucTmp += 4 ; } pucTmp=(uint8_t*)&pucBuffer[i*16] ; for ( j=0 ; j < 16 ; j++ ) { DBGU_PutChar( *pucTmp++ ) ; } printf( "\n\r" ) ; } if ( (dwSize%16) != 0 ) { dwLastLineStart=dwSize - (dwSize%16) ; printf( "0x%08X: ", (unsigned int ) (dwAddress + dwLastLineStart )) ; for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ ) { if ( (j!=dwLastLineStart) && (j%4 == 0) ) { printf( " " ) ; } if ( j < dwSize ) { printf( "%02X", pucBuffer[j] ) ; } else { printf(" ") ; } } printf( " " ) ; for ( j=dwLastLineStart ; j < dwSize ; j++ ) { DBGU_PutChar( pucBuffer[j] ) ; } printf( "\n\r" ) ; } }
//------------------------------------------------------------------------------ /// remove charaters from buffer positions //------------------------------------------------------------------------------ static char * DBGU_RemoveCharFromBuf (char *buffer, char *p, int *colp, int *np, int plen) { char *s; if (*np == 0) { return (p); } if (*(--p) == '\t') { while (*colp > plen) { DBGU_puts (gpEraseSeq); (*colp)--; } for (s=buffer; s<p; ++s) { if (*s == '\t') { DBGU_puts (gpTabSeq+((*colp) & 07)); *colp += 8 - ((*colp) & 07); } else { ++(*colp); DBGU_PutChar (*s); } } } else { DBGU_puts (gpEraseSeq); (*colp)--; } (*np)--; return (p); }
//------------------------------------------------------------------------------ /// Outputs a character to a file. //------------------------------------------------------------------------------ int fputc(int ch, FILE *f) { if ((f == stdout) || (f == stderr)) { DBGU_PutChar(ch); return ch; } else { return EOF; } }
//------------------------------------------------------------------------------ /// Implementation of fputc using the DBGU as the standard output. Required /// for printf(). /// Returns the character written if successful, or -1 if the output stream is /// not stdout or stderr. /// \param c Character to write. /// \param pStream Output stream. //------------------------------------------------------------------------------ signed int fputc(signed int c, FILE *pStream) { if ((pStream == stdout) || (pStream == stderr)) { DBGU_PutChar(c); return c; } else { return EOF; } }
/** * Reads an hexadecimal number * * \param pdwValue Pointer to the uint32_t variable to contain the input value. */ extern uint32_t DBGU_GetHexa32( uint32_t* pdwValue ) { uint8_t ucKey ; uint32_t dw = 0 ; uint32_t dwValue = 0 ; for ( dw=0 ; dw < 8 ; dw++ ) { ucKey = DBGU_GetChar() ; DBGU_PutChar( ucKey ) ; if ( ucKey >= '0' && ucKey <= '9' ) { dwValue = (dwValue * 16) + (ucKey - '0') ; } else { if ( ucKey >= 'A' && ucKey <= 'F' ) { dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ; } else { if ( ucKey >= 'a' && ucKey <= 'f' ) { dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ; } else { printf( "\n\rIt is not a hexa character!\n\r" ) ; return 0 ; } } } } printf("\n\r" ) ; *pdwValue = dwValue ; return 1 ; }
/** * Reads an integer * * \param pdwValue Pointer to the uint32_t variable to contain the input value. */ extern uint32_t DBGU_GetInteger( uint32_t* pdwValue ) { uint8_t ucKey ; uint8_t ucNbNb=0 ; uint32_t dwValue=0 ; while ( 1 ) { ucKey=DBGU_GetChar() ; DBGU_PutChar( ucKey ) ; if ( ucKey >= '0' && ucKey <= '9' ) { dwValue = (dwValue * 10) + (ucKey - '0'); ucNbNb++ ; } else { if ( ucKey == 0x0D || ucKey == ' ' ) { if ( ucNbNb == 0 ) { printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ; return 0 ; } else { printf( "\n\r" ) ; *pdwValue=dwValue ; return 1 ; } } else { printf( "\n\r'%c' not a number!\n\r", ucKey ) ; return 0 ; } } } }
void _ttywrch(int ch) { DBGU_PutChar((unsigned char)ch); }
//------------------------------------------------------------------------------ /// Check console is ready? /// \return 0 not ready, other value means ready and command string length //------------------------------------------------------------------------------ unsigned int DBGU_CommandIsReady() { unsigned char c; static char *p = gpConsoleBuffer; int escflag = 0; char * p_buf = gpConsoleBuffer; static int n = 0; // buffer index int plen = 0; // prompt length static int col=0; // output column cnt unsigned int cmdLen; plen = strlen(GS_SHELL_PROMPT); //right beginning of a new command input if(col == 0) col = plen; Tag_for_CombinedKey: if(DBGU_IsRxReady()) { c = DBGU_GetChar(); // // Special character handling // switch (c) { case '\r': // Enter case '\n': *p = '\0'; cmdLen = p - p_buf; p = gpConsoleBuffer; n = 0; //clear buffer index as 0 col = 0; // this is set for indicate next time input considered as new command gDBGUPromptFlag = 1;//DBGU_puts ("\r\n"); return cmdLen; case '\0': // nul return 0; case 0x03: // ^C - break //p_buf[0] = '\0'; // discard input return 0; case 0x15: // ^U - erase line while (col > plen) { DBGU_puts (gpEraseSeq); --col; } p = p_buf; n = 0; return 0; case 0x17: // ^W - erase word p=DBGU_RemoveCharFromBuf(p_buf, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=DBGU_RemoveCharFromBuf(p_buf, p, &col, &n, plen); } return 0; case 0x08: // ^H - backspace case 0x7F: // DEL - backspace p=DBGU_RemoveCharFromBuf(p_buf, p, &col, &n, plen); return 0; case 0x1b: // arrow, home flag escflag = 1; goto Tag_for_CombinedKey;//in window hyperterminal, arrow and home flag // keys are combined 1b + x case 'D': //ignore arrow,home key case 'C': case 'H': case 'A': case 'B': if(escflag) { escflag = 0; return 0; } default: // // Must be a normal character then // if (n < DBGU_CMDBUFSIZE-2) { if (c == '\t') { // expand TABs DBGU_puts (gpTabSeq+(col&07)); col += 8 - (col&07); } else { ++col; // echo input DBGU_PutChar (c); } *p++ = c; ++n; } else { // Buffer full DBGU_PutChar ('\a'); } } } return 0; }
//------------------------------------------------------------------------------ /// output a string to console /// \param pStr, string to output to DBGU console //------------------------------------------------------------------------------ static inline void DBGU_puts(const char *pStr) { while(*pStr) { DBGU_PutChar(*pStr++); } }
//------------------------------------------------------------------------------ // Global functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Applet main entry. This function decodes received command and executes it. /// \param argc always 1 /// \param argv Address of the argument area. //------------------------------------------------------------------------------ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; unsigned int bufferSize, bufferAddr, memoryOffset; unsigned int eraseStartSector, eraseEndSector, bytesToErase; unsigned int i; const unsigned char busWidth[3] = {FLASH_CHIP_WIDTH_8BITS, FLASH_CHIP_WIDTH_16BITS, FLASH_CHIP_WIDTH_32BITS}; unsigned int comType = 0; TRACE_CONFIGURE_ISP(DBGU_STANDARD, 115200, BOARD_MCK); PIO_Configure(pPinsNf, PIO_LISTSIZE(pPinsNf)); // ---------------------------------------------------------- // INIT: // ---------------------------------------------------------- if (pMailbox->command == APPLET_CMD_INIT) { // Save info of communication link comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) traceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- NorFlash Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); TRACE_INFO("INIT command\n\r"); norFlash.norFlashInfo.baseAddress = BOARD_NORFLASH_ADDR; // Check device CFI and get Vendor setting from it. TRACE_INFO("\t Common Flash Interface detecting...\n\r"); for (i = 0; i < 3; i++) { // Configure SMC for Norflash accesses TRACE_INFO("\t Try bus width %d bits\n\r", busWidth[i] * 8); BOARD_ConfigureNorFlash(busWidth[i] * 8); if (!NorFlash_CFI_Detect(&norFlash, busWidth[i])) break; } if (norFlash.norFlashInfo.cfiCompatible == 0) { pMailbox->status = APPLET_DEV_UNKNOWN; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; TRACE_INFO("Device Unknown\n\r"); goto exit; } else { TRACE_INFO("manufactureID : 0x%08x, deviceID : 0x%08x\n\r", NORFLASH_ReadManufactoryID(&norFlash), NORFLASH_ReadDeviceID(&norFlash)); NORFLASH_ReadManufactoryID(&norFlash); // Get device parameters memSize = NorFlash_GetDeviceSizeInBytes(&(norFlash.norFlashInfo)); pMailbox->argument.outputInit.bufferAddress = ((unsigned int) &end); #if defined (at91sam7se) pMailbox->argument.outputInit.bufferAddress = 0x21000000; #endif bufferSize = NorFlash_GetDeviceMaxBlockSize(&(norFlash.norFlashInfo)); if (bufferSize > MAX_BUFFER_SIZE) bufferSize = MAX_BUFFER_SIZE; pMailbox->argument.outputInit.bufferSize = bufferSize; pMailbox->argument.outputInit.memorySize = memSize; TRACE_INFO("bufferSize : %d memorySize : %d bufferAddr: 0x%x \n\r", pMailbox->argument.outputInit.bufferSize, pMailbox->argument.outputInit.memorySize, (unsigned int) &end); } } // ---------------------------------------------------------- // WRITE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; bufferSize = pMailbox->argument.inputWrite.bufferSize; TRACE_INFO("WRITE at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", memoryOffset, bufferAddr, bufferSize); if (memoryOffset < lastErasedOffset) { lastErasedSector = 0xFFFF; } lastErasedOffset = memoryOffset + bufferSize - 1; eraseStartSector = NorFlash_GetDeviceSectorInRegion(&(norFlash.norFlashInfo), memoryOffset); eraseEndSector = NorFlash_GetDeviceSectorInRegion(&(norFlash.norFlashInfo), lastErasedOffset); do { TRACE_INFO("lastErasedSector %d \n\r", lastErasedSector); if (eraseStartSector > lastErasedSector || lastErasedSector == 0xFFFF) { TRACE_INFO("Sector Erase in sector %d \n\r", eraseStartSector); if (NORFLASH_EraseSector( &norFlash, NorFlash_GetDeviceSectorAddress(&(norFlash.norFlashInfo),eraseStartSector))) { TRACE_INFO("Sector Erase failed in sector %d \n\r", eraseStartSector); pMailbox->status = APPLET_FAIL; goto exit; } lastErasedSector = eraseStartSector; } eraseStartSector++; } while (eraseStartSector <= eraseEndSector); // Write the buffer contents. if (NORFLASH_WriteData(&norFlash, memoryOffset, (unsigned char *)bufferAddr, bufferSize)) { TRACE_INFO("Program failed \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } pMailbox->argument.outputWrite.bytesWritten = bufferSize; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // READ: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; bufferSize = pMailbox->argument.inputRead.bufferSize; TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", memoryOffset, bufferAddr, bufferSize); NORFLASH_ReadData(&norFlash, memoryOffset, (unsigned char *) bufferAddr, bufferSize); pMailbox->argument.outputRead.bytesRead = bufferSize; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // BUFFER ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BUFFER_ERASE) { TRACE_INFO("BUFFER ERASE command\n\r"); memoryOffset = pMailbox->argument.inputBufferErase.memoryOffset; bytesToErase = NorFlash_GetDeviceMaxBlockSize(&(norFlash.norFlashInfo)) * 2; bytesToErase = ((memoryOffset + bytesToErase) > memSize) ? (memSize - memoryOffset): bytesToErase; lastErasedOffset = memoryOffset + bytesToErase; eraseStartSector = NorFlash_GetDeviceSectorInRegion(&(norFlash.norFlashInfo), memoryOffset); eraseEndSector = NorFlash_GetDeviceSectorInRegion(&(norFlash.norFlashInfo), lastErasedOffset); for (i = eraseStartSector; i <= eraseEndSector; i++) { if (NORFLASH_EraseSector( &norFlash, NorFlash_GetDeviceSectorAddress(&(norFlash.norFlashInfo),i))) { TRACE_INFO("Sector Erase failed in sector %d \n\r", i); pMailbox->status = APPLET_FAIL; goto exit; } lastErasedSector = i; } pMailbox->argument.outputBufferErase.bytesErased = bytesToErase; TRACE_INFO("Buffer Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command\n\r"); if (NORFLASH_EraseChip(&norFlash)) { TRACE_INFO("Full Erase failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("Full Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } exit : // Acknowledge the end of command TRACE_INFO("\tEnd of applet (command : %x --- status : %x)\n\r", pMailbox->command, pMailbox->status); // Notify the host application of the end of the command processing pMailbox->command = ~(pMailbox->command); // Send ACK character if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
//------------------------------------------------------------------------------ /// Applet main entry. This function decodes received command and executes it. /// \param argc always 1 /// \param argv Address of the argument area. //------------------------------------------------------------------------------ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; const At45Desc *pDesc = 0; unsigned int bytesToWrite, bytesToRead, bufferAddr, memoryOffset, packetSize; // index on read/write buffer unsigned char *pBuffer; // Temporary buffer used for non page aligned read/write unsigned int tempBufferAddr; // Offset in destination buffer during buffer copy unsigned int bufferOffset; // Configure the DBGU TRACE_CONFIGURE_ISP(DBGU_STANDARD, 115200, BOARD_MCK); // Configure pins (must be done each time because of some old ROM codes that reset PIO usage) if (at45Select[at45Index].pSpiHw != 0) { PIO_Configure(at45Select[at45Index].pPinsSpi, at45Select[at45Index].numPinsSpi); PIO_Configure(at45Select[at45Index].pPinCs, 1); } // ---------------------------------------------------------- // INIT: // ---------------------------------------------------------- if (pMailbox->command == APPLET_CMD_INIT) { // Save info of communication link comType = pMailbox->argument.inputInit.comType; at45Index = pMailbox->argument.inputInit.at45Idx; #if (DYN_TRACES == 1) traceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- DataFlash AT45 Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); if (at45Select[at45Index].pSpiHw == 0) { pMailbox->status = APPLET_NO_DEV; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; pMailbox->argument.outputInit.bufferAddress = (unsigned int) &end; TRACE_INFO("INIT command: No Dataflash %d defined for this board\n\r", \ pMailbox->argument.inputInit.at45Idx); pMailbox->status = APPLET_NO_DEV; goto exit; } TRACE_INFO("INIT command: Dataflash %d : SPI 0x%x SPI_NPCS 0x%x (0x%x)\n\r", \ pMailbox->argument.inputInit.at45Idx, at45Select[at45Index].spiIndex, at45Select[at45Index].cs, (unsigned int) &(pMailbox->argument.inputInit.at45Idx)); // Initialize the SPI and serial flash SPID_Configure(&spid, at45Select[at45Index].pSpiHw, at45Select[at45Index].spiId); PIO_Configure(at45Select[at45Index].pPinsSpi, at45Select[at45Index].numPinsSpi); PIO_Configure(at45Select[at45Index].pPinCs, 1); TRACE_INFO("\tSPI NCSR 0x%x\n\r", (int)AT45_CSR(BOARD_MCK, SPCK)); SPID_ConfigureCS(&spid, at45Select[at45Index].cs, AT45_CSR(BOARD_MCK, SPCK)); AT45_Configure(&at45, &spid, at45Select[at45Index].cs); TRACE_INFO("\tSPI and AT45 drivers initialized\n\r"); pMailbox->argument.outputInit.bufferAddress = (unsigned int) &end; // Read the JEDEC ID of the device to identify it pDesc = AT45_FindDevice(&at45, AT45D_GetStatus(&at45)); if (!pDesc) { pMailbox->status = APPLET_DEV_UNKNOWN; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; TRACE_INFO("\tDevice Unknown\n\r"); goto exit; } // Get device parameters pMailbox->status = APPLET_SUCCESS; numPages = AT45_PageNumber(&at45); pageSize = AT45_PageSize(&at45); #if defined(sram) || defined(at91sam7se) bufferSize = ((unsigned int) &_sstack) - ((unsigned int) &end) // user area - STACK_SIZE // stack size (if same area of applet code) - pageSize; // tempbuffer size to to make not aligned write operations bufferSize -= bufferSize % pageSize; // integer number of pages can be contained in each buffer //Buffer size can't be too big, otherwise COM will be timeout. if ( bufferSize < pageSize) { TRACE_INFO("\t No enought memory to load buffer.\n\r"); goto exit; } #else bufferSize = BUFFER_NB_PAGE * pageSize; #endif // Limit buffer size for tranfsert via COM. if (bufferSize > BUF_MAX_SIZE) { bufferSize = BUF_MAX_SIZE; bufferSize -= bufferSize % pageSize; // integer number of pages can be contained in each buffer } pMailbox->argument.outputInit.bufferSize = bufferSize; pMailbox->argument.outputInit.memorySize = numPages * pageSize; TRACE_INFO("\t%s numPages : 0x%x pageSize : 0x%x bufferAddr : 0x%x\n\r", at45.pDesc->name, numPages, pageSize, pMailbox->argument.outputInit.bufferAddress); } // ---------------------------------------------------------- // WRITE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; bytesToWrite = pMailbox->argument.inputWrite.bufferSize; TRACE_INFO("WRITE at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", memoryOffset, bufferAddr, bytesToWrite); pBuffer = (unsigned char *) bufferAddr; tempBufferAddr = bufferAddr + bufferSize; if ((memoryOffset % pageSize) != 0) { // We are not page aligned, retrieve first page content to update it // Flush temp buffer memset((unsigned int *)tempBufferAddr, 0xFF, pageSize); bufferOffset = (memoryOffset % pageSize); if( (bytesToWrite + bufferOffset) < pageSize) { packetSize = bytesToWrite; } else { packetSize = pageSize - bufferOffset; } memoryOffset -= bufferOffset; // Read page to be updated AT45D_Read(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); // Fill retrieved page with data to be programmed memcpy((unsigned char *)(tempBufferAddr + bufferOffset), pBuffer, packetSize); // Write the page contents AT45D_Write(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); bytesToWrite -= packetSize; pBuffer += packetSize; memoryOffset += pageSize; } // If it remains more than one page to write while (bytesToWrite >= pageSize) { // Write the page contents AT45D_Write(&at45, pBuffer, pageSize, memoryOffset); pBuffer += pageSize; memoryOffset += pageSize; bytesToWrite -= pageSize; } // Write remaining data if (bytesToWrite > 0) { // Read previous content of page AT45D_Read(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); // Fill retrieved block with data to be programmed memcpy((unsigned char *)tempBufferAddr, pBuffer, bytesToWrite); // Write the page contents AT45D_Write(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); // No more bytes to write bytesToWrite = 0; } TRACE_INFO("WRITE return byte written : 0x%x Bytes\n\r", pMailbox->argument.inputWrite.bufferSize - bytesToWrite); pMailbox->argument.outputWrite.bytesWritten = pMailbox->argument.inputWrite.bufferSize - bytesToWrite; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // READ: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; bytesToRead = pMailbox->argument.inputRead.bufferSize; TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", memoryOffset, bufferAddr, bytesToRead); pBuffer = (unsigned char *) bufferAddr; // Read packet after packets while (((unsigned int)pBuffer < (bufferAddr + bufferSize)) && (bytesToRead > 0)) { packetSize = min(PDC_MAX_COUNT, bytesToRead); AT45D_Read(&at45, pBuffer, packetSize, memoryOffset); pBuffer += packetSize; bytesToRead -= packetSize; memoryOffset += packetSize; } TRACE_INFO("READ return byte read : 0x%x Bytes\n\r", pMailbox->argument.inputRead.bufferSize - bytesToRead); pMailbox->argument.outputRead.bytesRead = pMailbox->argument.inputRead.bufferSize - bytesToRead; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command\n\r"); memoryOffset = 0; while (memoryOffset < (pageSize * numPages)) { // Erase the page AT45D_Erase(&at45, memoryOffset); memoryOffset += pageSize; } TRACE_INFO("Full Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // BUFFER ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BUFFER_ERASE) { TRACE_INFO("BUFFER ERASE command\n\r"); memoryOffset = pMailbox->argument.inputBufferErase.memoryOffset; while (memoryOffset < (pMailbox->argument.inputBufferErase.memoryOffset + bufferSize)) { // Erase the page AT45D_Erase(&at45, memoryOffset); memoryOffset += pageSize; } TRACE_INFO("Buffer Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // CONFIGURE IN BINARY MODE (power of two page size): // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BINARY_PAGE) { TRACE_INFO("BINARY PAGE SET command\n\r"); // Configure power-of-2 binary page size. AT45D_BinaryPage(&at45); TRACE_INFO("Binary Page achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } exit : // Acknowledge the end of command TRACE_INFO("\tEnd of applet (command : %x --- status : %x)\n\r", pMailbox->command, pMailbox->status); // Notify the host application of the end of the command processing pMailbox->command = ~(pMailbox->command); // Send ACK character if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
//------------------------------------------------------------------------------ /// Applet main entry. This function decodes received command and executes it. /// \param argc always 1 /// \param argv Address of the argument area. //------------------------------------------------------------------------------ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; unsigned int bufferSize, bufferAddr, memoryOffset; unsigned int bytesToWrite; unsigned int bytesRead = 0; unsigned int nbBadBlocks = 0; unsigned int nbBlocks = 0; // Temporary buffer used for non block aligned read / write unsigned int tempBufferAddr; unsigned short block, page, offset, i; // Index in source buffer during buffer copy unsigned int offsetInSourceBuff; // Index in destination buffer during buffer copy unsigned int offsetInTargetBuff; // Errors returned by SkipNandFlash functions unsigned char error = 0; // Configure the DBGU TRACE_CONFIGURE_ISP(DBGU_STANDARD, 115200, BOARD_MCK); // Configure SMC for Nandflash accesses (done each time applet is launched because of old ROM codes) BOARD_ConfigureNandFlash(nfBusWidth); PIO_Configure(pPinsNf, PIO_LISTSIZE(pPinsNf)); // ---------------------------------------------------------- // INIT: // ---------------------------------------------------------- if (pMailbox->command == APPLET_CMD_INIT) { // Save info of communication link comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) traceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- NandFlash applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("INIT command\n\r"); if (pPinsNf->pio == 0) { pMailbox->status = APPLET_NO_DEV; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; pMailbox->argument.outputInit.bufferAddress = (unsigned int) &end; TRACE_INFO("INIT command: No Nandflash defined for this board\n\r"); } else { memset(&skipBlockNf, 0, sizeof(skipBlockNf)); NandDisableInternalEcc(((struct RawNandFlash *) &skipBlockNf)); if (SkipBlockNandFlash_Initialize(&skipBlockNf, 0, cmdBytesAddr, addrBytesAddr, dataBytesAddr, nfCePin, nfRbPin)) { pMailbox->status = APPLET_DEV_UNKNOWN; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; TRACE_INFO("\tDevice Unknown\n\r"); } else { // Check the data bus width of the NandFlash nfBusWidth = NandFlashModel_GetDataBusWidth((struct NandFlashModel *)&skipBlockNf); // Reconfigure bus width BOARD_ConfigureNandFlash(nfBusWidth); TRACE_INFO("\tNandflash driver initialized\n\r"); #if defined (at91sam3u) pMailbox->argument.outputInit.bufferAddress = 0x60000000; #elif defined (at91sam7se) pMailbox->argument.outputInit.bufferAddress = 0x21000000; #else pMailbox->argument.outputInit.bufferAddress = (unsigned int) &end; #endif // Get device parameters memSize = NandFlashModel_GetDeviceSizeInBytes(&skipBlockNf.ecc.raw.model); blockSize = NandFlashModel_GetBlockSizeInBytes(&skipBlockNf.ecc.raw.model); numBlocks = NandFlashModel_GetDeviceSizeInBlocks(&skipBlockNf.ecc.raw.model); pageSize = NandFlashModel_GetPageDataSize(&skipBlockNf.ecc.raw.model); numPagesPerBlock = NandFlashModel_GetBlockSizeInPages(&skipBlockNf.ecc.raw.model); pMailbox->status = APPLET_SUCCESS; pMailbox->argument.outputInit.bufferSize = blockSize; pMailbox->argument.outputInit.memorySize = memSize; TRACE_INFO("\t pageSize : 0x%x blockSize : 0x%x blockNb : 0x%x bus width : %d\n\r", pageSize, blockSize, numBlocks, nfBusWidth); TRACE_INFO("\t bufferAddr : 0x%x\n\r", (unsigned int) &end); } } } // ---------------------------------------------------------- // WRITE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; tempBufferAddr = bufferAddr + blockSize; bytesToWrite = pMailbox->argument.inputWrite.bufferSize; TRACE_INFO("WRITE arguments : offset 0x%x, buffer at 0x%x, of 0x%x Bytes\n\r", memoryOffset, bufferAddr, bytesToWrite); pMailbox->argument.outputWrite.bytesWritten = 0; // Check word alignment if (memoryOffset % 4) { pMailbox->status = APPLET_ALIGN_ERROR; goto exit; } // Retrieve page and block addresses if (NandFlashModel_TranslateAccess(&(skipBlockNf.ecc.raw.model), memoryOffset, bytesToWrite, &block, &page, &offset)) { pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("WRITE at block 0x%x, page 0x%x, offset in page 0x%x\n\r", block, page, offset); if (page || offset || (bytesToWrite < blockSize)) { // We are not block aligned, retrieve block content to update it memset((unsigned int *)tempBufferAddr, 0xFF, blockSize); error = SkipBlockNandFlash_ReadBlock(&skipBlockNf, block, (unsigned int *)tempBufferAddr); if (error == NandCommon_ERROR_BADBLOCK) { pMailbox->status = APPLET_BAD_BLOCK; goto exit; } if (error) { pMailbox->status = APPLET_FAIL; goto exit; } // Fill retrieved block with data to be programmed offsetInTargetBuff = (page * pageSize) + offset; offsetInSourceBuff = 0; while ((offsetInTargetBuff < blockSize) && (bytesToWrite > 0)) { *(unsigned int *)(tempBufferAddr + offsetInTargetBuff) = *(unsigned int *)(bufferAddr + offsetInSourceBuff); offsetInSourceBuff += 4; offsetInTargetBuff += 4; bytesToWrite -= 4; } } else { // Write a full and aligned block tempBufferAddr = bufferAddr; bytesToWrite = 0; } // Erase target block error = SkipBlockNandFlash_EraseBlock(&skipBlockNf, block, NORMAL_ERASE); if (error == NandCommon_ERROR_BADBLOCK) { pMailbox->status = APPLET_BAD_BLOCK; goto exit; } if (error) { pMailbox->status = APPLET_FAIL; goto exit; } // Write target block error = SkipBlockNandFlash_WriteBlock(&skipBlockNf, block, (unsigned int *)tempBufferAddr); if (error == NandCommon_ERROR_BADBLOCK) { pMailbox->status = APPLET_BAD_BLOCK; goto exit; } if (error) { pMailbox->status = APPLET_FAIL; goto exit; } pMailbox->argument.outputWrite.bytesWritten = pMailbox->argument.inputWrite.bufferSize - bytesToWrite; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // READ: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; tempBufferAddr = bufferAddr + blockSize; bufferSize = pMailbox->argument.inputRead.bufferSize; TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", memoryOffset, bufferAddr, bufferSize); pMailbox->argument.outputRead.bytesRead = 0; // Check word alignment if (memoryOffset % 4) { pMailbox->status = APPLET_ALIGN_ERROR; goto exit; } // Retrieve page and block addresses if (NandFlashModel_TranslateAccess(&(skipBlockNf.ecc.raw.model), memoryOffset, bufferSize, &block, &page, &offset)) { pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("READ at block 0x%x, page 0x%x, offset in page 0x%x\n\r", block, page, offset); if (page || offset) { memset((unsigned int *)tempBufferAddr, 0xFF, blockSize); error = SkipBlockNandFlash_ReadBlock(&skipBlockNf, block, (unsigned int *)tempBufferAddr); if (error == NandCommon_ERROR_BADBLOCK) { pMailbox->status = APPLET_BAD_BLOCK; goto exit; } if (error) { pMailbox->status = APPLET_FAIL; goto exit; } // Fill dest buffer with read data offsetInSourceBuff = (page * pageSize) + offset; offsetInTargetBuff = 0; while ((offsetInSourceBuff < blockSize) && (offsetInTargetBuff < blockSize) && (bytesRead < bufferSize)) { *(unsigned int *)(bufferAddr + offsetInTargetBuff) = *(unsigned int *)(tempBufferAddr + offsetInSourceBuff); offsetInSourceBuff += 4; offsetInTargetBuff += 4; bytesRead += 4; } pMailbox->argument.outputRead.bytesRead = bytesRead; pMailbox->status = APPLET_SUCCESS; } else { memset((unsigned int *)bufferAddr, 0xFF, blockSize); error = SkipBlockNandFlash_ReadBlock(&skipBlockNf, block, (unsigned int *)bufferAddr); if (error == NandCommon_ERROR_BADBLOCK) { pMailbox->status = APPLET_BAD_BLOCK; goto exit; } if (error) { pMailbox->status = APPLET_FAIL; goto exit; } pMailbox->argument.outputRead.bytesRead = bufferSize; pMailbox->status = APPLET_SUCCESS; } } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command\n\r"); TRACE_INFO("\tForce erase flag: 0x%x\n\r", pMailbox->argument.inputFullErase.eraseType); for (i = 0; i < numBlocks; i++) { // Erase the block if (SkipBlockNandFlash_EraseBlock(&skipBlockNf, i, pMailbox->argument.inputFullErase.eraseType)) { TRACE_INFO("Found block #%d BAD, skip it\n\r", i); } } TRACE_INFO("Full Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // BATCH FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BATCH_ERASE) { TRACE_INFO("BATCH ERASE command\n\r"); block = pMailbox->argument.inputBatchErase.batch * (numBlocks / ERASE_BATCH); TRACE_INFO("Erase block from #%d to #%d\n\r", block, block + (numBlocks / ERASE_BATCH)); for (i = block ; i < block + (numBlocks / ERASE_BATCH) ; i++) { // Erase the block if (SkipBlockNandFlash_EraseBlock(&skipBlockNf, i, pMailbox->argument.inputBatchErase.eraseType)) { TRACE_INFO("Found block #%d BAD, skip it\n\r", i); } } if ((pMailbox->argument.inputBatchErase.batch + 1) == ERASE_BATCH) { TRACE_INFO("Full Erase achieved, erase type is %d\n\r", pMailbox->argument.inputBatchErase.eraseType); pMailbox->argument.outputBatchErase.nextBatch = 0; } else { pMailbox->argument.outputBatchErase.nextBatch = pMailbox->argument.inputBatchErase.batch + 1; TRACE_INFO("Batch Erase achieved\n\r"); } pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_ERASE_BLOCKS) { TRACE_INFO("BLOCKS ERASE command\n\r"); memoryOffset = pMailbox->argument.inputBlocksErase.memoryOffsetStart; if ((pMailbox->argument.inputBlocksErase.memoryOffsetEnd > memSize) || (pMailbox->argument.inputBlocksErase.memoryOffsetEnd < memoryOffset) ) { TRACE_INFO("Out of memory space\n\r"); pMailbox->status = APPLET_ERASE_FAIL; goto exit; } nbBlocks = ((pMailbox->argument.inputBlocksErase.memoryOffsetEnd- memoryOffset)/ blockSize) + 1; TRACE_INFO("Erase blocks from %d to %d \n\r", memoryOffset / blockSize, (memoryOffset / blockSize)+ nbBlocks ); // Erase blocks for (i = memoryOffset / blockSize; i < memoryOffset / blockSize + nbBlocks ; i++) { if (SkipBlockNandFlash_EraseBlock(&skipBlockNf, i , NORMAL_ERASE)) { TRACE_INFO("Found block #%d BAD, skip it\n\r", i); } } TRACE_INFO("Blocks Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // LIST BAD BLOCKS: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_LIST_BAD_BLOCKS) { TRACE_INFO("LIST BAD BLOCKS command\n\r"); nbBadBlocks = 0; bufferAddr = (unsigned int) &end; pMailbox->argument.outputListBadBlocks.bufferAddress = bufferAddr; for (i = 0; i < numBlocks; i++) { // Erase the page if (SkipBlockNandFlash_CheckBlock(&skipBlockNf, i) == BADBLOCK) { nbBadBlocks++; *((unsigned int *)bufferAddr) = i; bufferAddr += 4; TRACE_INFO("Found block #%d BAD\n\r", i); } } TRACE_INFO("LIST BAD BLOCKS achieved\n\r"); pMailbox->argument.outputListBadBlocks.nbBadBlocks = nbBadBlocks; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // TAG BLOCK: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_TAG_BLOCK) { TRACE_INFO("TAG BLOCK command\n\r"); bufferAddr = (unsigned int) &end; block = pMailbox->argument.inputTagBlock.blockId; // To tag the block as good, just erase it without bad block check if ((unsigned char)pMailbox->argument.inputTagBlock.tag == 0xFF) { if (SkipBlockNandFlash_EraseBlock(&skipBlockNf, block, SCRUB_ERASE)) { TRACE_INFO("Cannot erase block %d\n\r", block); pMailbox->status = APPLET_FAIL; goto exit; } } else { for (i = 0; i < 2; i++) { // Start by reading the spare memset((unsigned char *)bufferAddr, 0xFF, NandCommon_MAXSPAREECCBYTES); TRACE_INFO("Tag to write : 0x%x\n\r", (unsigned char)pMailbox->argument.inputTagBlock.tag); NandSpareScheme_WriteBadBlockMarker((struct NandSpareScheme *)(NandFlashModel_GetScheme((struct NandFlashModel *)(&skipBlockNf))), (unsigned char *)bufferAddr, ((unsigned char)pMailbox->argument.inputTagBlock.tag)); if (RawNandFlash_WritePage((struct RawNandFlash *)(&skipBlockNf), block, i, 0, (unsigned char *)bufferAddr)) { TRACE_ERROR("Failed to write spare data of page %d of block %d\n\r", i, block); pMailbox->status = APPLET_FAIL; goto exit; } } } TRACE_INFO("TAG BLOCK achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } exit : // Acknowledge the end of command TRACE_INFO("\tEnd of applet (command : %x --- status : %x)\n\r", pMailbox->command, pMailbox->status); // Notify the host application of the end of the command processing pMailbox->command = ~(pMailbox->command); // Send ACK character if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; const At45Desc *pDesc = 0; uint32_t bytesToWrite, bytesToRead, bufferAddr, memoryOffset, packetSize; /* index on read/write buffer */ uint8_t *pBuffer; /* Temporary buffer used for non block aligned read/write */ uint32_t tempBufferAddr; /* Offset in destination buffer during buffer copy */ uint32_t bufferOffset; /* Configure pins */ PIO_Configure(pins, PIO_LISTSIZE(pins)); if (pMailbox->command == APPLET_CMD_INIT) { /* Save communication link type */ comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) dwTraceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- DataFlash AT45 Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); /* Initialize DMA driver instance with polling mode */ DMAD_Initialize( &dmad, 1 ); /* Initialize the SPI and serial flash */ SPID_Configure(&spid, SPI0, ID_SPI0, &dmad); AT45_Configure(&at45, &spid, SPI_CS, 1); TRACE_INFO("SPI and at45 drivers initialized\n\r"); pMailbox->argument.outputInit.bufferAddress = (uint32_t) &_end ; /* Read the JEDEC ID of the device to identify it */ pDesc = AT45_FindDevice(&at45, AT45D_GetStatus(&at45)); if (!pDesc) { pMailbox->status = APPLET_DEV_UNKNOWN; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; TRACE_INFO("Device Unknown\n\r"); goto exit; } else { /* Get device parameters */ pMailbox->status = APPLET_SUCCESS; pageSize = AT45_PageSize(&at45); numPages = AT45_PageNumber(&at45); /* Program page */ bufferSize = BUFFER_NB_PAGE * pageSize; pMailbox->argument.outputInit.bufferSize = bufferSize; pMailbox->argument.outputInit.memorySize = numPages * pageSize; TRACE_INFO("%s numPages : 0x%x bufferAddr : 0x%x\n\r", at45.pDesc->name, (unsigned int)numPages, (unsigned int)pMailbox->argument.outputInit.bufferAddress); } } // ---------------------------------------------------------- // WRITE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; bytesToWrite = pMailbox->argument.inputWrite.bufferSize; TRACE_INFO("WRITE at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", (unsigned int)memoryOffset, (unsigned int)bufferAddr,(unsigned int) bytesToWrite); pBuffer = (unsigned char *) bufferAddr; tempBufferAddr = bufferAddr + bufferSize; if ((memoryOffset % pageSize) != 0) { /* We are not page aligned, retrieve first page content to update it */ memset((unsigned int *)tempBufferAddr, 0xFF, pageSize); bufferOffset = (memoryOffset % pageSize); if( (bytesToWrite + bufferOffset) < pageSize) { packetSize = bytesToWrite; } else { packetSize = pageSize - bufferOffset; } memoryOffset -= bufferOffset; /* Read page to be updated */ AT45D_Read(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); /* Fill retrieved page with data to be programmed */ memcpy((unsigned char *)(tempBufferAddr + bufferOffset), pBuffer, packetSize); /* Write the page contents */ AT45D_Write(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); bytesToWrite -= packetSize; pBuffer += packetSize; memoryOffset += pageSize; } /* If it remains more than one page to write */ while (bytesToWrite >= pageSize) { /* Write the page contents */ AT45D_Write(&at45, pBuffer, pageSize, memoryOffset); pBuffer += pageSize; memoryOffset += pageSize; bytesToWrite -= pageSize; } /* Write remaining data */ if (bytesToWrite > 0) { /* Read previous content of page */ AT45D_Read(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); /* Fill retrieved block with data to be programmed */ memcpy((unsigned char *)tempBufferAddr, pBuffer, bytesToWrite); /* Write the page contents */ AT45D_Write(&at45, (unsigned char *) tempBufferAddr, pageSize, memoryOffset); /* No more bytes to write */ bytesToWrite = 0; } TRACE_INFO("WRITE return byte written : 0x%x Bytes\n\r", (unsigned int)(pMailbox->argument.inputWrite.bufferSize - bytesToWrite)); pMailbox->argument.outputWrite.bytesWritten = pMailbox->argument.inputWrite.bufferSize - bytesToWrite; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // READ: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; bytesToRead = pMailbox->argument.inputRead.bufferSize; TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes\n\r", (unsigned int)memoryOffset, (unsigned int)bufferAddr, (unsigned int)bytesToRead); pBuffer = (unsigned char *) bufferAddr; /* Read packet after packets */ while (((unsigned int)pBuffer < (bufferAddr + bufferSize)) && (bytesToRead > 0)) { packetSize = min(MAX_COUNT, bytesToRead); AT45D_Read(&at45, pBuffer, packetSize, memoryOffset); pBuffer += packetSize; bytesToRead -= packetSize; memoryOffset += packetSize; } TRACE_INFO("READ return byte read : 0x%x Bytes\n\r", (unsigned int)(pMailbox->argument.inputRead.bufferSize - bytesToRead)); pMailbox->argument.outputRead.bytesRead = pMailbox->argument.inputRead.bufferSize - bytesToRead; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command\n\r"); memoryOffset = 0; while (memoryOffset < (pageSize * numPages)) { /* Erase the page */ AT45D_Erase(&at45, memoryOffset); memoryOffset += pageSize; } TRACE_INFO("Full Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // BUFFER ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BUFFER_ERASE) { TRACE_INFO("BUFFER ERASE command\n\r"); memoryOffset = pMailbox->argument.inputBufferErase.memoryOffset; while (memoryOffset < (pMailbox->argument.inputBufferErase.memoryOffset + bufferSize)) { /* Erase the page */ AT45D_Erase(&at45, memoryOffset); memoryOffset += pageSize; } TRACE_INFO("Buffer Erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // CONFIGURE IN BINARY MODE (power of two page size): // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_BINARY_PAGE) { TRACE_INFO("BINARY PAGE SET command\n\r"); /* Configure power-of-2 binary page size. */ AT45D_BinaryPage(&at45); TRACE_INFO("Binary Page achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } exit: /* Acknowledge the end of command */ TRACE_INFO("\tEnd of applet (command : %x --- status : %x)\n\r", (unsigned int)pMailbox->command, (unsigned int)pMailbox->status); /* Notify the host application of the end of the command processing */ pMailbox->command = ~(pMailbox->command); if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
//------------------------------------------------------------------------------ /// Applet main entry. This function decodes received command and executes it. /// \param argc always 1 /// \param argv Address of the argument area. //------------------------------------------------------------------------------ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; unsigned int bytesToWrite, bufferAddr, memoryOffset; unsigned int l_start; unsigned int l_end; unsigned int *pActualStart = NULL; unsigned int *pActualEnd = NULL; unsigned char error; TRACE_CONFIGURE_ISP(DBGU_STANDARD, 115200, BOARD_MCK); // ---------------------------------------------------------- // INIT: // ---------------------------------------------------------- if (pMailbox->command == APPLET_CMD_INIT) { // Save info of communication link comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) traceLevel = pMailbox->argument.inputInit.traceLevel; #endif switch (pMailbox->argument.inputInit.bank) { default: case 0: flashBaseAddr = AT91C_IFLASH; flashBaseAddrInit = AT91C_IFLASH; #if defined (at91sam3u4) flashSize = AT91C_IFLASH_SIZE + AT91C_IFLASH1_SIZE; #else flashSize = AT91C_IFLASH_SIZE; #endif flashPageSize = AT91C_IFLASH_PAGE_SIZE; pMailbox->argument.outputInit.memoryInfo.numbersLockBits = AT91C_IFLASH_NB_OF_LOCK_BITS; flashLockRegionSize = AT91C_IFLASH_LOCK_REGION_SIZE; break; #if defined (at91sam3u4) case 1: flashBaseAddr = AT91C_IFLASH1; flashBaseAddrInit = AT91C_IFLASH1; flashSize = AT91C_IFLASH1_SIZE; flashPageSize = AT91C_IFLASH1_PAGE_SIZE; pMailbox->argument.outputInit.memoryInfo.numbersLockBits = AT91C_IFLASH1_NB_OF_LOCK_BITS; flashLockRegionSize = AT91C_IFLASH1_LOCK_REGION_SIZE; break; #endif } TRACE_INFO("-- Internal Flash Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); // Initialize flash driver FLASHD_Initialize(BOARD_MCK); // flash accesses must be 4 bytes aligned pMailbox->argument.outputInit.bufferAddress = ((unsigned int) &end); #if defined (at91sam7s161) || defined (at91sam3u1) bufferSize = flashPageSize * 2; #elif defined (at91sam7s32) || defined (at91sam7s321) || defined (at91sam7l) bufferSize = flashPageSize; #else bufferSize = AT91C_ISRAM_SIZE // sram size - ( ((unsigned int) &end) - AT91C_ISRAM ) // program size (romcode, code+data) - STACK_SIZE; // stack size at the end #endif // integer number of pages can be contained in each buffer // operation is : buffersize -= bufferSize % flashPageSize // modulo can be done with a mask since flashpagesize is a power of two integer bufferSize -= (bufferSize & (flashPageSize - 1)); if (bufferSize > MAX_BUF_SIZE && (comType == DBGU_COM_TYPE)) bufferSize = MAX_BUF_SIZE; pMailbox->argument.outputInit.bufferSize = bufferSize; pMailbox->argument.outputInit.memorySize = flashSize; pMailbox->argument.outputInit.memoryInfo.lockRegionSize = flashLockRegionSize; TRACE_INFO("bufferSize : %d bufferAddr: 0x%x \n\r", pMailbox->argument.outputInit.bufferSize, (unsigned int) &end ); TRACE_INFO("memorySize : %d lockRegionSize : 0x%x numbersLockBits : 0x%x \n\r", pMailbox->argument.outputInit.memorySize, pMailbox->argument.outputInit.memoryInfo.lockRegionSize, pMailbox->argument.outputInit.memoryInfo.numbersLockBits); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // WRITE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; bytesToWrite = pMailbox->argument.inputWrite.bufferSize; #if defined (at91sam3u4) if (flashBaseAddrInit == AT91C_IFLASH) { if ((memoryOffset < AT91C_IFLASH_SIZE) && ((memoryOffset + bytesToWrite) > AT91C_IFLASH_SIZE)) { flashBaseAddr = AT91C_IFLASH; bytesToWrite = AT91C_IFLASH_SIZE - memoryOffset; } else if (memoryOffset >= AT91C_IFLASH_SIZE) { flashBaseAddr = AT91C_IFLASH1; memoryOffset -= AT91C_IFLASH_SIZE; } } #endif TRACE_INFO("WRITE at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes (flash base addr : 0x%x)\n\r", memoryOffset, bufferAddr, bytesToWrite, flashBaseAddr); // Check the giving sector have been locked before. if (FLASHD_IsLocked(flashBaseAddr + memoryOffset, flashBaseAddr + memoryOffset + bytesToWrite) != 0) { TRACE_INFO("Error page locked\n\r"); pMailbox->argument.outputWrite.bytesWritten = 0; pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } // Write data if (FLASHD_Write(flashBaseAddr + memoryOffset, (const void *)bufferAddr, bytesToWrite) != 0) { TRACE_INFO("Error write operation\n\r"); pMailbox->argument.outputWrite.bytesWritten = 0; pMailbox->status = APPLET_WRITE_FAIL; goto exit; } TRACE_INFO("Write achieved\n\r"); pMailbox->argument.outputWrite.bytesWritten = bytesToWrite; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // READ: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; bufferSize = pMailbox->argument.inputRead.bufferSize; #if defined (at91sam3u4) if (flashBaseAddrInit == AT91C_IFLASH) { flashBaseAddr = AT91C_IFLASH; if ((memoryOffset < AT91C_IFLASH_SIZE) && ((memoryOffset + bufferSize) > AT91C_IFLASH_SIZE)) { bufferSize = AT91C_IFLASH_SIZE - memoryOffset; } else if (memoryOffset >= AT91C_IFLASH_SIZE) { flashBaseAddr = AT91C_IFLASH1; memoryOffset -= AT91C_IFLASH_SIZE; } } #endif TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes (flash base addr : 0x%x)\n\r", memoryOffset, bufferAddr, bufferSize, flashBaseAddr); // read data memcpy((void *)bufferAddr, (void *)(flashBaseAddr + memoryOffset), bufferSize); TRACE_INFO("Read achieved\n\r"); pMailbox->argument.outputRead.bytesRead = bufferSize; pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // FULL ERASE: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command \n\r"); #if defined (at91sam3u4) if (flashBaseAddrInit == AT91C_IFLASH) { flashBaseAddr = AT91C_IFLASH; // Check if at least one page has been locked if (FLASHD_IsLocked(flashBaseAddr, flashBaseAddr + AT91C_IFLASH_SIZE - 1) != 0) { TRACE_INFO("Error page locked \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } } else { // Check if at least one page has been locked if (FLASHD_IsLocked(flashBaseAddr, flashBaseAddr + AT91C_IFLASH1_SIZE - 1) != 0) { TRACE_INFO("Error page locked \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } } #else // Check if at least one page has been locked if (FLASHD_IsLocked(flashBaseAddr, flashBaseAddr + flashSize) != 0) { TRACE_INFO("Error page locked \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } #endif // Implement the erase all command if (FLASHD_Erase(flashBaseAddr) != 0) { TRACE_INFO("Full erase failed! \n\r"); pMailbox->status = APPLET_ERASE_FAIL; goto exit; } #if defined (at91sam7xc512) || (at91sam7x512) if (FLASHD_Erase(flashBaseAddr + FLASH_SECOND_BANK_OFFSET) != 0) { TRACE_INFO("Full erase failed! \n\r"); pMailbox->status = APPLET_ERASE_FAIL; goto exit; } #endif TRACE_INFO("Full erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // LOCK SECTOR: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_LOCK) { TRACE_INFO("LOCK command \n\r"); #if defined (at91sam3u4) if (flashBaseAddrInit == AT91C_IFLASH) { flashBaseAddr = AT91C_IFLASH; if (pMailbox->argument.inputLock.sector >= AT91C_IFLASH_NB_OF_LOCK_BITS) { flashBaseAddr = AT91C_IFLASH1; pMailbox->argument.inputLock.sector -= AT91C_IFLASH_NB_OF_LOCK_BITS; } } #endif l_start = (pMailbox->argument.inputLock.sector * flashLockRegionSize) + flashBaseAddr; l_end = l_start + flashLockRegionSize; if( FLASHD_Lock(l_start, l_end, pActualStart, pActualEnd) != 0) { TRACE_INFO("Lock failed! \n\r"); // ASSERT( *pActualStart == l_start, "-F- Lock failed! \n\r"); // ASSERT( *pActualEnd == (l_start + flashLockRegionSize), "-F- Lock failed! \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } TRACE_INFO("Lock sector achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // UNLOCK SECTOR: // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_UNLOCK) { TRACE_INFO("UNLOCK command \n\r"); #if defined (at91sam3u4) if (flashBaseAddrInit == AT91C_IFLASH) { flashBaseAddr = AT91C_IFLASH; if (pMailbox->argument.inputLock.sector >= AT91C_IFLASH_NB_OF_LOCK_BITS) { flashBaseAddr = AT91C_IFLASH1; pMailbox->argument.inputLock.sector -= AT91C_IFLASH_NB_OF_LOCK_BITS; } } #endif l_start = (pMailbox->argument.inputLock.sector * flashLockRegionSize) + flashBaseAddr; l_end = l_start + flashLockRegionSize; if( FLASHD_Unlock(l_start, l_end, pActualStart, pActualEnd) != 0) { TRACE_INFO("Unlock failed! \n\r"); //ASSERT( *pActualStart == l_start, "-F- Unlock failed! \n\r"); //ASSERT( *pActualEnd == (l_start + flashLockRegionSize), "-F- Unock failed! \n\r"); pMailbox->status = APPLET_UNPROTECT_FAIL; goto exit; } TRACE_INFO("Unlock sector achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } // ---------------------------------------------------------- // GPNVM : // ---------------------------------------------------------- #if !defined (at91sam7a3) else if (pMailbox->command == APPLET_CMD_GPNVM) { if( pMailbox->argument.inputGPNVM.action == 0) { TRACE_INFO("DEACTIVATES GPNVM command \n\r"); error = FLASHD_ClearGPNVM(pMailbox->argument.inputGPNVM.bitsOfNVM); } else { TRACE_INFO("ACTIVATES GPNVM command \n\r"); error = FLASHD_SetGPNVM(pMailbox->argument.inputGPNVM.bitsOfNVM); } if(error != 0) { TRACE_INFO("GPNVM failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("GPNVM achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } #endif // #if !defined (at91sam7a3) // ---------------------------------------------------------- // SET SECURITY : // ---------------------------------------------------------- #if defined(CHIP_FLASH_EFC) && !defined (at91sam7a3) else if (pMailbox->command == APPLET_CMD_SECURITY) { TRACE_INFO("SET SECURITY BIT command \n\r"); if (FLASHD_SetSecurityBit() != 0) { TRACE_INFO("SET SECURITY BIT failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("SET SECURITY BIT achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } #endif #if defined(at91sam3u4) // ---------------------------------------------------------- // READ UNIQUE ID : // ---------------------------------------------------------- else if (pMailbox->command == APPLET_CMD_READ_UNIQUE_ID) { TRACE_INFO("READ UNIQUE ID command \n\r"); if (FLASHD_ReadUniqueID (pMailbox->argument.inputReadUniqueID.bufferAddr) != 0) { TRACE_INFO("Read Unique ID failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("Read Unique ID achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } #endif exit: // Acknowledge the end of command TRACE_INFO("\tEnd of Applet %x %x.\n\r", pMailbox->command, pMailbox->status); // Notify the host application of the end of the command processing pMailbox->command = ~(pMailbox->command); // Send ACK character if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
//------------------------------------------------------------------------------ /// Applet code for initializing the external RAM. //------------------------------------------------------------------------------ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; unsigned int ramType = 0; unsigned int dataBusWidth = 0; unsigned int ddrModel = 0; unsigned int baseAddress = 0; unsigned int *ramAddr = (unsigned int *) EXTRAM_ADDR; unsigned int comType = 0; TRACE_CONFIGURE_ISP(DBGU_STANDARD, 115200, BOARD_MCK); // ---------------------------------------------------------- // INIT: // ---------------------------------------------------------- if (pMailbox->command == APPLET_CMD_INIT) { // Save info of communication link comType = pMailbox->argument.inputInit.comType; #if (TRACE_LEVEL==0) && (DYN_TRACES==0) if (comType == DBGU_COM_TYPE){ // Function TRACE_CONFIGURE_ISP wiil be bypass due to the 0 TRACE_LEVEL. We shall reconfigure the baut rate. DBGU_Configure(DBGU_STANDARD, 115200, BOARD_MCK); } #endif // Enable User Reset AT91C_BASE_RSTC->RSTC_RMR |= AT91C_RSTC_URSTEN | (0xA5<<24); ramType = pMailbox->argument.inputInit.ramType; dataBusWidth = pMailbox->argument.inputInit.dataBusWidth; ddrModel = pMailbox->argument.inputInit.ddrModel; baseAddress = pMailbox->argument.inputInit.baseAddress; #if (DYN_TRACES == 1) traceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- EXTRAM Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); TRACE_INFO("INIT command:\n\r"); TRACE_INFO("\tCommunication link type : %d\n\r", pMailbox->argument.inputInit.comType); TRACE_INFO("\tData bus width : %d bits\n\r", dataBusWidth); if (ramType == TYPE_SDRAM) { TRACE_INFO("\tExternal RAM type : %s\n\r", "SDRAM"); } else { if (ramType == TYPE_DDRAM) { TRACE_INFO("\tExternal RAM type : %s\n\r", "DDRAM"); } else { TRACE_INFO("\tExternal RAM type : %s\n\r", "PSRAM"); } } #if defined(at91cap7) || defined(at91cap9) || defined(at91sam9m10) || defined(at91sam9g45) TRACE_INFO("\tInit EBI Vdd : %s\n\r", (pMailbox->argument.inputInit.VddMemSel)?"3.3V":"1.8V"); BOARD_ConfigureVddMemSel(pMailbox->argument.inputInit.VddMemSel); #endif //defined(at91cap9) if (pMailbox->argument.inputInit.ramType == TYPE_SDRAM) { // Configure SDRAM controller TRACE_INFO("\tInit SDRAM...\n\r"); #if defined(PINS_SDRAM) BOARD_ConfigureSdram(dataBusWidth); #endif } else if (pMailbox->argument.inputInit.ramType == TYPE_PSRAM) { TRACE_INFO("\tInit PSRAM...\n\r"); #if defined(at91sam3u) BOARD_ConfigurePsram(); #endif } else { // Configure DDRAM controller #if defined(at91sam9m10) || defined(at91sam9g45) TRACE_INFO("\tInit DDRAM ... (model : %d)\n\r", ddrModel); BOARD_ConfigureDdram(baseAddress, ddrModel, dataBusWidth); if (baseAddress != (unsigned int)AT91C_BASE_DDR2C) { ramAddr = (unsigned int *)EXTRAM_ADDR_2; } #elif defined(at91cap9dk) TRACE_INFO("\tInit DDRAM ... (model : %d)\n\r", ddrModel); BOARD_ConfigureDdram(ddrModel, dataBusWidth); #endif } // Test external RAM access if (ExtRAM_TestOk(ramAddr)) { pMailbox->status = APPLET_SUCCESS; } else { pMailbox->status = APPLET_FAIL; } pMailbox->argument.outputInit.bufferAddress = ((unsigned int) &end); pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = EXTRAM_SIZE; TRACE_INFO("\tInit successful.\n\r"); } // Acknowledge the end of command TRACE_INFO("\tEnd of applet (command : %x --- status : %x)\n\r", pMailbox->command, pMailbox->status); // Notify the host application of the end of the command processing pMailbox->command = ~(pMailbox->command); // Send ACK character if (comType == DBGU_COM_TYPE) { DBGU_PutChar(0x6); } return 0; }
/** * \brief Outputs a character on the DBGU. * * \param c Character to output. * * \return The character that was output. */ extern WEAK signed int putchar( signed int c ) { DBGU_PutChar( c ) ; return c ; }