/****************************************************************************** * Copyright (c) 2002 University of Florida * Department of Electrical and Computer Engineering * Gainesville, FL, USA 32611 * * Applied Digital Design Laboratory * Benton Hall Room 313 * * Authors: Scott Morrison, morrisos@ufl.edu * Jeremy Parks, jeremyp@ufl.edu * * Advisor: Dr. Karl Gugel, gugel@ecel.ufl.edu * *****************************************************************************/ /****************************************************************************** * File Name: DSlave.c * * Description: Console program to interface the C33 PCI Development card. * * Revision: Ver. 4.0, Jan. 24, 2001 *****************************************************************************/ #include #include #include #include "DSlave.h" #include // for elapsed time operations #include // for exponent, ceiling functions /****************************************************************************** * Function: main * * The primary entry point for DSlave.h. Includes the menu with all functions. *****************************************************************************/ void main() { int RUN_PROGRAM = TRUE; // 1 = stay in menu loop int MenuSelection; // users selection U32 Location; // address of memory or register U32 Data32; int NumWords; // number of 32-bit words U32 i; // for testing double doubleResult; // for math calculations (fp values) U32 badMem[4*DPRAM_USER_SIZE]; U32 j; char format, c; char filename[MAX_LEN]; // filename to load DSP code FILE *bFile; IopSpace = IopSpace0; // set up IO Space for PLX 9030 chip MessageLevel = LEVEL1; // controls the verboseness of the output messages to console /************************************ * Welcome and Setup ************************************/ printf("\t University of Florida Applied Digital Design Laboratory\n"); printf("\t TI C33 DSP PCI Board Console Application\n\n"); // select the first available PLX Device DeviceSelected = SelectDevice(&Device); if (DeviceSelected == -1) exit(0); rc = PlxPciDeviceOpen(&Device, &hDevice); if (rc != ApiSuccess) { printf("\n*ERROR* Unable to find or select a PLX device\n"); _Pause; exit(-1); } printf("\nInitializing PLX Board...\nSelected: %.4x %.4x [bus %.2x slot %.2x]\n", Device.DeviceId, Device.VendorId, Device.BusNumber, Device.SlotNumber); // reset PLX board and configure registers/user pins (also resets DSP) resetPLXBoard(); /************************************ * Main Menu ************************************/ do { // set default menu selection to error (then overwrite with valid selection) MenuSelection = MENU_ERROR; // prompt to continue printf("\n\n** Press any key to continue. **"); getch(""); // capture any key system("CLS"); // clear screen before printing menu // Print menu printf("C33 CONSOLE MAIN MENU\n"); printf("\n****PLX/PCI Options********************************************\n"); printf(" 0) Reset PLX board\t\t"); printf(" 3) Read PCI config reg\n"); printf(" 1) Read PLX local config reg\t"); printf(" 4) Write to PCI config reg\n"); printf(" 2) Write to PLX local config reg\n"); printf("\n****C33 DSP Options********************************************\n"); printf(" 5) Reset DSP board\t\t"); printf(" 10) Download DSP Code\n"); printf(" 6) Read DSP config reg\t\t"); printf(" 11) Execute DSP Code\n"); printf(" 7) Write to DSP config reg\t"); printf(" 12) *** BLANK ***\n"); printf(" 8) Read DSP memory\t\t"); printf(" 13) Download new DSP OS\n"); printf(" 9) Write to DSP memory\n"); printf("\n****Other Options**********************************************\n"); printf("20) Read DPRAM Memory\t\t"); printf(" 23) Search DSP memory\n"); printf("21) Write to DPRAM Memory\t"); printf(" 97) Change Console Message Level\n"); printf("22) Perform DPRAM Memory Test\t"); printf(" 99) Exit program\n"); printf("\n\nSelection: "); fflush(stdin); // flush the input buffer to prevent errors scanf("%d", &MenuSelection); // read the users selection printf("\n"); system("CLS"); // clear screen before performing function // call the appropriate function switch (MenuSelection) { case 0: // reset PLX board and DSP resetPLXBoard(); break; case 1: // read PLX local config register printf("** Read PLX Local Configuration Register **\n\n"); // ask user for register address printf("Enter register number (hex): "); scanf("%x", &Location); ReturnCode = readLocalReg(Location); if (ReturnCode == RETURN_ERROR) printf("*ERROR* Cannot read local config reg %x.\n",Location); break; case 2: // write to PLX local config reg printf("** Write to PLX Local Configuration Register **\n\n"); printf("Enter register number (hex): "); scanf("%x", &Location); printf("\nEnter 32-bit data: "); scanf("%x", &Data32); ReturnCode = writeLocalReg(Location,Data32); if (ReturnCode == RETURN_ERROR) printf("*ERROR* Cannot write to local config reg %x.\n",Location); break; case 3: // read pci config register printf("** Read PCI Configuration Register **\n\n"); printf("Enter register number (hex): "); scanf("%x", &Location); ReturnCode = readPCIReg(Location); if (ReturnCode == RETURN_ERROR) printf("*ERROR* Cannot read pci reg %x.\n",Location); break; case 4: // write to pci config reg printf("** Write to PCI Configuration Register **\n\n"); printf("Enter register number (hex): "); scanf("%x", &Location); printf("\nEnter 32-bit data: "); scanf("%x", &Data32); ReturnCode = writePCIReg(Location,Data32); if (ReturnCode == RETURN_ERROR) printf("*ERROR* Cannot write to pci reg %x.\n",Location); break; case 5: // reset DSP Board printf("** Reset the DSP **\n\n"); printf("\nReseting DSP and checking for confirmation..."); ReturnCode = resetDSP(DSP_OS_FILE); // reset the DSP with default OS if (ReturnCode != RETURN_SUCCESS) printf("\n*ERROR* DSP Reset failed.\n"); else printf("\nThe DSP was reset successfully."); break; case 6: // read from DSP register printf("** Read DSP Register **\n\n"); printf("Enter register offset (hex): "); scanf("%x", &Location); if( readDSPMem((DSP_REG_BASE+Location), 1) != RETURN_SUCCESS) { printf("\n*ERROR* readDSPMem failed for Address: %08x, NumWords: %x.",Location,NumWords); break; // exit this case statement, do not attempt to print results to screen. } printf("\nDSP Register Offset %x at address %08x contains value %08x.\n",Location,DSP_REG_BASE+Location,BufferRead[1]); // clear read buffer after use clearReadBuffer(); break; case 7: // write to DSP register printf("** Write to DSP Register **\n\n"); printf("Enter DSP register offset (hex): "); scanf("%x", &Location); printf("\nEnter 32-bit data: "); scanf("%x", &Data32); printf("\n"); ReturnCode = writeDSPMem((DSP_REG_BASE+Location), 1, &Data32); // NumWords=1 break; case 8: // read from DSP memory, display results to screen with option to save to file printf("** Read DSP Memory **\n\n"); printf("Enter start address (0x0-0x00FFFFFF): "); scanf("%x", &Location); printf("Enter number of words (hex): "); scanf("%x", &NumWords); while(TRUE) { printf("\nView format - (h)ex, (d)ecimal, or (f)loat: "); format=getch(); putch(format); printf("\n"); if ((format=='h' || format=='d' || format=='f')) break; else printf("*ERROR* You entered \"%c\", which is invalid. Please select again.\n",format); } // read from DSP if (readDSPMem(Location, NumWords) != RETURN_SUCCESS) { printf("\n*ERROR* readDSPMem failed for Address: %08x, NumWords: %x.",Location,NumWords); break; // exit this case statement, do not attempt to print results to screen. } // read was successful, now print results printf("\nResults for DSP Read...\n"); for(i=0; i DPRAM_USER_SIZE) { printf("*ERROR* Invalid number of words.\n"); break; } if (NumWords == 1) { printf("Enter 32-bit data: "); scanf("%x", &Data32); printf("\n"); ReturnCode = writeDPRAMMem(Location,NumWords,&Data32); break; } ReturnCode = writeDPRAMMem(Location,NumWords,BufferWrite); break; case 22: // PC to DPRAM memory test j=0; printf("** DPRAM Memory Test **\n\n"); printf("Performing DPRAM Memory Test...\n"); Location = 0; NumWords = 1; // clear write buffer and write to dpram for(i = 0x0; i < DPRAM_USER_SIZE; i++) { BufferWrite[i] = 0x0; // fill with 0 } // perform the write rc = PlxBusIopWrite( hDevice, IopSpace, 0, FALSE, // No Re-map BufferWrite, (4 * DPRAM_USER_SIZE), // total bytes to write BitSize32 ); while (TRUE) { Data32 = Location + 0xFF000000; // perform the write rc = PlxBusIopWrite( hDevice, IopSpace, Location <<2, FALSE, // No Re-map &Data32, (4 * NumWords), // total bytes to write BitSize32 ); printf("Address: %04x ", Location); if(rc != ApiSuccess) { printf("\nWrite failed.\n"); break; } rc = PlxBusIopRead( hDevice, IopSpace, 0, FALSE, // No Re-map &BufferRead, (4*DPRAM_USER_SIZE), // 4 is no. of bytes in word BitSize32 ); if(rc != ApiSuccess) { printf("\nRead failed.\n"); break; } printf("Data: %08x\r", BufferRead[Location]); for(i = 0x0; i < DPRAM_USER_SIZE; i++) { //printf("Location:%x Data:%d\r",i,BufferRead[i]); if (i!=Location && BufferRead[i]!=0x0) // fill with 0 { badMem[j++]=i; badMem[j++]=BufferRead[i]; //printf("\nERROR - Non-zero data found at %x.\n",i); } } // clear data before moving on Data32 = 0x00000000; // perform the write rc = PlxBusIopWrite( hDevice, IopSpace, Location <<2, FALSE, // No Re-map &Data32, (4 * NumWords), // total bytes to write BitSize32 ); Location++; if (Location == DPRAM_USER_SIZE) break; } if(badMem[1]==0) // check for success { printf("\nMemory test successfully completed.\n"); break; } // print first 20 errors for(j=0;j<40;j++) printf("\nLocation: %x Data: %x",badMem[j++],badMem[j]); break; case 23: // Search DSP Memory for Value printf("** Search DSP Memory for Value **\n\n"); printf("Enter start address (0x000-0x00FFFFFF) for search: "); scanf("%x", &Location); printf("Enter number of 32-bit words (0x000-0xFFF) to search: "); scanf("%x", &NumWords); printf("\nEnter 32-bit search value (hex): "); scanf("%x", &Data32); // read from DSP if (readDSPMem(Location, NumWords) != RETURN_SUCCESS) { printf("\n*ERROR* readDSPMem failed for Address: %08x, NumWords: %x.",Location,NumWords); break; // exit this case statement, do not attempt to search results } // search for the value printf("\nThe search produced the following results:\n"); for(i=0; i < NumWords; i++, Location++) { if(BufferRead[i]==Data32) printf("Address: %08x Data: %08x\n", Location, BufferRead[i]); } printf("\nSearch completed.\n"); clearReadBuffer(); // clear Read Buffer before returning break; case 24: // *** BLANK *** break; case 96: // write to Mailbox in infinite loop while (TRUE) { Data32 = 0xAAAAAAAA; // perform the write rc = PlxBusIopWrite( hDevice, IopSpace, 0xFFF <<2, FALSE, // No Re-map &Data32, (4 * NumWords), // total bytes to write BitSize32 ); } break; case 97: // change the console message output level printf("Change Console Message Output Level."); printf("\n\nThe current Message Level is %d.",MessageLevel); while(TRUE) { printf("\n\nPlease select a new message level:"); printf("\n 1 = Few Messages"); printf("\n 2 = More Messages"); printf("\n 3 = Lots of Messages"); printf("\n\nNew Message Level: "); scanf("%d", &MessageLevel); if (MessageLevel != LEVEL1 & MessageLevel != LEVEL2 & MessageLevel != LEVEL3) { printf("\nYour selection \"%d\" is invalid. Please choose again.",MessageLevel); } else break; } printf("\nSelection accepted. The new Message Level is %d",MessageLevel); break; case 99: // quit printf("Exit program...\n"); RUN_PROGRAM = FALSE; break; case MENU_ERROR: // User typed a non-number key printf("\n*ERROR* Selection must be a menu number.\n",MenuSelection); break; default: // invalid selection printf("\n*ERROR* Selection %d is not valid.\n",MenuSelection); break; } // end switch statement } while (RUN_PROGRAM); // Close the PLX9030 Device before exiting rc = PlxPciDeviceClose(hDevice); if (rc != ApiSuccess) { printf("\n*ERROR* Unable to release the PLX9030 Device. PlxPciDeviceClose failed."); printf("\n\n** Press any key to continue. **"); getch(""); // capture any key } } // end main function /************************************ * Function: resetPLXBoard ************************************/ int resetPLXBoard() { PlxPciBoardReset(hDevice); printf("\nInitializing PLX user pins..."); // setup user pin (GPIO8) for DSP reset to be inactive // first, set direction of GPIO8 // bit 26 => 1 to output a high on GPIO8 // bit 25 => 1 to set GPIO8 direction for output // bit 13 => 0 GPIO4 should be input (XF0 from DSP) ** int_L from CPLD ** // bit 12 => 0 enable GPIO4 // bit 5:3 formerly [110] to configure GPIO1 as output set to high ReturnCode = writeLocalReg(LOCAL_GPIOC,0x06248030); // change to 06248000 if (ReturnCode != RETURN_SUCCESS) printf("\n*ERROR* Unable to configure GPIO8 for RESET=High\n"); // The following registers were changed from the default values in the PLX serial eeprom: // CS0BASE: 0x00000000 // turn off CS0, formerly used by PLX board DPRAM // CS1BASE: 0x00002001 // DPRAM size = 4k, start @ 0x0000 (0x0000-3FFF, 16k effective) // LAS0BRD: 0x50A15881 // 32-bit bus, wait states, burst enable // LAS0RR : 0x0FFFC000 // decode w/ PCI A(31..14), use PCI memory space // PCIBAR2: 0xE6410000 // mapped LAS0 at PCI address // LAS0BA : 0x00000001 // enabled decoding of PCI address to target printf("\nPLX chip reset successfully."); // load OS and reset DSP ReturnCode = loadOS(DSP_OS_FILE, message); if(ReturnCode != RETURN_SUCCESS) printf("\n*Error* %s\n\n", message); else printf("\nDSP Operating System loaded to DPRAM."); ReturnCode = resetDSP(DSP_OS_FILE); // reset the DSP with default OS if (ReturnCode != RETURN_SUCCESS) printf("\n*ERROR* DSP Reset failed.\n"); else printf("\nThe DSP was reset successfully."); return ReturnCode; } // end resetPLXBoard function /************************************ * Function: readLocalReg ************************************/ int readLocalReg(U32 RegisterNumber) { U32 ReadResult; // perform the read ReadResult = PlxRegisterRead( hDevice, RegisterNumber, &rc ); // error-check result if (rc == ApiSuccess) { printf("Register Address: %04x has data %08x\n", RegisterNumber, ReadResult); return RETURN_SUCCESS; } // must be an error printf("*ERROR* Unable to read PLX local register\n"); return RETURN_ERROR; } // end readLocalReg function /************************************ * Function: writeLocalReg ************************************/ int writeLocalReg(U32 RegisterNumber, U32 Data32) { // perform the write rc = PlxRegisterWrite( hDevice, RegisterNumber, Data32 ); // error-check result if (rc == ApiSuccess) { //printf("Data: %08x written to register: %04x\n", Data32, RegisterNumber); return RETURN_SUCCESS; } // must be an error printf("*ERROR* Unable to write to PLX local register\n"); return RETURN_ERROR; } // end writeLocalReg function /************************************ * Function: readPCIReg ************************************/ int readPCIReg(U32 RegisterNumber) { U32 ReadResult; // perform the read ReadResult = PlxPciConfigRegisterRead( Device.BusNumber, Device.SlotNumber, RegisterNumber, &rc ); // error-check result if (rc == ApiSuccess) { printf("Register: %04x has data: %08x\n", RegisterNumber, ReadResult); return RETURN_SUCCESS; } // must be an error printf("*ERROR* Unable to read PCI register\n"); return RETURN_ERROR; } // end readPCIReg function /************************************ * Function: writePCIReg ************************************/ int writePCIReg(U32 RegisterNumber, U32 Data32) { // perform the write rc = PlxPciConfigRegisterWrite( Device.BusNumber, Device.SlotNumber, RegisterNumber, &Data32 ); // error-check result if (rc == ApiSuccess) { //printf("Data: %08x written to register: %04x\n", Data32, RegisterNumber); return RETURN_SUCCESS; } // must be an error printf("*ERROR* Unable to write to PCI register %x\n", RegisterNumber); return RETURN_ERROR; } // end writePCIReg function /************************************ * Function: writeDSPMem ************************************/ int writeDSPMem(U32 Location, U32 NumWords, U32 *Buffer) { U32 Opcode; U32 ReadResult; // Verify the location and numwords, create the opcode ReturnCode = fetchOpcode(Location, NumWords, DSP_WRITE, &Opcode); if (ReturnCode == RETURN_ERROR) return RETURN_ERROR; // fetchOpcode was successful, address has been verified // perform the write to DPRAM rc = PlxBusIopWrite( hDevice, IopSpace, (DPRAM_START_MEM << 2), FALSE, // No Re-map Buffer, (NumWords * 4), // total bytes to write BitSize32 ); // error-check result if (rc != ApiSuccess) { if(MessageLevel > LEVEL2) printf("*ERROR* PlxBusIopWrite failed while writing to DPRAM.\n"); return RETURN_ERROR; } // write NumWords value to Address 0x01 if (writeDPRAMMem(DPRAM_NUMWORDS, 1, &NumWords) != RETURN_SUCCESS) return RETURN_ERROR; // write the command to the DSP mailbox if (writeDPRAMMem(MAILBOX_PCtoDSP, 1, &Opcode) != RETURN_SUCCESS) return RETURN_ERROR; // Signal DSP and wait for it to write the data to DPRAM ReturnCode = readMailbox(MAILBOX_DSPtoPC, &ReadResult); if (ReturnCode==RETURN_TIMEOUT) { if (MessageLevel > LEVEL2) printf("*ERROR* The DSP did not complete writeDSPMem in time. Operation timed out.\n"); return RETURN_ERROR; } // check if DSP returned correct opcode and for other errors if ((ReadResult != DSP_CONFIRM) || (ReturnCode==RETURN_ERROR)) { if (MessageLevel > LEVEL2) { printf("*ERROR* Write to DSP failed.\n"); printf("Opcode: %x DSP returned: %x\n", Opcode, ReadResult); } return RETURN_ERROR; } // display success messages if(MessageLevel > LEVEL1) { printf("\nResults for DSP write...\n"); if (NumWords == 1) printf("Data: %08x written to address: %04x\n", *Buffer, Location); else printf("0x%04x words written successfully.\n", NumWords); } return RETURN_SUCCESS; } // end writeDSPMem function /************************************ * Function: readDSPMem ************************************/ int readDSPMem(U32 Location, U32 NumWords) { U32 Opcode; U32 ReadResult; // Verify the location and numwords, create the opcode ReturnCode = fetchOpcode(Location, NumWords, DSP_READ, &Opcode); if (ReturnCode == RETURN_ERROR) return RETURN_ERROR; // fetchOpcode was successful, address has been verified // write NumWords value to Address 0x01 if (writeDPRAMMem(DPRAM_NUMWORDS, 1, &NumWords) != RETURN_SUCCESS) return RETURN_ERROR; // write the command to the DSP mailbox if (writeDPRAMMem(MAILBOX_PCtoDSP, 1, &Opcode) != RETURN_SUCCESS) return RETURN_ERROR; // Signal DSP and wait for the it to write the data to DPRAM ReturnCode = readMailbox(MAILBOX_DSPtoPC, &ReadResult); if (ReturnCode==RETURN_TIMEOUT) { printf("*ERROR* Read from DSP timed out.\n"); return RETURN_ERROR; } // check if DSP returned correct opcode and for other errors if ((ReadResult != DSP_CONFIRM) || (ReturnCode==RETURN_ERROR)) { if(MessageLevel > LEVEL1) printf("*ERROR* Read from DSP failed.\n"); return RETURN_ERROR; } // the DSP has written the data to DPRAM, now fetch the data // perform the read rc = PlxBusIopRead( hDevice, IopSpace, (DPRAM_START_MEM << 2), FALSE, // No Re-map &BufferRead, (4 * NumWords), BitSize32 ); // error-check result if (rc != ApiSuccess) { if(MessageLevel > LEVEL2) printf("*ERROR* PlxBusIopRead failed, therefore read from DSP failed.\n"); return RETURN_ERROR; } return RETURN_SUCCESS; } // end readDSPMem function /************************************ * Function: runDSPProg ************************************/ int runDSPProg(U32 Location) { U32 Opcode; U32 ReadResult; // Verify the location and numwords, create the opcode ReturnCode = fetchOpcode(Location, 0x0, DSP_EXECUTE, &Opcode); if (ReturnCode == RETURN_ERROR) return RETURN_ERROR; // write the command to the DSP mailbox if (writeDPRAMMem(MAILBOX_PCtoDSP, 1, &Opcode) != RETURN_SUCCESS) return RETURN_ERROR; // Signal DSP and wait for the it to write the data to DPRAM ReturnCode = readMailbox(MAILBOX_DSPtoPC, &ReadResult); if (ReturnCode==RETURN_TIMEOUT) { printf("*ERROR* Code Execution timed out.\n"); return RETURN_ERROR; } // check if DSP returned correct opcode and for other errors if ((ReadResult != DSP_CONFIRM) || (ReturnCode==RETURN_ERROR)) { printf("*ERROR* DSP Code Execution Failed.\n"); printf("Opcode: %x DSP returned: %x\n", Opcode, ReadResult); return RETURN_ERROR; } // display success messages printf("\nDSP Code Execution Complete.\n"); return RETURN_SUCCESS; } // end runDSPProg function /************************************ * Function: writeDPRAMMem ************************************/ int writeDPRAMMem(U32 Location, U32 NumWords, U32 *Buffer) { U32 StartAddress; // Shift address so it is word-aligned StartAddress = Location << 2; // perform the write rc = PlxBusIopWrite( hDevice, IopSpace, StartAddress, FALSE, // No Re-map Buffer, (4 * NumWords), // total bytes to write BitSize32 ); // error-check result if (rc != ApiSuccess) { printf("*ERROR* Write to DPRAM failed.\n"); return RETURN_ERROR; } // display success messages //if (NumWords == 1) printf("Data: %08x written to address: %04x\n", *Buffer, Location); //else printf("Write completed successfully.\n"); return RETURN_SUCCESS; } // end writeDPRAMMem function /************************************ * Function: readDPRAMMem ************************************/ int readDPRAMMem(U32 Location, U32 NumWords) { unsigned int i; // variable for print loop U32 StartAddress; // clear read buffer before reading new data clearReadBuffer(); // Shift address so it is word-aligned StartAddress = Location << 2; // perform the read from the DPRAM rc = PlxBusIopRead( hDevice, IopSpace, StartAddress, FALSE, // No Re-map &BufferRead, (4*NumWords), // 4 is no. of bytes in word BitSize32 ); // error-check result if (rc != ApiSuccess) { return RETURN_ERROR; } // read was successful, now print results //ReadBufferPtr = BufferRead; //printf("\nResults for DPRAM Read...\n"); //for(i=0; i DPRAM_USER_SIZE || (Location+NumWords) > DSP_END_MEM) { // blocksize is too large, print error message printf("*ERROR* Number of words is too large or exceeds DSP memory range.\n"); printf(" The maximum number of words is %x.\n",DPRAM_USER_SIZE); return RETURN_ERROR; } else { // address and numwords have been validated, create opcode // 32-bit Opcode == [8-bit command][24-bit address] *Opcode = ((Location & 0x00FFFFFF) | Command); return RETURN_SUCCESS; } } else { // address is out-of-range of DSP address space printf("*ERROR* Invalid start address. Address must be within 0x0-0x00FFFFFF.\n"); return RETURN_ERROR; } } // end fetchOpcode function /************************************ * Function: readMailbox ************************************/ int readMailbox(U32 Mailbox, U32 *Data) { time_t startTime; time_t currentTime; // If DSP to PC Mailbox, poll for the interrupt if (Mailbox==MAILBOX_DSPtoPC) { time(&startTime); while (TRUE) { *Data = PlxRegisterRead( hDevice, LOCAL_GPIOC, // location = GPIO Config register &rc ); // check status of GPIO0 if((*Data & GPIO4_DATA) == 0) break; // PC Mailbox Interrupt went low // check if TIMEOUT has occured time(¤tTime); if (difftime(currentTime, startTime) > TIMEOUT_DSP_CONFIRM) return RETURN_TIMEOUT; } // end while(TRUE) // check if error when performing last register read in while loop if (rc != ApiSuccess) return RETURN_ERROR; } // end if (Mailbox==MAILBOX_DSPtoPC) // If DSP to PC interrupt just occurred. Must read it to reset // perform the read from the DPRAM rc = PlxBusIopRead( hDevice, IopSpace, (Mailbox << 2), FALSE, // No Re-map Data, 4, // 4 is no. of bytes in word BitSize32 ); // error-check result if (rc != ApiSuccess) return RETURN_ERROR; // read successful return RETURN_SUCCESS; } // end readMailbox function /************************************ * Function: resetDSP ************************************/ int resetDSP(const char *fName) { int ReturnCode; U32 Data; int i; // general purpose loop counter time_t startTime; time_t currentTime; // make /RESET go low // GPIOC bit 25 => 1 to set GPIO8 direction for output (reset to DSP) // GPIOC bit 26 => 0 to output a low, then 1 to output a high on GPIO8 ReturnCode = writeLocalReg(LOCAL_GPIOC,0x02248000); // low if (ReturnCode != RETURN_SUCCESS) { if(MessageLevel > LEVEL1) printf("\n*ERROR* Unable to change GPIO8 for RESET=Low\n"); return RETURN_ERROR; } // clear DSPtoPC mailbox before reset (DPM_INTL) ReturnCode = readDPRAMMem(MAILBOX_DSPtoPC, 1); if (ReturnCode != RETURN_SUCCESS) { if(MessageLevel > LEVEL1) printf("\n*ERROR* Unable to clear DSP Mailbox before reset.\n"); return RETURN_ERROR; } // now that /RESET is low, load the OS into the DPRAM ReturnCode = loadOS(fName, message); if(ReturnCode != RETURN_SUCCESS) { printf("\n*Error* %s", message); printf("\nLoading the default OS: \"%s\".",DSP_OS_FILE); if(loadOS(DSP_OS_FILE, message)!=RETURN_SUCCESS) { printf("\n*Error* %s\n\n", message); printf("\nThe default OS \"%s\" could not be loaded.",DSP_OS_FILE); printf("\n\nThe DSP is now in an unknown state."); return RETURN_ERROR; } } ReturnCode = writeLocalReg(LOCAL_GPIOC,0x06248000); // high if (ReturnCode != RETURN_SUCCESS) { if(MessageLevel > LEVEL1) printf("\n*ERROR* Unable to restore GPIO8 for RESET=High\n"); clearWriteBuffer(); return RETURN_ERROR; } // wait for reset confirmation to be loaded into DPRAM if(readMailbox(MAILBOX_DSPtoPC, &Data)==RETURN_TIMEOUT) { if(MessageLevel > LEVEL1) printf("\n*WARNING* DSP reset confirmation timed out.\n"); clearWriteBuffer(); return RETURN_ERROR; } // check confirmation data returned from DSP if (Data==DSP_CONFIRM) { // overwrite dsp OS in write buffer clearWriteBuffer(); return RETURN_SUCCESS; } // reset didn't work if(MessageLevel > LEVEL1) printf("\n*WARNING* DSP reset confirmation was not received. Returned data: %x\n",Data); return RETURN_ERROR; } // end resetDSP function /********************************************************************** * Function: loadDSP * * The loadDSP routine will take a COFF (COMMON OBJECT FILE FORMAT) * formatted file and load it into the DSP memory. The COFF file is * the format outputed by the lnk3x.exe linker program. * * The "message" parameter must be pointer to an EXISTING block of * of memory which is defined as type char. This is used to return * error messages back to the calling program. This routine will * allocate the memory for you if "message" is a NULL pointer. However, * you will be responsible for returning the memory to the heap by * calling a free(); * * You may alternatively convert all the sprintf statements to printf * if you want the error messages displayed to the standard output. * Then you may remove the "message" parameter completely. * * This routine returns 1 for success 0 otherwise. ***********************************************************************/ int loadDSP(const char *fName, char *message) { int section, m; U32 load_address; FILE *fpin; File_Header file_header; Section_Header section_header[MAX_SECTIONS]; U32 ssize; // section size double subsections; int i; // loop counter U32 *image_ptr; // pointer to section_image U32 section_image[MAX_SECTION_IMAGE_SIZE]; if(!message) message = (char *)calloc(1024,sizeof(char)); if((fpin=fopen(fName,"rb"))==NULL) { sprintf(message,"Can't open %s for read\n",fName); return(RETURN_ERROR); } if(fread(&file_header,sizeof(file_header),1,fpin) !=1) { sprintf(message,"Error reading %s",fName); return(RETURN_ERROR); } if(file_header.magic != 0x0093) { fclose(fpin); sprintf(message,"Invalid input file type"); return(RETURN_ERROR); } if(file_header.opt_head_size != 0) { fseek(fpin, file_header.opt_head_size, SEEK_CUR); } for(section=0;section<(int)file_header.num_sec;section++) { if(fread(§ion_header[section],sizeof(section_header[0]),1,fpin) != 1) { sprintf(message,"Error reading section header from %s\n",fName); return(RETURN_ERROR); } } for(section=0;section<(int)file_header.num_sec;section++) { if(section_header[section].flags != STYP_BSS) { if(fseek(fpin,section_header[section].raw_data_pointer,0)) { sprintf(message,"Seek error in file %s\n",fName); return(RETURN_ERROR); } load_address=section_header[section].physical_address; m=fread(section_image,sizeof(unsigned long),(int)section_header[section].size,fpin); if(m != (int)section_header[section].size) { sprintf(message,"Only read %d words. Should be %d words.\nError reading raw data from section %s", m,(int)section_header[section].size,section_header[section].name); return(RETURN_ERROR); } if((ssize=section_header[section].size)>0) { double sub = (double)ssize/(double)DPRAM_USER_SIZE; subsections = ceil(sub); image_ptr = section_image; for (i=0;i=10) printf("\n**********************************"); //else printf("\n*********************************"); if (ssize > DPRAM_USER_SIZE) { if(MessageLevel > LEVEL1) printf("\n*** Section: %d Subsection: %d ***", section,i); //if(i>=10) printf("\n**********************************"); //else printf("\n*********************************"); //printf("\nLoad address: %x Size: %x\n", load_address,DPRAM_USER_SIZE); writeDSPMem(load_address, DPRAM_USER_SIZE, image_ptr); ssize -= DPRAM_USER_SIZE; // decrememnt total size image_ptr += DPRAM_USER_SIZE; // increment pointer to next subsection load_address += DPRAM_USER_SIZE; // increment load address } else // last subsection { if(MessageLevel > LEVEL1) printf("\n*** Section: %d Subsection: %d ***", section,i); //if(i>=10) printf("\n**********************************"); //else printf("\n*********************************"); //printf("\nLoad address: %x Size: %x\n", load_address,ssize); writeDSPMem(load_address, ssize, image_ptr); } } // end for } } } fclose(fpin); return RETURN_SUCCESS; } // end load DSP function /********************************************************************** * Function: loadOS * * Load the DSP operating system into DPRAM memory. The DSP must be * reset after calling this function. The DSP will then load and boot * from the DPRAM code. /**********************************************************************/ int loadOS(const char *fName, char *message) { FILE *fpin; unsigned int buffer_words; // put DSP in reset writeLocalReg(LOCAL_GPIOC,0x02248000); // make GPIO8 low if(!message) message = (char *)calloc(1024,sizeof(char)); if((fpin=fopen(fName,"rb"))==NULL) { sprintf(message,"Cannot open file \"%s\" for read.\n",fName); return(RETURN_ERROR); } buffer_words = fread(BufferWrite, WORD_WIDTH, DPRAM_USER_SIZE, fpin); fclose(fpin); // need to reverse the byte order of the data // --------------------------------------------------------------- // | B0 | B1 | B2 | B3 | Current format (because Intel machine) // --------------------------------------------------------------- // | B3 | B2 | B1 | B0 | We need this format (Big Endian TI Chip) // --------------------------------------------------------------- switchEndianess(BufferWrite, buffer_words); // now write the data to DPRAM memory ReturnCode = writeDPRAMMem(0, buffer_words, BufferWrite); if(ReturnCode != RETURN_SUCCESS) { if(MessageLevel > LEVEL1) printf("\n*ERROR* Failed to write new OS to DPRAM."); clearWriteBuffer(); return RETURN_ERROR; } clearWriteBuffer(); return RETURN_SUCCESS; } // end loadOS function /********************************************************************** * Function: switchEndianess * * reverse the byte order of the data: * --------------------- * | B0 | B1 | B2 | B3 | Current format * --------------------- * | B3 | B2 | B1 | B0 | We need this format (or vice versa) * --------------------- /**********************************************************************/ void switchEndianess(U32 *buffer, int words) { U32 B0,B1,B2,B3; U32 TEMP; unsigned int i; for (i = 0; i <= words; i++) { TEMP = buffer[i]; B3 = ((U32) 0x000000FF & TEMP) << 24; B2 = ((U32) 0x0000FF00 & TEMP) << 8; B1 = ((U32) 0x00FF0000 & TEMP) >> 8; B0 = ((U32) 0xFF000000 & TEMP) >> 24; buffer[i] = (U32) (B3 | B2 | B1 | B0); } } // end switchEndianess function