The SI-C667x product line is based on Texas Instruments Keystone Hardware and Software modules. TI's documents and resources are highly recommended for users to fully understand the architecture and utilization of the SI-C667xDSP board. Below is a breakdown of C667x key NDK features and links to learn how to use them.
BIOS_start();
The "after main()" startup sequence is governed by SYS/BIOS and is initiated by an explicit call to the BIOS_start() function at the end of the application's main() function. The SYS/BIOS startup sequence that run when BIOS_start() is called is as follows: 1. Startup Functions. Run the user-supplied "startup functions" (see BIOS.startupFxns). If the system supports Timers, all statically created timers are initialized at this point using their static configuration. If a timer was configured to start "automatically," it is started here. 2. Enable Hardware Interrupts. 3. Enable Software Interrupts. If the system supports software interrupts (Swis) (see BIOS.swiEnabled), then the SYS/BIOS startup sequence enables Swis at this point. 4. Task Startup. If the system supports Tasks (see BIOS.taskEnabled), then task scheduling begins here. If there are no statically or dynamically created Tasks in the system, then execution proceeds directly to the idle loop
Startup.lastFxns.$add('&EVM_init'); : Last in a list of functions called after module startup var tskNdkStackTest = Task.create("&StackTest"); tskNdkStackTest.stackSize = 0x2000; tskNdkStackTest.priority = 0x6;
Tasks represent independent threads of control that conceptually execute functions in parallel within a single C program; in reality, concurrency is achieved by switching the processor from one task to another.
When you create a task, it is provided with its own run-time stack, used for storing local variables as well as for further nesting of function calls. Each stack must be large enough to handle normal subroutine calls and one task preemption context. A task preemption context is the context that gets saved when one task preempts another as a result of an interrupt thread readying a higher-priority task. All tasks executing within a single program share a common set of global variables, accessed according to the standard rules of scope defined for C functions.
Each task is in one of five modes of execution at any point in time: running, ready, blocked, terminated, or inactive. By design, there is always one (and only one) task currently running, even if it is only the idle task managed internally by Task. The current task can be suspended from execution by calling certain Task functions, as well as functions provided by other modules like the Semaphore or Event Modules. The current task can also terminate its own execution. In either case, the processor is switched to the highest priority task that is ready to run.
You can assign numeric priorities to tasks. Tasks are readied for execution in strict priority order; tasks of the same priority are scheduled on a first-come, first-served basis. The priority of the currently running task is never lower than the priority of any ready task. Conversely, the running task is preempted and re-scheduled for execution whenever there exists some ready task of higher priority.
var Idle = xdc.useModule('ti.sysbios.knl.Idle'); Idle.idleFxns[0] = "&hBeatFxn";
The Idle module is used to specify a list of functions to be called when no other tasks are running in the system. If tasking is enabled (ie BIOS.taskEnabled = true), then the Task module will create an "Idle task" with the lowest possible priority. When no other tasks are running, this idle task runs in an infinite loop, calling the list of functions specified by the Idle module. If tasking is disabled (ie BIOS.taskEnabled = false), then the idle functions are called in an infinite loop within the BIOS_start function called within main().
The different thread types main differences outlined below:
For more programming details, please refer to the SYS/BIOS User's Guide:
The TI-RTOS Networking or TI NDK (Network Development Kit) combines dual mode IPv4/IPv6 stack with some network applications, and is not included with CCS. Therefore, the TI NDK must be separately downloaded; for more details and documentation, please refer to the TI web page:
Please note that NDK interfaces NETCP directly and does not utilize the PA; which is to say that the hardware stack will filter some of the incoming packets while the NDK software stack will filter out rest of the packets. The PA provides better performance but requires a steeper learning curve. As such if used and properly configured, the PA will increase performance since unnecessary packets will be filtered out on the hardware level. However, the NDK provides a simpler interface allowing the user to easily port Host side socket code to the DSP side.
According to TI:
TI provides both NDK and PA LLD. The application can either use NDK or PA LLD with a network stack provided by the customer. If you choose to use the NDK, your application should interface with the NDK only, i.e. invoking NDK APIs for all data traffic. If you choose to use the PA LLD, you need to write your own network stack to interface with the PA LLD and other low layer software stacks such as CPPI and QMSS LLDs.
TI PDK (Platform Development Kit) is a package that provides the foundational drivers and software to enable the device, and is included with CCS. From a software development perspective, the SI-C667xDSP board has differences with the TI EVM and therefore SI provides a customized TI PDK package for its users. To use the SI PDK and create projects with CCS, the following steps must be performed:
TI provides some really useful C6x software libraries for use on the C667x. The Mathlib in particular is a well optimized and useful library. Please refer to the TI web page:
SI provides several DSP demo projects, and are designed to work in conjunction with their corresponding Host side demo projects.
Sample_DSP_C667x
This project contains a simple heartbeat loop and some basic arithmetic commands. To use this project, open HostExampleApp and use option '1' to load the precompiled 'sample.out' binary file to the DSP, then use option 'm' for the interactive display.
Sample_Ethernet
This project contains a simple TCP echo server running on the DSP side. It demonstrates initialization and utilization of the TI Keystone Ethernet interface. Please note that the SI PDK is required along with any Ethernet projects that run on the SI-C667xDSP board; refer to the PDK section for additional details. The workflow for this project is listed below:
h1. PDK
Modifications to the TI C6678 EVM PDK to operate with our hardware.
{{TOC}}
h2. platform.c
h3. EMAC Port Selection
When the PDK builds its configuration descriptors for the EMAC ports, it determines how to enumerate the ports based on an enum _emac_port_mode_. This enum tells the constructor functions what mode the port should be configured to. There are two emac ports on the C6678 and they are represented by the 0 and 1 types specified in the _emac_port_mode_ enum.
The array 'emac_port_mode' is defined in platform.c.
⚠ <pre>
/* This structure holds information about the EMAC port on the platform */
PLATFORM_EMAC_PORT_MODE emac_port_mode[PLATFORM_MAX_EMAC_PORT_NUM] = {
PLATFORM_EMAC_PORT_MODE_PHY, //Port 0 PLATFORM_EMAC_PORT_MODE_NONE //Port 1
};
Note: Our PHY is on Port 0. The EVM board uses Port 1.
⚠ </pre>
The enum type _PLATFORM_EMAC_PORT_MODE_ is defined in platform.h.
⚠ <pre>
/**
* @brief Indicates the EMAC port mode * */
typedef enum {
PLATFORM_EMAC_PORT_MODE_NONE, /**<EMAC port not used */ PLATFORM_EMAC_PORT_MODE_PHY, /**<EMAC port connected to a PHY */ PLATFORM_EMAC_PORT_MODE_AMC, /**<EMAC port connected to the backplane AMC chassis */ PLATFORM_EMAC_PORT_MODE_MAX /**<End of port mode */
} PLATFORM_EMAC_PORT_MODE;
⚠ </pre>
h3. platform_init
h4. PASS PLL
The function will test various config flags( arg passed to platform_init(platform_init_flags, ...)) to see which systems on the chip need to be configured. The first test is to configure the PLLs. We do not need to set the Main PLL as that is done through the I2C boot, but we do need to setup the PASS PLL. The relevant code can be moved outside the PLL configure check to force the PASS PLL configuration. The following is the required PASS PLL configuration code:
Note: This is located in platform_init(...) inside platform.c
⚠ <pre>
status = SetPaPllConfig(); if (status != CSL_SOK) { platform_errno = PLATFORM_ERRNO_PLL_SETUP; return ( (Platform_STATUS) Platform_EFAIL); }
⚠ </pre>
The function _SetPaPllConfig_ is defined in evmc6678.c and by default uses the configuration settings for a PASS CLK of 100 Mhz. Our board's boot configuration disables the input PASSCLK and switches the PASS Clock source selection multiplexer to use the CORECLK input.
This clock is used to clock the NetCP which requires a 350 Mhz clock. The PASSPLL has an automatic divide by 2 and there is an additional divide by 3 before the input to the NetCP.
Note: 'DNUM' value in this function should refer to core 0 so that this is only run if coe zero is running this code.
h4. PowerUpDomains
This function is defined in evmc6678.c and enables various system domains through the PCS (Power Sleep Controller). At this time it is not necessary to power up the EMIF4 or the EMIF25/SPI. The relevant lines of code should be commented out.
⚠ <pre>
void PowerUpDomains (void)
{
... /* Enable the clocks for PASS modules */ //CSL_PSC_setModuleNextState (CSL_PSC_LPSC_EMIF4F, PSC_MODSTATE_ENABLE); //CSL_PSC_setModuleNextState (CSL_PSC_LPSC_EMIF25_SPI, PSC_MODSTATE_ENABLE); ....
}
Note: PowerUpDomains(void) can be found in evmc6678.c
⚠ </pre>
h4. PHY Config
The PHY Config flag should be set and this will cause the PHYs to be configured. The PHY configuration function _Init_SGMII_ takes as its argument the MDC/MDIO address of the device to configure. Our Marvell 88E1111 is presently wired to address/port 0x0.
Note: This can be found in platform_init(...) inside of platform.c
In the examples EVM_init() sets the Phy config flag(p_flags->phy) and calls platform_init(flags, ...)
⚠ <pre>
if (p_flags->phy) //<--phy config flag { configSerdes(); mNotify(0x61); Init_SGMII(0); //<--we use macPortNum = 0 //Init_SGMII(1); }
⚠ </pre>
h3. NOTE: Revisit _Init_SGMII()_ and the need for modifications if needed
h2. evmc6678_phy.c
h3. configSerdes()
Change the SERDES PLL multiplier and divider settings to match the input reference clock SRIOSGMIICLK input.
In the Gigabit Ethernet (GbE) Switch Subsystem User Guide there is a table on page 3-82 that shows the available PLL multiply options. There is an automatic divide by two on the PLL output and the final output frequency needs to be 1.25 Ghz. So the PLL multiplier and divider settings for the SRIOSGMIICLK input clock should result in an output frequency of 2.5 Ghz which will then be divided by two.
For 312.5 Mhz *Multiply by 8 uses 0x41
⚠ <pre>
CSL_BootCfgSetSGMIIConfigPLL (0x00000041);⚠ </pre>
For 250 Mhz *We use 250 Mhz so we multiply by 10
⚠ <pre>
CSL_BootCfgSetSGMIIConfigPLL (0x00000051);⚠ </pre>
h2. TODO
1. Verify _Init_SGMII()_ sections need for changes or not. 2. Write function to convert binary as hex and assign to array.
h2. Random
1. Encountered a build error: Two resources of the same name: /blah/blah/blah generated by different tools tool1: C6000 Compiler tool2: C6000 Compiler
Only seemed to disappear once I cleaned all project without rebuilding at the same time. Until then builds would only show this error in a pop up but not the output window. All binaries created would fail when loaded After I did a clean all, then build platform, and finally a build of my project did my binary work on the new system -Perhaps a clean with build is not a full clean
2. The webpage uses a mixture of generated web pages and a pre-existing default.htm file to create the webpage
h1. NDK
{{TOC}}
h2. Notes
h3. Getting started
h4. Set up network services:
THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION before using the stack!!
int NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
NETCTRL is used to initialize the stack and maintain services. To accomplish this, it makes use of the configuration manager provided in the NETTOOLS library. Note that the configuration definitions and structures defined here are specific to NETCTRL, not CONFIG.
// First: Initialize the run-time environment _extern int NC_SystemOpen( int Priority, int OpMode );
h4. Create and build the system configuration from scratch.
I have yet to see this is documentation but the example follows with:
_extern HANDLE CfgNew();
_extern int CfgAddEntry( HANDLE hCfg, uint Tag, uint Item, uint Mode, int Size, UINT8 *pData, HANDLE *phCfgEntry );
See "int StackTest()"
h4. Start the network using the supplied configuration
_extern int NC_NetStart( HANDLE hCfg, void (*NetStart)(), void (*NetStop)(), void (*NetIP)(IPN,uint,uint) );
Example) static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
_extern HANDLE TaskCreate( void(*pFun)(), char *Name, int Priority, uint StackSize, UINT32 Arg1, UINT32 Arg2, UINT32 Arg3 );
fdOpenSession( TaskSelf() );
socket(), send(), bind(), listen, ...
TaskBlock( TaskSelf() );
h4. Destroy a configuration
_extern void CfgFree( HANDLE hCfg );
h4. Close down the run-time environment
_extern void NC_SystemClose();
h3. NC_NetStart - netctrl.c
If you are not using XGCONF, your application must call the NETCTRL function NC_NetStart() to invoke the network scheduler after the configuration is loaded. Besides the handle to the configuration, this function takes three additional callback pointer parameters; a pointer to a Start callback function, a Stop function, and a IP Address Event function. The first two are run once and are pretty self-explanatory. The latter is run every time an IP Address is given.
Summary: NC_NetStart() handles network requests and is run in a loop so that you may reboot it if you choose. The function does not exit unless you reboot or stop it(error can cause a stop too).
_llTimerInit() - associates some event with a timer initialized to zero - Purpose: ?? _llUserLedInit() - EVM specific - Initialize LED driver _llSerialInit() - Initialize CPLD(appears to handle their external interrupts), associate EXTINT7 with a handler Also sets default contol alues for serial devices. Not sure how the two are related. _llPacketInit() - DOES NOTHING(casts event handle as void) but claims to open packet driver and enumerate devices NIMUInit - Initialize Network Interface Management Unit Core stack - Initialzes the EMAC and software interface VLANInit - init vlan usule in core stack(ensure enough spce for NIMU header) IPv6Init - Init IPv6 Stack if used Save Network Open, Close, IP Address pointers - create loacal servers(tasks), kill them , and print message for new connections ExecOpen() - Sero out udp, tcp, ipv6, raw, stat structures NS_BootTask - Install service provider callbacks and boots user tasks ( OS, IP, Service, IpNet, Route) NetScheduler - STart running the stack and only exit when nethalt to clean up all previous calls
- check for stack related eventts, timer, ethernet, and serial - polls events and handles them
LOOK HERE:
3.2.5.1 The NETCTRL Task Thread If you are not using XGCONF, your application must create a Task thread that contains a call to ND_NetStart(), which in turn runs the network scheduler function. The NSP example applications provide this thread. SPRU523H–May 2001–Revised February 2012 Configuring the NDK with C Code (without XGCONF) This Task thread (called the scheduler thread) is the thread in which nearly all the NETCTRL activity takes place. This thread acts as the program’s entry-point and performs initialization actions. Later, it becomes the NETCTRL scheduler thread. Therefore, control of this thread is not returned to the caller until the stack has been shut down.
h2. NDK User Guide
h3. The STACK Library
The STACK library is the main TCP/IP networking stack. It contains everything from the sockets layer at the top to the Ethernet and Point-to-point protocol (PPP) layers at the bottom. The library is compiled to make use of the SYS/BIOS operating system, and does not need to be ported when moved from one platform to another. Several builds of the library are included in the NDK. The STACK libraries are provided in the <NDK_INSTALL_DIR>\packages\ti h3. NETTOOL Libraries
The Network Tools (NETTOOL) function library contains all the sockets-based network services supplied with the NDK, plus a few additional tools designed to aid in the development of network applications.
h3. OS and MiniPrintf Libraries
These libraries form a thin adaptation layer that maps some abstracted OS function calls to SYS/BIOS function calls. This adaptation layer allows the SYS/BIOS system programmer to tune the NDK system to any OS based on SYS/BIOS. This includes Task thread management, memory allocation, packet buffer management, printing, logging, critical sectioning, cache coherency, interrupt management and jumbo packet buffer management.
h3. HAL Libraries
The HAL libraries contain files that interface the hardware peripherals to the NDK. These include timers, LED indicators, Ethernet devices, and serial ports.
h3. NETCTRL Libraries
The NETCTRL or Network Control library can be considered the center of the stack. It controls the interaction between the TCP/IP and the outside world. Of all the stack modules, it is the most important to the operation of the NDK.
h2. Previous NDK Wiki Entry
file:///C:/ti/pdk_C6678_1_1_0_3/packages/ti/platform/docs/platform/platform_library_user_guide.html
Adding NDK support is a pain. Documentation lacks any useful information. Need to find and download the ndk, nsp, pdk(c6678 specific). Unzip these in the ti installation directory.
Then I added the 'Global' Module to SYS/BIOS. This creates lots of errors. Online w\instructions will tell you libraries are missing. Lies. You need to include source code files. Currently I'm trying platform_osal.c and resourcemgr.c. At this point I'm not sure where I got them but they do exist in the ti installation. Either the ndk, nsp, or pdk. Now your project should compile but will no longer run properly. To get the hbeat going again I added the HeapMem mosule. Created an instance called systemHeap with size 131072.
Then I modified the Memory module to use systemHeap as the default Heap instance!
ti.sysbios.heaps.HeapMem.Instance#1 4096
removed this from memory Managment module after adding Heap Memory instance Systemheap and making it much larger)
Current progress:
Call to this function fails. Unfortunately this function doesn't seem to even return with an error. Instead it never returns. Possibly the wrong one is being used but I don't see how it's linked in yet pform_status = platform_init(&sFlags, &sConfig);
Header file for definition C:\ti\pdk_C6678_1_0_0_21\packages\ti\platform
C:\ti\pdk_C6678_1_0_0_21\packages\ti\platform\evmc6678l\platform_lib\src C:\ti\pdk_C6678_1_0_0_21\packages\ti\platform\simc6678\platform_lib\src
When you delete a project in eclipse you get asked if you also want to delete the folder contents. If not, the project folder remains in the workspace folder. You can re-add it with File->Import and then choose General->Existing Project into Workspace.
The library to be included is pdk_C####_#_#_#_#/packages/ti/platform/evmc6678l/platform_lib/lib/debug or release/ti.platform.evm6678l.ae66; Application needs to include the CSL library as well. If you are a RTSC project you can include the CSL libraries in your CFG file by using the following statement: var Csl = xdc.useModule('ti.csl.Settings');. If your are not a RTSC project see the pdk_C####_#_#_#_#/packages/ti/csl/lib directory for the list of libraries to include. You will need the *.ae66 for little endian and *.ae66e for big endian. The library is re-buildable as a CCSv5 project. Just import from the platform_lib directory as an existing CCS project.
Requires newer compiler: https://www-a.ti.com/downloads/sds_support/TICodegenerationTools/download.htm#C6000
To get the NDK stuff moving forward I have: 1) Added the bare minimum module from the SYS BIOS (General) 2) This required adding paramets to the cfg file:
// Load the CSL package
var Csl = xdc.useModule('ti.csl.Settings'); // Load the CPPI package var Cppi = xdc.loadPackage('ti.drv.cppi'); // Load the QMSS package var Qmss = xdc.loadPackage('ti.drv.qmss'); // Load the PA package var Pa = xdc.useModule('ti.drv.pa.Settings');
// Load the Platform/NDK Transport packages
var PlatformLib = xdc.loadPackage('ti.platform.evmc6678l'); var NdkTransport = xdc.loadPackage('ti.transport.ndk');
Some section mapping may need to be done to allow the compilation to fit in memory
These also tie in with the platform library and source files: 3) Added source files from the client_evmc6678l example project: Source code and project files are here: C:\ti\mcsdk_2_01_00_03\examples\ndk\client
client.h client.c(I pulled source code from this file and integrated it with my own main as this is main for the example) platform.h platform_osal.c webpage.c webdata<dir>
default.h dspchip.h logobar.h websample.h default.htm dspchip.gif logobar.gif sample.htm
4) The platform library needs to be modified: C:\ti\pdk_C6678_1_1_0_3\packages\ti\platform\evmc6678l\platform_lib
Import this project into your workspace. It may require a different compiler. Download and install it. At this point the project may physically exist in your workspace but not show up in the project list in CCS. Remedy this by selecting: File->Import->General->'Existing Projects in Workspace' and the project missing. I made a copy of the entire C:\ti\pdk_C6678_1_1_0_3 directory, and work on this one, rather than a copy of just the project directory because links will no longer work and resolving them was a proving to be a nuisance.
5) In the sample project I removed MCSDK PDK TMS32C6678 from the Properties->RTSC->Products and Repositories and replaced it with the copy I created above called: C:\ti\tim_C6678_1_1_0_3\packages Note that the original link doesn't require packages(my be done behind the scenes) but mine requires this extra directory guidance
6) Should be able to now build the platform library and then the sample project
CSL_BootCfgSetSGMIIConfigPLL (0x00000051); //We use 250 Mz: 10x : Instead of -- 0x00000041 312.5 MHz: 8x Init_SGMII(0); instead of Port 1 (verify)
7)Added
CSL_SGMII_setAdvAbility (macPortNum, &sgmiiCfg); //Existing code in Init_SGMII()
//ADDED TIM W CSL_SGMII_disableAutoNegotiation (macPortNum);
8) Platform.c /* This structure holds information about the EMAC port on the platform */
PLATFORM_EMAC_PORT_MODE emac_port_mode[PLATFORM_MAX_EMAC_PORT_NUM] = {
PLATFORM_EMAC_PORT_MODE_PHY, PLATFORM_EMAC_PORT_MODE_NONE //PLATFORM_EMAC_PORT_MODE_AMC, //PLATFORM_EMAC_PORT_MODE_PHY
};
9) Added to platform_init()(normally part of pll flag calls but now forced):
/* Set the PA_SS PLL */ //ADDED THIS status = SetPaPllConfig(); if (status != CSL_SOK) { platform_errno = PLATFORM_ERRNO_PLL_SETUP; return ( (Platform_STATUS) Platform_EFAIL); }
10) In Init_SGMII() swapped the 'if (macPortNum)' sections 0->1 & 1-> 0
h3. The NETCTRL Task Thread
If you are not using XGCONF, your application must create a Task thread that contains a call to ND_NetStart(), which in turn runs the network scheduler function. The NSP example applications provide this thread. SPRU523H–May 2001–Revised February 2012 Network Application Development 51 Submit Documentation Feedback Copyright © 2001–2012, Texas Instruments Incorporated Configuring the NDK with C Code (without XGCONF) www.ti.com This Task thread (called the scheduler thread) is the thread in which nearly all the NETCTRL activity takes place. This thread acts as the program’s entry-point and performs initialization actions. Later, it becomes the NETCTRL scheduler thread. Therefore, control of this thread is not returned to the caller until the stack has been shut down. Application Tasks—network-oriented or otherwise—are not executed within this thread.
h2. NOTES
http://e2e.ti.com/support/embedded/bios/f/355/t/120158.aspx
This issue describes how to use one socket between two tasks. In the NDK, you must use a file descriptor. You must open a session and then share the session data.
Add MDIO info.
Add random notes about rebuilding/ added libs
Bug fixed by removing .config folder: http://e2e.ti.com/support/embedded/tirtos/f/355/t/569964