Blackfin Speedway Workshop Lab 3 TCP/IP Using: Page 1 of 11 Purpose: The purpose of this lab is to show the necessary steps in creating a TCP/IP based application. In addition to implementing the TCP/IP stack, the user will also learn the steps necessary to create boot code, initialize the memory controller, and boot the board independent of the software tools. These lessons will be useful for when a designer creates their own board and at sometime wants to create his/her own boot image. Page 2 of 11 TCP/IP LwIP for ADSP-BF537 EZ-KIT LiteTM This example uses the TCP/IP framework provided with VisualDSP++ for Ethernet applications to setup a pingable client-server application. The 1st phase of this project is to setup the hardware: STEPS: 1) Plug the USB Debug Agent into the ADSP-BF537 EZ-KIT Lite board and into a free USB port on your PC. Plug in the included AC adapter and power on the board. 2) Plug the supplied EIA/TIA 568-B.2 cross-over cable into the RJ45 ports of both the ADSP-BF537 EZ-KIT Lite and your PC. 3) You must give your network card a specific IP address for this lab to work. Go to “Start->Settings->Network Connections” and right-click on “Local Area Connection” and select “Disable” to shut down the connection and avoid your PC trying to continuously connect to the board before the application is loaded. Right-click again and select “Properties…”. Select the “Internet Protocol (TCP/IP)” item and click Properties. Click “Use the following IP address” and enter the following: IP address: 192.168.0.3 Subnet mask: 255.255.255.0 Default gateway: 1.1.1.1 Click OK to close the TCP/IP Properties window. Click Close to close the Local Area Connection Properties window. Now that the PC and EZ-KIT are properly configured, the 2nd phase is to create, build, and load the TCP/IP application via the USB Debug Agent to the BF537 EZ-KIT Lite. 4) Launch VisualDSP++ using the desktop shortcut and open a “BF537 EZKIT Lite via Debug Agent” session. If there are any projects open in your active IDDE session, right-click the “Project Group” in your Project window on the left and select “Close All Projects”. Click Yes in response to any pop-up windows. 5) Right-click the empty “Project Group” and select “Add New Project…” Page 3 of 11 This will invoke the New Project Wizard. Give your project a name and use the “c:\speedway\Lab3” directory to save your newly created project. Under “Project types”, select “TCP/IP Stack application using LwIP and VDK”. Click Next->. In the pop-up, click Yes to create the directory. 6) On the next screen, select the ADSP-BF537 as your Processor type. Use the “Automatic” silicon revision. Leave the Project output type as “Executable file”. Click Next->. 7) In the “Add Startup Code” phase, leave “No” selected and click Next->. 8) The next step targets the ADDS-BF537 EZ-KIT Lite board. Click Next->. 9) The final step summarizes your skeletal project. Click Finish and observe the Project being populated in your Project window on the left. The default TCP/IP libraries are built assuming a DHCP server is running on your network. Since this is a point-to-point application, the TCP/IP libraries must be built for a static IP address. 10) In VisualDSP++, use the “Settings->Preferences…” pull-down and click on the Plugins selection on the left. Scroll the window down and make sure the “TCP/IP Configuration Manager” box is checked. Click OK. 11) Use the “Settings->TCP/IP Configuration…” pull-down and click the Network0 tab. Make sure “Use DHCP” is not selected and fill in the first three fields as follows: IP address: 192.168.0.2 Subnet mask: 255.255.255.0 Default gateway: 1.1.1.1 Note that these values are the same as the settings given in the initialization of your network card above, with the exception that the IP address itself is 1 less than that given to the network card. 12) Click the General tab. Under Protocols, select All and click the “Save and add to project” button. Give your file the name “speedway.tcp” and click Save. Note that the Configuration File field is populated with the file you just created. Click OK and note that a TCP/IP Configuration folder now appears in your Project window. 13) Before a TCP/IP connection can be established, you must re-enable your PC network card. Return to your “Network Connections” and right-click on “Local Area Connection” and select “Enable”. Page 4 of 11 14) Use F7 to build and load the project. Select Yes in the pop-up asking if you’d like to save the files that have been modified. Press F5 to run the project and note three strings output to the Console window: Waiting for the link to be established Link established IP Address: 192.168.0.2 15) Open a command prompt and type ping 192.168.0.2. You should see a 0% loss on the test packets sent in the ping operation. Now phase two is complete. Phase three is going to add some functionality to the client so that it has the ability to do something beyond responding to a ping. 16) NOTE: While doing this step, Double-check the spelling of the ThreadType name (Caesar_Cipher_ThreadType), as any misspelling will cause compilation errors and incorrect naming of all the skeleton code. As a result you will have numerous errors requiring several edits. From the Kernel tab of the VisualDSP++ Project window, navigate to “Kernel–>Threads– >Thread Types”. Right-click “Thread Types” and select “New Thread Type”. Type Caesar_Cipher_ThreadType in the Name field. Click OK. 17) Switch back to the Project tab, expand the Source Files sub-tree, and double-click Caesar_Cipher_ThreadType.cpp to open the file. Replace the method Caesar_Cipher_ThreadType::Run() with this code (copy/paste): Note: For convenience, all the snippets below can be copy and pasted from the *.txt files found in c:\speedway\lab3\cut and paste files\lab3stepXX.txt For example, the code below is found in “c:\speedway\lab3\cut and paste files\lab3step17.txt”. Open the file and copy/paste the information into the appropriate place in the project source file. Please be careful when cutting and pasting to ensure there is no “orphaned” text or braces. void Caesar_Cipher_ThreadType::Run() { static char *pszWelcome = "Welcome to Blackfin. Type letters \"A\" though \"Z\" and I will encrypt them.\xa\xd"; if ( 0 >= send ( m_iSocket, pszWelcome, strlen ( pszWelcome ), 0 ) ) return; while (1) { int iCount; if ((iCount= recv(m_iSocket, m_vInBuf, sizeof(m_vInBuf)/sizeof(char), 0)) >= 1 ){ Page 5 of 11 int iCharNum; char c; for ( iCharNum = 0; iCharNum < iCount; ++iCharNum ){ c = m_vInBuf [ iCharNum ]; if ( ( c >= 'A' && c <= 'Y' ) || ( c >= 'a' && c <= 'y' ) ) ++c; else if ( c == 'Z' || c == 'z' ) c -= ( 'Z' - 'A' ); m_vOutBuf [ iCharNum ] = '\x8'; /* telnet backspace control character to overwrite the character sent */ m_vOutBuf [ iCharNum + iCount ] = c; } if ( send (m_iSocket, m_vOutBuf, iCount * 2, 0) <= 0 ) break; } else{ break; } } close ( m_iSocket ); } 18) Replace the Caesar_Cipher_ThreadType::Caesar_Cipher_ThreadType() constructor with this code (copy/paste): Caesar_Cipher_ThreadType::Caesar_Cipher_ThreadType(VDK::Thread::ThreadCreation Block &tcb) : VDK::Thread(tcb) { m_iSocket = (int) tcb.user_data_ptr; } 19) Expand the Header Files sub-tree and double-click Caesar_Cipher_ThreadType.h to open the file for editing. Add this code to the class immediately before the ending brace “};” (copy/paste): protected: int m_iSocket; char m_vInBuf[16]; char m_vOutBuf[16*2]; int m_iBufLen; 20) In Caesar_Cipher_ThreadType.cpp, add #include <lwip/sockets.h> near the top of the file with the other #include directives. 21) In lwip_sysboot_threadtype.c, replace the member function lwip_sysboot_threadtype_RunFunction with this code (copy/paste): void lwip_sysboot_threadtype_RunFunction(void **inPtr){ char ip[32]; Page 6 of 11 if(system_init() == -1) { printf("Failed to initialize system\n"); return; } start_stack(); /* start stack */ memset(ip,0,sizeof(ip)); if(gethostaddr(0,ip)) { printf("IP ADDRESS: %s\n",ip); } struct sockaddr_in saddr; int listenfd; if ( 0 > ( listenfd = socket ( AF_INET, SOCK_STREAM, 0 ) ) ) printf ( "Call to socket() failed.\n" ); abort(); } { memset ( &saddr, 0, sizeof ( saddr ) ); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl ( INADDR_ANY ); saddr.sin_port = htons ( 23 ); /* listening on port 23 (well-known default "telnet") */ if ( -1 == bind ( listenfd, (struct sockaddr*) &saddr, sizeof(saddr) ) ) printf ( "Call to bind() failed.\n" ); abort(); } { if ( -1 == listen ( listenfd, 0 ) ) { printf ( "Call to listen() failed.\n" ); abort(); } for ( ;; ) { struct sockaddr cliaddr; int clilen; int iSocket; iSocket = accept (listenfd, &cliaddr, &clilen); if ( -1 == iSocket ) { printf ( "Call to accept() failed.\n" ); abort(); } VDK_ThreadCreationBlock TCB = { kCaesar_Cipher_ThreadType, (VDK_ThreadID)0, 0, (VDK_Priority)0, (void *) iSocket, 0 }; if ( UINT_MAX == VDK_CreateThreadEx ( &TCB ) ) { printf ( "Call to VDK_CreateThreadEx() failed.\n" ); abort(); } Page 7 of 11 } } 22) Press F7 to build. Select Yes in the pop-up asking to stop the currently running program. Now, press F5 to run. As described earlier, the assigned IP address is echoed to the VisualDSP++ Console window. Open the Command Prompt and use the telnet application to connect to the EZ-KIT: telnet 192.168.0.2 23) Once connected, you’ll see the welcome message: Welcome to Blackfin. Type letters ‘A’ though ‘Z’ and I will encrypt them. 24) Type characters A through Z and you should see the letter is incremented by 1 and displayed (both lower and upper case) while non-letter characters are echoed back as input. 25) When finished, close the telnet session with CTRL+ ] and type ‘quit’ at the telnet prompt. Page 8 of 11 That concludes phase three. The next phase is to create a loader file (boot image), which will be used to program the flash so that the processor can boot the application and run stand-alone, such that the only connection to the PC is the RJ45 ethernet cable. By default, the SDRAM controller on the Blackfin processors is initialized by the VisualDSP++ IDDE through a series of register reset values defined in the processor’s XML file, in this case ADSP-BF537-proc.xml, which is located in the “…\Analog Devices\VisualDSP 4.0\System\ArchDef” install directory. For an end application, however, initialization of the SDRAM controller is required prior to accessing the SDRAM memory space, otherwise hardware errors will be generated when the boot kernel attempts to load code/data to external memory. Since the LwIP software will be resolved to external SDRAM during booting, an INIT block needs to be included in the loader file, which will be loaded and executed before the rest of the application is booted. Initialization code is already available for the ADDS-BF537 EZ-KIT Lite to setup the SDRAM controller for the default settings of the EZ-KIT, however, for the sake of instruction, you will create the init code here. Remember that your application may use a different SDRAM device, a different crystal/oscillator CLKIN, or a different SCLK, therefore, you would need to program these registers according to YOUR timing specifications. To create your init block: 26) Using Windows Explorer, create a directory in your working project directory(C:\speedway\Lab3\) called InitCode. Go to the “…\Analog Devices\VisualDSP 4.0\Blackfin\ldr\init_code” directory and copy the file Init_code.asm to your InitCode directory (c:\speedway\Lab3\init_code\). 27) In the VisualDSP++ IDDE Project window, right-click the “Project Group” and select “Add New Project…”. Use the new project wizard to setup a “BF537 standard application” named InitCode and set the directory to the InitCode directory that you created in step 26. Click Next>, Next>, Next>, Finish to complete the wizard. 28) Right-click the “Source Files” sub-tree under the InitCode project, select “Add File(s) to folder…”, and double-click the Init_code.asm file that you copied in step 26. 29) Open Init_code.asm and change the included header file to defBF537.h. 30) Use “File->Open…->File…” to open the ADSP-BF537-proc.xml file found in the Analog Devices\VisualDSP 4.0\System\ArchDef” directory. Scroll to the bottom of the file to find the section labeled “Register resets used by emulator”. Use these values to program the corresponding registers in Init_code.asm. Note: Do not copy line by line the contents of the xml file. Rather, see what hex values are Page 9 of 11 being assigned to the SDRAM configuration registers and then using/editing the assembly language in the init_code.asm; assign the same values to the same registers. See example below Ex: To assign a 32-bit value to a data register, you need to assign the upper 16-bits to Rx.H and the lower 16-bits to Rx.L e.g., to assign 0x12345678 to R0: R0.H = 0x1234; R0.L = 0x5678; 31) Right-click the “Linker Files” sub-tree under InitCode, select “Add File(s) to folder…”, go to the “…\Analog Devices\VisualDSP 4.0\Blackfin\ldf” directory, and double-click ADSP-BF537_ASM.ldf. This is an assembly-only LDF and is required when no CRT is used. 32) Build the project to generate the Init_code.dxe file in the \InitCode\Debug directory. 33) Now right-click your LwIP project and “Set as Active Project”. Rightclick again to access “Project Options…”. Next to the “Type” pull-down, select “Loader file”. Click the Load sub-tree and select a boot mode of Flash/PROM, a boot format of Intel hex, and an output width of 16-bit. These are the appropriate selections for the flash memory populated on the ADDS-BF537 EZ-KIT Lite. Click the browse “…” button next to “Initialization file” and select your Init_code.dxe file you just created in your \InitCode\Debug directory. Click OK when done. 34) Press F7 to build the project again. Select Yes in the pop-up asking to rebuild affected files. Select No in the subsequent pop-up asking to reload the program. Notice the Build Window indicates that you’ve created a loader file this time. 35) Now it is time to physically program the flash. Use the “Tools->Flash Programmer…” pull-down to open the Flash Programmer Utility. Click the browse button “…” next to the “Driver file” dialog and navigate to the directory “...\Analog Devices\VisualDSP 4.0\Blackfin\Flash Programmer Drivers\ADSP-BF537 EZ-kit Lite” and select the “BF537EzFlash.dxe” file. Click the “Load Driver” button and observe the Status LED changing from red to yellow to green. Once green, the driver has successfully loaded and the flash memory device description appears next to the LED. Page 10 of 11 36) Next to the “Data file” dialog box, click the browse “…” button and navigate to your \Debug directory and double-click the *.ldr file that you just created. Click “Load File” and observe the green status bar at the bottom changing until the load is complete. Close the Flash Programmer window. 37) In the disassembly window (note: you may need to re-arrange your project windows to view the disassembly window), double-click the “NOP;” that is highlighted under the AFP_BreakReady label to clear the breakpoint. Type jump 0; at this location to create an infinite loop. Strike F5 to leave emulation space and press the Reset button on the EZ-KIT. Halt the processor using SHIFT+F5 and you will see that the application code has changed because the processor has booted your application from flash and has overwritten the flash programmer code that was there. 38) Close VisualDSP++ and unplug the USB Debug Agent from the EZ-KIT. Press the Reset button on the board again to boot the application. Open a command prompt and ping the board using ping 192.168.0.2. When the ping is successful, execute telnet 192.168.0.2 and run the Caesar Cipher algorithm. The part is up and running and you are done with this demo! Make sure you restore the network settings that we modified in your PC hardware to make this demo work!!! Page 11 of 11