Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在TI的C2000DSP上移植的问题 #158

Open
mojinpan opened this issue May 21, 2023 · 1 comment
Open

在TI的C2000DSP上移植的问题 #158

mojinpan opened this issue May 21, 2023 · 1 comment

Comments

@mojinpan
Copy link

因为工作的需要用到了TI 的C2000系列DSP(TMS320F28377D),本以为移植shell是简单的事情,实际移植起来发现挺多的问题,在这里分享处理,希望能帮助到其他有类似需求的朋友,也希望作者能改进过来

编译器配置 : CCS12.0 使用eabi模式

  1. 处理导出相关的问题
    先要在链接文件CMD中增加shell的链接信息:
shellCommand : {
_shell_command_start = .;
	*(shellCommand)
	 _shell_command_end = .;
   } > FLASHA_M //flash的位置根据实际情况来确定

然后在代码中修改和编译器相关的内容

#ifndef SHELL_SECTION
    #if defined(__CC_ARM) || defined(__CLANG_ARM)
        #define SHELL_SECTION(x)                __attribute__((used,section(x)))
    #elif defined (__IAR_SYSTEMS_ICC__)
        #define SHELL_SECTION(x)                @ x
    #elif defined(__GNUC__) || defined(__TI_EABI__)
        #define SHELL_SECTION(x)                __attribute__((section(x)))
    #else
        #define SHELL_SECTION(x)
    #endif
#endif

#ifndef SHELL_USED
    #if defined(__CC_ARM) || defined(__CLANG_ARM)
        #define SHELL_USED                      __attribute__((used))
    #elif defined (__IAR_SYSTEMS_ICC__)
        #define SHELL_USED                      __root
    #elif defined(__GNUC__)
        #define SHELL_USED                      __attribute__((used))
    #elif defined(__TI_EABI__)
        #define SHELL_USED                      __attribute__((retain))
    #else
        #define SHELL_USED
    #endif
#endif
void shellInit(Shell *shell, char *buffer, unsigned short size)
{
    shell->parser.length = 0;
    shell->parser.cursor = 0;
    shell->info.user = NULL;
    shell->status.isChecked = 1;

    shell->parser.buffer = buffer;
    shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1);
    
#if SHELL_HISTORY_MAX_NUMBER > 0
    shell->history.offset = 0;
    shell->history.number = 0;
    shell->history.record = 0;
    for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++)
    {
        shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1);
    }
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */

#if SHELL_USING_CMD_EXPORT == 1
    #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
        shell->commandList.base = (ShellCommand *)(&shellCommand$$Base);
        shell->commandList.count = ((uint32_t)(&shellCommand$$Limit)
                                - (uint32_t)(&shellCommand$$Base))
                                / sizeof(ShellCommand);

    #elif defined(__ICCARM__) || defined(__ICCRX__)
        shell->commandList.base = (ShellCommand *)(__section_begin("shellCommand"));
        shell->commandList.count = ((uint32_t)(__section_end("shellCommand"))
                                - (uint32_t)(__section_begin("shellCommand")))
                                / sizeof(ShellCommand);
    #elif defined(__GNUC__) || defined(__TI_EABI__)
        shell->commandList.base = (ShellCommand *)(&_shell_command_start);
        shell->commandList.count = ((uint32_t)(&_shell_command_end)
                                - (uint32_t)(&_shell_command_start))
                                / sizeof(ShellCommand);
    #else
        #error not supported compiler, please use command table mode
    #endif
#else
    shell->commandList.base = (ShellCommand *)shellCommandList;
    shell->commandList.count = shellCommandCount;
#endif

    shellAdd(shell);

    shellSetUser(shell, shellSeekCommand(shell,
                                         SHELL_DEFAULT_USER,
                                         shell->commandList.base,
                                         0));
    shellWritePrompt(shell, 1);
}

  1. 处理数据类型差异

    在DSP上char和int都是16位的,char的差异不影响程序,但是int的差异是影响的,所以需要把所有的int和 unsigned int 都修改为int32_t 或uint32_t,这里建议作者引用stdint.h等头文件,将类型都统一成和编译器无关的类型

  2. 处理代码的兼容性问题

​ TI的编译器不会根据使用情况自动做类型转换,比如你将uint16_t当成uint32_t来使用时,系统不会帮你做强制转换,从而导致代码的错误,这点希望作者能直接在源码中修正.下面列出移植过程中发现的代码问题:

void shellHandler(Shell *shell, char data)
{
    SHELL_ASSERT(data, return);
    SHELL_LOCK(shell);

#if SHELL_LOCK_TIMEOUT > 0
    if (shell->info.user->data.user.password
        && strlen(shell->info.user->data.user.password) != 0
        && SHELL_GET_TICK())
    {
        if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT)
        {
            shell->status.isChecked = 0;
        }
    }
#endif
    /* 根据记录的按键键值计算当前字节在按键键值中的偏移 */
    char keyByteOffset = 24;
    int32_t keyFilter = 0x00000000; //将int改成int32_t
    if ((shell->parser.keyValue & 0x0000FF00) != 0x00000000)
    {
        keyByteOffset = 0;
        keyFilter = 0xFFFFFF00;
    }
    else if ((shell->parser.keyValue & 0x00FF0000) != 0x00000000)
    {
        keyByteOffset = 8;
        keyFilter = 0xFFFF0000;
    }
    else if ((shell->parser.keyValue & 0xFF000000) != 0x00000000)
    {
        keyByteOffset = 16;
        keyFilter = 0xFF000000;
    }
    /* 遍历ShellCommand列表,尝试进行按键键值匹配 */
    ShellCommand *base = (ShellCommand *)shell->commandList.base;
    for (short i = 0; i < shell->commandList.count; i++)
    {
        /* 判断是否是按键定义并验证权限 */
        if (base[i].attr.attrs.type == SHELL_TYPE_KEY
            && shellCheckPermission(shell, &(base[i])) == 0)
        {
            /* 对输入的字节同按键键值进行匹配 */
            if ((base[i].data.key.value & keyFilter) == shell->parser.keyValue
                && (base[i].data.key.value & (0xFFUL << keyByteOffset)) //将oxFF声明为32位
                    == ((uint32_t)data << keyByteOffset)) //将data强制转换为32位
            {
                shell->parser.keyValue |= (uint32_t)data << keyByteOffset;//将data强制转换为32位
                data = 0x00;
                if (keyByteOffset == 0 || (base[i].data.key.value & (0xFFUL << (keyByteOffset - 8)))== 0x00000000)//将oxFF声明为32位
                {
                    if (base[i].data.key.function)
                    {
                        base[i].data.key.function(shell);
                    }
                    shell->parser.keyValue = 0x00000000;
                    break;
                }
            }
        }
    }

    if (data != 0x00)
    {
        shell->parser.keyValue = 0x00000000;
        shellNormalInput(shell, data);
    }

    if (SHELL_GET_TICK())
    {
        shell->info.activeTime = SHELL_GET_TICK();
    }
    SHELL_UNLOCK(shell);
}
@NevermindZZT
Copy link
Owner

感谢您的分享和指正

第一点:各个芯片的编译链都会有一些差异,没办法一次性全部覆盖,如果做了适配,可以提 PR 合入进来的

第二点:一开始做的时候确实是只考虑了 32 位的芯片,后面如果大改会整体处理一下

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants