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 voidNetworkOpen(); static voidNetworkClose(); static voidNetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd ); // Fun reporting function static voidServiceReport( 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_flagssFlags; 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*/ #elsesFlags.phy = 1; /* Ethernet*/ #endifsFlags.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;//软件中断优先级设置为2swiParams.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表示一直等待,直到信号量为1intrc;int i;HANDLEhCfg;QMSS_CFG_Tqmss_cfg;CPPI_CFG_Tcppi_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 bannerplatform_write(VerStr);//// Create and build the system configuration from scratch.//// Create a new configurationhCfg = 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 bannerprintf(VerStr);//// Create and build the system configuration from scratch.//// Create a new configurationhCfg = CfgNew();if( !hCfg ){printf("Unable to create configuration\n");goto main_exit;}// We better validate the length of the supplied namesif( 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;IPNIPTmp;// Setup manual IP addressbzero( &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 1CfgAddEntry( 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 routeCfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );// Manually add the DNS server when specifiedIPTmp = inet_addr(DNSServer);if( IPTmp )CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );}// Else we specify DHCPelse{CI_SERVICE_DHCPC dhcpc;// Specify DHCP Service on IF-1bzero( &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 WARNINGSrc = 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 ConfigurationCfgFree( 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: ");elseprintf("Network Removed: ");// Print a messageIPTmp = 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 specifiedIPTmp = inet_addr(DNSServer);if( IPTmp )CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );} }
Nancy Wang:
通过cfg和xdc脚本配置是一样的。
直接通过代码比较难分析,建议先通过ROV 和 UIA工具看一下程序跑起来之后各线程的执行情况,帮助分析。
processors.wiki.ti.com/…/Runtime_Object_View_(ROV)
www.ti.com/…/spruh43f.pdf
user5032060:
回复 Nancy Wang:
请问有相关的例程可以参考吗?我将两个放在一起就不行,然后这种情况下需要用到信号量吗?