程序调用延迟-C&;Linux

程序调用延迟-C&;Linux,c,linux,beagleboneblack,C,Linux,Beagleboneblack,我正在为主动假肢设计新的硬件。我的系统有一台BeagleBone Black RevC嵌入式计算机和一些定制板。BeagleBone Black(BBB)运行Debian Linux 我编写了一个C控制台应用程序来与Linux上的其他板进行对话。从终端,我可以发送“/plan execute_1 set_pid_gains 10 50 0”之类的命令,以更改在我的电机驱动器上运行的控制回路的增益。“plan”函数是用C编写的。它通过SPI发送消息 程序本身运行良好,我可以发送我想要的所有命令。然

我正在为主动假肢设计新的硬件。我的系统有一台BeagleBone Black RevC嵌入式计算机和一些定制板。BeagleBone Black(BBB)运行Debian Linux

我编写了一个C控制台应用程序来与Linux上的其他板进行对话。从终端,我可以发送“/plan execute_1 set_pid_gains 10 50 0”之类的命令,以更改在我的电机驱动器上运行的控制回路的增益。“plan”函数是用C编写的。它通过SPI发送消息

程序本身运行良好,我可以发送我想要的所有命令。然而,当我们开始从Python测试它时(使用Popen调用C程序),我们意识到它的执行速度没有我们想要的那么快

为了复制和隔离问题,我编写了一个shell脚本(fxa_test_z_1),在我的网络上发送3个命令:

#!/bin/bash
# Places FlexSEA in Impedance control mode
# Use with care!

# Set control mode to 'z' (4)
./plan execute_1 set_control 4

# Current loop gains:
./plan execute_1 set_current_gains 10 50 0

# Choose from one of these:
./plan execute_1 set_z_gains 1 0 0
echo "FlexSEA in Stiffness mode"
每个功能之间有14毫秒的延迟(用示波器测量)。我做了许多小实验来解决这个问题。打开和关闭SPI端口、发送SPI命令以及解析agv[]都不是问题所在。如果我在同一个程序调用中多次调用它们,则每个串行数据包之间的延迟约为700us

调用“nice-n-19./fxa_test_z_1”并没有改变任何事情

==

我可以做些什么来加快这些函数调用的速度?我能让他们去吗

现在我正试图避免对代码进行重大修改,因为我们希望明天测试我们的控制循环

谢谢


Jeff

在再次运行之前,您可以让
计划
做更多的工作,从而加快运行速度。开始一个过程需要做很多工作,所以你不想做得太频繁

要让
plan
做更多的工作,您可以在stdin上或从文件中向其提供命令列表。然后,棘手的部分是解析每一行以提取单独的命令和参数。由于您现有的代码已经从argv读取命令,因此使用
strtok
将命令解析为类似argv的数组非常容易:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_COMMAND_LEN 256
#define MAX_ARGS 64
char *fake_argv[MAX_ARGS];  /* For compatibility with existing parser. */
const char *delims = " \n";

