1.我要做的事情是:
通过触发中断(SWI或HWI),使NDK里面的UDP跑起来,实现DSP与PC数据传输。
2.我现在的问题是:
(1)单独跑NDK没有问题,能够实现DSP与PC通信,但是我加了SWI和信号量来触发NDK的StackTest的话,没有成功。
(我的逻辑是,创建两个任务,第一个任务是int StackTest(),作用是配置UDP并实现DSP与PC通信,它里面放了一个等待信号量Semaphore_pend(sem0, BIOS_WAIT_FOREVER),信号量来了才运行; 第二个任务是void fun_enswi0(void),作用是触发软中断,软中断我用的是计数器Swi_dec(swi0),当swi0减了我设定的数就触发软中断; 软中断是void func_swi0(void),作用是释放信号量,这样第一个任务就能运行起来了)
(2)NDK例程里的StackTest是不是和直接用cfg创建的task不一样?
(我是在helloworld例程,也就是在原任务是int StackTest()的基础上添加的task和软中断,我在创建任务时,发现原来的StackTest创建方式是用的xdc而不是cfg方式。)
(3)如果是想通过软中断或者硬中断来触发NDK,实现通信是必须要用到多核吗?
(4)刚学DSP不久的学生,然后这几天急着要用这个,请问有大佬能分享下经验吗,如果能参考一下程序万分感谢!
3.我的主函数程序是:
#include <stdio.h>
#include <ti/ndk/inc/netmain.h>
/* BIOS6 include */
#include <ti/sysbios/BIOS.h>
/*TASK SWI*/
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Swi.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <xdc/runtime/Log.h>
/* Platform utilities include */
#include "ti/platform/platform.h"
#include "ti/platform/resource_mgr.h"
#include "TSC.h"
#include "My_edma.h"
#include "srio_var.h"
#include "KeyStone_common.h"
#include "KeyStone_DDR_Init.h"
#include "ledcommon.h"
/* Platform Information - we will read it form the Platform Library */
platform_info gPlatformInfo;
//---------------------------------------------------------------------------
// Title String
//
char *VerStr = "\nTCP/IP Stack 'Hello World!' Application\n\n";
// Our NETCTRL callback functions
static void NetworkOpen();
static void NetworkClose();
static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd );
// Fun reporting function
static void ServiceReport( uint Item, uint Status, uint Report, HANDLE hCfgEntry );
// External references
extern int dtask_udp_hello();
//---------------------------------------------------------------------------
// Configuration
//
char *HostName = "tidsp";
char *LocalIPAddr = "169.254.198.113";
char *LocalIPMask = "255.255.255.0"; // Not used when using DHCP
char *GatewayIP = "169.254.198.101"; // Not used when using DHCP
char *DomainName = "demo.net"; // Not used when using DHCP
char *DNSServer = "0.0.0.0"; // Used when set to anything but zero
// Simulator EMAC Switch does not handle ALE_LEARN mode, so please configure the
// MAC address of the PC where you want to launch the webpages and initiate PING to NDK */
Uint8 clientMACAddress [6] = {0x00, 0xE1, 0x8C, 0xA4, 0x6C, 0x08}; /* MAC address for my PC */
void EVM_init()
{
platform_init_flags sFlags;
platform_init_config sConfig;
/* Status of the call to initialize the platform */
int32_t pform_status;
/*
* You can choose what to initialize on the platform by setting the following
* flags. Things like the DDR, PLL, etc should have been set by the boot loader.
*/
memset( (void *) &sFlags, 0, sizeof(platform_init_flags));
memset( (void *) &sConfig, 0, sizeof(platform_init_config));
sFlags.pll = 0; /* PLLs for clocking */
sFlags.ddr = 0; /* External memory */
sFlags.tcsl = 1; /* Time stamp counter */
#ifdef _SCBP6618X_
sFlags.phy = 0; /* Ethernet */
#else
sFlags.phy = 1; /* Ethernet */
#endif
sFlags.ecc = 0; /* Memory ECC */
sConfig.pllm = 0; /* Use libraries default clock divisor */
pform_status = platform_init(&sFlags, &sConfig);
/* If we initialized the platform okay */
if (pform_status != Platform_EOK) {
/* Initialization of the platform failed... die */
while (1) {
(void) platform_led(1, PLATFORM_LED_ON, PLATFORM_USER_LED_CLASS);
(void) platform_delay(50000);
(void) platform_led(1, PLATFORM_LED_OFF, PLATFORM_USER_LED_CLASS);
(void) platform_delay(50000);
}
}
}
//---------------------------------------------------------------------
// Main Entry Point Disable all EDMA3 interrupts and events
//---------------------------------------------------------------------
//#pragma DATA_SECTION(SRIO_BUF, ".srio_data")
//MhalMessage_S32 SRIO_BUF;
Swi_Handle swi0;//声明一个全局的SWI句柄*************
Semaphore_Handle sem0;//声明一个全局信号量句柄
Int count = 0;//用来判断stacktest何时开始运行
void fun_enswi0(void);
void func_swi0(void);
int main()
{
//初始化SWI参数
Swi_Params swiParams;
Swi_Params_init(&swiParams);
swiParams.priority = 8;//软件中断优先级设置为2
swiParams.trigger = 2;//设置软件中断计数器
swi0 = Swi_create(func_swi0,&swiParams,NULL);//创建软件中断swi0,func_swi0为软件中断函数
//初始化信号量参数
sem0 = Semaphore_create(0, NULL, NULL);//创建信号量
TSC_init();
BIOS_start();//执行这个就会打开进程StackTest 网口初始化相关
}
//-------------------------------SWI_TASK_LISHIYONG------------------------------------------//
//中断函数
void func_swi0(void){
static int count_swi0 = 0;
printf("swi0 is doing %d\n",count_swi0);
count_swi0++;
Semaphore_post(sem0);//在中断函数里增加一个解锁信号量的函数
}
//触发中断的函数
void fun_enswi0(void)
{
//Int count = 0;
while(count<10)
{
//Semaphore_pend(sem0, BIOS_WAIT_FOREVER); //在任务函数中增加一个等待信号量为1的函数,BIOS_WAIT_FOREVER表示一直等待,直到信号量为1
//printf("Task1 is doing %d\n",count);
Swi_dec(swi0);
//Task_yield();//优先级调度函数,其作用就是如果有相同优先级的任务,则调度到同优先级的其它任务执行!
count++;
}
}
//
// UDP任务,在其中创建了dtask_udp_hello实现通信
//
int StackTest()
{
//printf("StackTest is doing !");
Semaphore_pend(sem0, BIOS_WAIT_FOREVER); //在需要增加互斥信号量的任务函数中增加一个等待信号量为1的函数,BIOS_WAIT_FOREVER表示一直等待,直到信号量为1
int rc;
int i;
HANDLE hCfg;
QMSS_CFG_T qmss_cfg;
CPPI_CFG_T cppi_cfg;
/* Get information about the platform so we can use it in various places */
memset( (void *) &gPlatformInfo, 0, sizeof(platform_info));
(void) platform_get_info(&gPlatformInfo);
(void) platform_uart_init();
(void) platform_uart_set_baudrate(115200);
(void) platform_write_configure(PLATFORM_WRITE_ALL);
/* Clear the state of the User LEDs to OFF */
for (i=0; i < gPlatformInfo.led[PLATFORM_USER_LED_CLASS].count; i++) {
(void) platform_led(i, PLATFORM_LED_OFF, PLATFORM_USER_LED_CLASS);
}
/* Initialize the components required to run this application:
* (1) QMSS
* (2) CPPI
* (3) Packet Accelerator
*/
/* Initialize QMSS */
if (platform_get_coreid() == 0)
{
qmss_cfg.master_core = 1;
}
else
{
qmss_cfg.master_core = 0;
}
qmss_cfg.max_num_desc = MAX_NUM_DESC;
qmss_cfg.desc_size = MAX_DESC_SIZE;
qmss_cfg.mem_region = Qmss_MemRegion_MEMORY_REGION0;
if (res_mgr_init_qmss (&qmss_cfg) != 0)
{
platform_write ("Failed to initialize the QMSS subsystem \n");
goto main_exit;
}
else
{
platform_write ("QMSS successfully initialized \n");
}
/* Initialize CPPI */
if (platform_get_coreid() == 0)
{
cppi_cfg.master_core = 1;
}
else
{
cppi_cfg.master_core = 0;
}
cppi_cfg.dma_num = Cppi_CpDma_PASS_CPDMA;
cppi_cfg.num_tx_queues = NUM_PA_TX_QUEUES;
cppi_cfg.num_rx_channels = NUM_PA_RX_CHANNELS;
if (res_mgr_init_cppi (&cppi_cfg) != 0)
{
platform_write ("Failed to initialize CPPI subsystem \n");
goto main_exit;
}
else
{
platform_write ("CPPI successfully initialized \n");
}
if (res_mgr_init_pass()!= 0) {
platform_write ("Failed to initialize the Packet Accelerator \n");
goto main_exit;
}
else
{
platform_write ("PA successfully initialized \n");
}
//
// THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION before
// using the stack!!
//
rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
if( rc )
{
platform_write("NC_SystemOpen Failed (%d)\n",rc);
for(;;);
}
// Print out our banner
platform_write(VerStr);
//
// Create and build the system configuration from scratch.
//
// Create a new configuration
hCfg = CfgNew();
if( !hCfg )
{
platform_write("Unable to create configuration\n");
goto main_exit;
}
//
// THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!!
//
rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
if( rc )
{
printf("NC_SystemOpen Failed (%d)\n",rc);
for(;;);
}
// Print out our banner
printf(VerStr);
//
// Create and build the system configuration from scratch.
//
// Create a new configuration
hCfg = CfgNew();
if( !hCfg )
{
printf("Unable to create configuration\n");
goto main_exit;
}
// We better validate the length of the supplied names
if( strlen( DomainName ) >= CFG_DOMAIN_MAX ||
strlen( HostName ) >= CFG_HOSTNAME_MAX )
{
printf("Names too long\n");
goto main_exit;
}
// Add our global hostname to hCfg (to be claimed in all connected domains)
CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
strlen(HostName), (UINT8 *)HostName, 0 );
// If the IP address is specified, manually configure IP and Gateway
//#if defined(_SCBP6618X_) || defined(_EVMTCI6614_) || defined(DEVICE_K2H) || defined(DEVICE_K2K)
/* SCBP6618x, EVMTCI6614, EVMK2H, EVMK2K always uses DHCP */
// if (0)
//#else
//if (!platform_get_switch_state(1))
if(1)
//#endif
{
printf("IP address is specified.\n");
CI_IPNET NA;
CI_ROUTE RT;
IPN IPTmp;
// Setup manual IP address
bzero( &NA, sizeof(NA) );
NA.IPAddr = inet_addr(LocalIPAddr);
NA.IPMask = inet_addr(LocalIPMask);
strcpy( NA.Domain, DomainName );
NA.NetType = 0;
// Add the address to interface 1
CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0,
sizeof(CI_IPNET), (UINT8 *)&NA, 0 );
// Add the default gateway. Since it is the default, the
// destination address and mask are both zero (we go ahead
// and show the assignment for clarity).
bzero( &RT, sizeof(RT) );
RT.IPDestAddr = 0;
RT.IPDestMask = 0;
RT.IPGateAddr = inet_addr(GatewayIP);
// Add the route
CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,
sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );
// Manually add the DNS server when specified
IPTmp = inet_addr(DNSServer);
if( IPTmp )
CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
}
// Else we specify DHCP
else
{
CI_SERVICE_DHCPC dhcpc;
// Specify DHCP Service on IF-1
bzero( &dhcpc, sizeof(dhcpc) );
dhcpc.cisargs.Mode = CIS_FLG_IFIDXVALID;
dhcpc.cisargs.IfIdx = 1;
dhcpc.cisargs.pCbSrv = &ServiceReport;
CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
sizeof(dhcpc), (UINT8 *)&dhcpc, 0 );
}
//
// Configure IPStack/OS Options
//
// We don't want to see debug messages less than WARNINGS
rc = DBG_WARN;
CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,
CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
//
// This code sets up the TCP and UDP buffer sizes
// (Note 8192 is actually the default. This code is here to
// illustrate how the buffer and limit sizes are configured.)
//
// UDP Receive limit
//rc = 8192;
rc = 64000;
CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,
CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
//TCP Receive Buffer Size
//rc = 64000;
//CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF,CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
//
// Boot the system using this configuration
//
// We keep booting until the function returns 0. This allows
// us to have a "reboot" command.
//
do
{
rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );
} while( rc > 0 );
// Delete Configuration
CfgFree( hCfg );
printf("TEST END!!!\n");
// Close the OS
main_exit:
NC_SystemClose();
return(0);
}
//
// System Task Code [ Server Daemon Servers ]
//
static HANDLE hHello=0;
//
// NetworkOpen
//
// This function is called after the configuration has booted
//
static void NetworkOpen()
{
// Create our local server 创建一个守护进程 可能是反应堆模式
//hHello = DaemonNew( SOCK_STREAMNC, 0, 7, dtask_udp_hello,
// OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );
//DMA_Init_region(edma_channel_1);
hHello = DaemonNew( SOCK_DGRAM, 0, 7, dtask_udp_hello,
OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );
}
//
// NetworkClose
//
// This function is called when the network is shutting down,
// or when it no longer has any IP addresses assigned to it.
//
static void NetworkClose()
{
DaemonFree( hHello );
}
//
// NetworkIPAddr
//
// This function is called whenever an IP address binding is
// added or removed from the system.
//
static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
{
IPN IPTmp;
if( fAdd )
printf("Network Added: ");
else
printf("Network Removed: ");
// Print a message
IPTmp = ntohl( IPAddr );
printf("If-%d:%d.%d.%d.%d\n", IfIdx,
(UINT8)(IPTmp>>24)&0xFF, (UINT8)(IPTmp>>16)&0xFF,
(UINT8)(IPTmp>>8)&0xFF, (UINT8)IPTmp&0xFF );
}
//
// Service Status Reports
//
// Here's a quick example of using service status updates
//
static char *TaskName[] = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };
static char *ReportStr[] = { "","Running","Updated","Complete","Fault" };
static char *StatusStr[] = { "Disabled","Waiting","IPTerm","Failed","Enabled" };
static void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
{
printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",
TaskName[Item-1], StatusStr[Status],
ReportStr[Report/256], Report&0xFF );
//
// Example of adding to the DHCP configuration space
//
// When using the DHCP client, the client has full control over access
// to the first 256 entries in the CFGTAG_SYSINFO space.
//
// Note that the DHCP client will erase all CFGTAG_SYSINFO tags except
// CFGITEM_DHCP_HOSTNAME. If the application needs to keep manual
// entries in the DHCP tag range, then the code to maintain them should
// be placed here.
//
// Here, we want to manually add a DNS server to the configuration, but
// we can only do it once DHCP has finished its programming.
//
if( Item == CFGITEM_SERVICE_DHCPCLIENT &&
Status == CIS_SRV_STATUS_ENABLED &&
(Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPADD) ||
Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPRENEW)) )
{
IPN IPTmp;
// Manually add the DNS server when specified
IPTmp = inet_addr(DNSServer);
if( IPTmp )
CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
}
}