int main(int argc, char *argv[])
{
    char command[MAX_COMMAND_LEN];

    while( fgets(command, sizeof(command), stdin) )
    {
        int fake_argc = 0;
        fake_argv[fake_argc] = strtok(command, delims);
        while( fake_argv[fake_argc] != NULL )
        {
            fake_argv[++fake_argc] = strtok(NULL, delims);      
        }

        { int i;  /* debug print... you can remove this block */
          printf("Handling command: [%s], argc %d\n", command, fake_argc);
          for( i = 0; i < fake_argc; ++i ) { printf("  arg: [%s]\n", fake_argv[i]); }
        }
        /* ... do the stuff you were already doing except now with fake_argv */
    }

    return 0;
}
#包括
#包括
#包括
#定义最大命令长度256
#定义最大参数64
字符*伪字符[最大字符];/*与现有解析器兼容*/
常量字符*delims=“\n”;
int main(int argc,char*argv[])
{
char命令[MAX_command_LEN];
while(fgets(command,sizeof(command),stdin))
{
int伪_argc=0;
fake_argv[fake_argc]=strtok(命令,delims);
while(fake_argv[fake_argc]!=NULL)
{
假_argv[++假_argc]=strtok(NULL,delims);
}
{int i;/*调试打印…您可以删除此块*/
printf(“处理命令:[%s],argc%d\n”,命令,伪argc);
对于(i=0;i
然后,bash脚本可以是一组输入程序的行:

./plan << END_COMMAND_LIST
execute_1 set_control 4
execute_1 set_current_gains 10 50 0
execute_1 set_z_gains 1 0 0
END_COMMAND_LIST

/plan我将indiv的代码与main()合并,它可以正常工作,我可以每760us发送一次新命令(比以前快18倍!)

我的代码可能不那么优雅,但其他人可能会从一个完整的解决方案中受益,因此:

//****************************************************************************
// main: FlexSEA Plan project: console app to control FlexSEA slaves
//****************************************************************************

//****************************************************************************
// Include(s)
//****************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/flexsea_console.h"
#include "../inc/plan_spi.h"
#include "flexsea_local.h"

//****************************************************************************
// Local variable(s) & definitions
//****************************************************************************

int analog0 = 0;

//Choose between single multiple commands console app:
//#define SINGLE_COMMAND
#define MULTIPLE_COMMANDS

#ifdef SINGLE_COMMAND
    #ifdef MULTIPLE_COMMANDS
        #error "Pick one Command option!"
    #endif
#endif


#define MAX_COMMAND_LEN 256
#define MAX_ARGS 8
char *fake_argv[MAX_ARGS];
const char *delims = " \n";

//****************************************************************************
// External variable(s)
//****************************************************************************

extern unsigned char execute_1_data[];

//****************************************************************************
// Function(s)
//****************************************************************************

int main(int argc, char *argv[])
{
    #ifdef MULTIPLE_COMMANDS
    char command[MAX_COMMAND_LEN];
    char string1[20], string2[20] = "quit";
    char default_argv[] = "";
    int i = 0;
    #endif  //MULTIPLE_COMMANDS

    //Open SPI:
    flexsea_spi_open();

    #ifdef MULTIPLE_COMMANDS
    while(fgets(command, sizeof(command), stdin))
    {
        int fake_argc = 1;

        //Fills fake_argv with empty strings to avoid sending old values with new commands
        for(i = 0; i < MAX_ARGS; i++)
        {
            fake_argv[i] = default_argv;
        }

        //First argument
        fake_argv[fake_argc] = strtok(command, delims);

        //Other arguments
        while( fake_argv[fake_argc] != NULL )
        {
            fake_argv[++fake_argc] = strtok(NULL, delims);
        }

        //Enable for terminal debug only:
        /*
        for(i = 0; i < MAX_ARGS; i++)
        {
            printf("fake_argv[%i] = %s\n", i, fake_argv[i]);
        }
        */

        //Do we want to exit? (exit when "quit" is received)
        strcpy(string1, fake_argv[1]);
        if(!strcmp(string1, string2))
        {
            printf("Quitting.\n");
            break;
        }
        else
        {
            //Parser for console commands:
            flexsea_console_parser(fake_argc, fake_argv);

            //Can we decode what we received?
            decode_spi_rx();
        }
    }
    #endif  //MULTIPLE_COMMANDS

    #ifdef SINGLE_COMMAND

    //Parser for console commands:
    flexsea_console_parser(argc, argv);

    //Can we decode what we received?
    decode_spi_rx();

    #endif  //SINGLE_COMMAND

    //Close SPI:
    flexsea_spi_close();

    return 0;
}
//****************************************************************************
//主:FlexSEA计划项目:控制台应用程序控制FlexSEA从机
//****************************************************************************
//****************************************************************************
//包括
//****************************************************************************
#包括
#包括
#包括
#包括“./inc/flexsea_console.h”
#包括“./inc/plan_spi.h”
#包括“flexsea_local.h”
//****************************************************************************
//局部变量和定义
//****************************************************************************
int=0=0;
//在控制台应用程序的单个和多个命令之间进行选择:
//#定义单个命令
#定义多个_命令
#ifdef单_命令
#ifdef多个_命令
#错误“选择一个命令选项!”
#恩迪夫
#恩迪夫
#定义最大命令长度256
#定义最大参数8
char*fake_argv[MAX_ARGS];
常量字符*delims=“\n”;
//****************************************************************************
//外部变量
//****************************************************************************
extern无符号字符执行_1_数据[];
//****************************************************************************
//职能
//****************************************************************************
int main(int argc,char*argv[])
{
#ifdef多个_命令
char命令[MAX_command_LEN];
char string1[20],string2[20]=“退出”;
字符默认值_argv[]=“”;
int i=0;
#endif//多个_命令
//开放SPI:
flexsea_spi_open();
#ifdef多个_命令
while(fgets(command,sizeof(command),stdin))
{
int伪_argc=1;
//用空字符串填充伪_argv,以避免用新命令发送旧值
对于(i=0;i#!/bin/bash
# How quickly can we send serial commands?

./plan << END_COMMAND_LIST
execute_1 set_leds 0 255 0 0
execute_1 set_leds 0 255 0 0
execute_1 set_leds 0 255 0 0
execute_1 set_leds 0 255 0 0
execute_1 set_leds 0 255 0 0
END_COMMAND_LIST