This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/TMS320F28379D:通过集成 driverlib 实现 SYS/BIOS sci Rx 中断

Guru**** 2535750 points
Other Parts Discussed in Thread: C2000WARE, SYSBIOS

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/766316/rtos-tms320f28379d-sys-bios-sci-rx-interrupt-by-integrating-driverlib

器件型号:TMS320F28379D
Thread 中讨论的其他器件:C2000WARESYSBIOS

工具/软件:TI-RTOS

您好!

我想实现一个小型 SYS/BIOS 和 C2000Ware 工程、该工程在控制台中打印 SCI 通信接收到的字符。 我想配置一个 RX SCI 中断。 同时、有2个任务只需通过控制台进行打印、每秒打印一个字符串。 为此、我已将 driverlib 集成到 SYS/BIOS 项目中。 我已经复制了 driverlib sci 回送中断示例中的大部分代码。

我的代码如下:

#include 
#include 
#include 
#include 
#include 

#include "c2000ware/device.h"

#define task_scI_base SCIB_BASE

void Task1 (UARg arg1、UARg arg2);

/*计数器由计时器中断递增*/
易失性 UINT tickCount = 0;

/*
=== main ====
*/
int main()
{
Task_Params task_PRMS;
ERROR_Block EB;

/*
*将"Hello world"打印到日志缓冲区。
*
System_printf ("start\r\n");
system_flush();

ERROR_INIT (&EB);
Task_Params_init (&task_PRM);
Task_PRM.STACKSIZE = 1024;
Task_PRM.priority = 15;
Task_create (Task1、&task_prMS、&EB);

/*
*启动 BIOS。
*开始任务调度。
*
BIOS_start();/*不返回*/
return (0);
}

//
sciaRXFIFOISR - SCIA 接收 FIFO ISR
//
__interrupt void sciRXFIFOISR (void)
{
uint16_t a[10];

SCI_readCharArray (task_sci_BASE、A、1);
A[1]='\0';

System_printf ("a =%s\r\n、a);
system_flush();

SCI_clearOverflowStatus (task_SCI_base);

SCI_clearInterruptStatus (task_SCI_base、SCI_INT_RXFF);

//发出 PIE ACK
interrupt_clearACKGroup (interrupt_ack_group9);
}

void initComms (void){
//
//初始化设备时钟和外设
//
device_init();

//
//通过禁用引脚锁定和启用上拉来设置 GPIO
//
DEVICE_initGPIO();

//
// GPIO28是 SCI Rx 引脚。
//
GPIO_setMasterCore (71、GPIO_CORE_CPU1);
GPIO_setPinConfig (GPIO_71_SCIRXDB);
GPIO_setDirectionMode (71、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (71、GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode (71、GPIO_QUAL_ASYNCx);

//
//初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
//
interrupt_initModule();

//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//
interrupt_initVectorTable();

//
//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
//
interrupt_register (INT_SCIB_RX、sciRXFIFOISR);

//
// 8个字符位,1个停止位,无奇偶校验。 波特率为9600。
//
SCI_setConfig (task_SCI_base、device_LSPCLK_FREQ、115200、(SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE));
SCI_enableModule (task_sci_BASE);
SCI_resetChannels (task_sci_BASE);
SCI_enableFIFO (task_sci_BASE);

//
//启用 RX 和 TX FIFO 中断
//
SCI_enableInterrupt (task_SCI_base、SCI_INT_RXFF);
SCI_disableInterrupt (task_SCI_base、SCI_INT_RXERR);

SCI_setFIFOInterruptLevel (task_SCI_base、SCI_FIFO_TX0、SCI_FIFO_RX1);
SCI_performSoftwareReset (task_sci_BASE);

SCI_resetTxFIFO (task_sci_BASE);
SCI_resetRxFIFO (task_sci_BASE);

#ifdef 自动波特率
//
//执行自动波特率锁定。
// SCI 要求用'A'或'A'来锁定波特率。
//
SCI_lockAutobaud (task_SCI_base);
#endif

INTERRUPT_ENABLE (INT_SCIB_RX);
INTERRUPT_ENABLE (INT_SCIB_TX);

INTERRUPT_clearACKGROUP (INTERRUPT_ACK_group9);

//
//启用全局中断(INTM)和实时中断(DBGM)
//
EINT;
ERTM;
}

空任务2 (UARg arg1、UARg arg2){
initComms();

while (true){
System_printf ("任务2\r\n");
system_flush();

Task_sleep(1000);
}
}

空任务1 (UARg arg1、UARg arg2){
Task_Params task_PRMS;
ERROR_Block EB;

ERROR_INIT (&EB);
Task_Params_init (&task_PRM);
Task_PRM.STACKSIZE = 1024;
Task_PRM.priority = 15;
Task_create (task2、&task_prMS、&EB);

while (true){
System_printf ("任务1\r\n");
system_flush();

Task_sleep(1000);
}
}

问题是、每秒打印一个简单字符串的任务都会在指令时被占用:

Task_sleep (1000); 

如果我评论下一行、它们不会卡住:

initComms(); 

调试时,我检查了 initComms()函数中使其他两个任务不起作用的函数是:

interrupt_initModule(); 

我已经检查了这个函数的代码,接下来的行负责将另外2个任务从 Task_sleep()函数中占用:

IER = 0x0000U;
IFR = 0x0000U; 

我想此 driverlib 代码与我的 app.cfg 有冲突、因此请在下面找到它:

VAR Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory'
) var SysMin = xdc.useModule('xdc.runtime.SysMin');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
VAR Swi = xdc.useModule('ti.sysbios.knl.Swi');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');

var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');

var Boot = xdc.useModule('ti.catalog.c2800.initF2837x.Boot');

//
*取消注释此行以全局禁用断言。
*所有模块继承'库'模块的默认值。 您
*可以使用 Module.common$按模块覆盖这些默认值。
*禁用断言将节省代码空间并提高运行时性能。
Defaults.common$.diags_ASSERT = Diags.always_off;
*/

*
取消注释此行以防止模块名称加载到目标上。
*模块名称字符串放置在.const 段中。 将此
*参数设置为 false 将节省.const 段中的空间。 错误和
*断言消息将包含"未知模块"前缀、而
不是*实际模块名称。
Defaults.common$.namedModule = false;
*/

/*
将系统中的 exit 处理程序数组最小化。 System 模块包括
*一组函数,这些函数在 System_atexit()中注册,
*由 System_exit()调用。
//
System.maxAtexitHandlers = 4;

/*
取消注释此行以禁用错误打印功能。
*禁用时,我们会丢失错误信息,因为
*不打印错误。 如果
*由于 Error_print()函数
*调用 System_printf(),禁用 raiseHook 将节省一些代码空间。
error.raiseHook =空;
*/

/*
取消注释此行以防止*在
目标上加载错误、断言和日志字符串。 这些字符串放置在.const 段中。
*将此参数设置为 false 将节省.const 段中的空间。
*错误、断言和日志消息将打印原始 ID 和 args、而不是
*格式化的消息。
text.isLoaded = false;
*/

/*
取消注释此行以在
程序退出时禁用 SysMin *的字符输出。 SysMin 向循环缓冲区写入字符。
*可以使用 ROV 中的 SysMin Output 视图查看该缓冲器。
SysMin.flushAtExit = false;
*/

/*
BIOS 模块将为系统创建默认堆。
*指定此默认堆的大小。
//
BIOS.heapSize = 0x1000;

//
*从源代码构建自定义 SYS/BIOS 库。
//
BIOS.libType = BIOS.LibType_Custom;

//系统堆栈大小(由 ISR 和 Swi 使用)*/
Program.stack = 0x100;

// System_printf ()的循环缓冲区大小*/
sysmin.bufSize = 0x200;

//
*为整个系统创建并安装记录
器*/
var logerBufParams = 32.creLogerBufParams

;创建和安装 loggerBufParams = 32;创建 loggerBufParfLoggerfParams =新建 LoggerfParams;
Defaults.common$.logger = logger0;
Main.common$.diags_INFO = Diags.always_on;

System.SupportProxy = SysMin;

Boot.configureClocks = true;
boot.configureFlashController = true;
BIOS.cpufreq.lo = 200000000;
Clock.tickPeriod = 1000;
Boot.SYSCLKDIVSEL = 1;
Boot.OSCCLK = 20;
boot.SPLLIMULT = 20;
boot.SPLLFAULT = Boot.Fract_0;
Boot.OSCCLKSRCSEL = Boot.OSCCLK_XTAL;
Boot.DisableWatchdog = true;
Boot.BootFromFlash = true;
boot.configSharedRAM = true;

有人能告诉我正在发生什么情况并向我提出解决方案吗?

提前感谢!

此致、

Adria

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Adria、

    在用于中断的 SYS/BIOS 中、您应该创建一个 Hwi、而不是调用中断驱动程序函数。 SYS/BIOS 将为您处理初始化 PIE 和矢量表。 您是否看过 CCS 中 Resource Explorer (经典)提供的 SYS/BIOS"PIE 中断示例"? 它很好地演示了如何在 C28上配置 Hwi。

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的惠特尼:

    是的、我已经查看过它、但我不知道如何将 Hwi 配置为由 SCI Rx 触发。 我已经使用 driverlib (仅 SCI API、避免像您说过的那样使用中断 API)来实现它、它起作用。

    现在我有两个小问题:

    1.我不能直接从 Hwi ISR 调用 SCI API、这就使我、例如、从 Hwi ISR 发布一个任务正暂挂的事件、然后此任务执行我无法从 Hwi ISR 执行的 SCI 行。 这些行是:

    SCI_clearOverflowStatus (SCI_RX_INTERRUPT_SCI_BASE);
    SCI_clearInterruptStatus (SCI_RX_INTERRUPT_SCI_BASE、SCI_INT_RXFF); 

    2.对于我接收到的每个字节、ISR 被调用两次、我不知道为什么。 请找到我的 SCI 配置代码(使用 driverlib)、看看您是否可以找到原因:

    DEVICE_INIT ();
    Device_initGPIO ();
    GPIO_setMasterCore (71、GPIO_CORE_CPU1);
    GPIO_setPinConfig (GPIO_71_SCIRXDB);
    GPIO_setDirectionMode (71、GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig (71、GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode (71、 GPIO_QUAL_异 步);
    SCI_setConfig (SCIB_BASE、DEVICE_LSPCLK_FREQ、115200、(SCI_CONFIG_WLEN_8 |
    SCI_CONFIG_STOP_ONE |
    SCI_CONFIG_PAR_NONE);
    SCI_enableModule (SCIB_BASE);
    SCI_resetChannels (SCIB_BASE);
    SCI_enableFIFO (SCIB_BASE);
    SCI_enableInterrupt (SCIB_BASE、 SCI_INT_RXFF);
    SCI_setFIFOInterruptLevel (SCIB_BASE、SCI_FIFO_TX0、SCI_FIFO_RX1);
    SCI_performSoftwareReset (SCIB_BASE);
    SCI_resetTxFIFO (SCIB_BASE);
    SCI_resetRxFIFO (SCIB_BASE); 

    并找到我的 Hwi 配置代码:

    ERROR_Block EB;
    Hwi_Params hwi_params;
    
    Hwi_Params_init (&hwi_params);
    hwi_params.arg = 98;
    hwi_params.enableAck = true;
    hwi_params.maskSetting = Hwi_MaskingOption_bitmask;
    hwi_params.disableMask = 0x0;
    hwi_params.restoreMask = 0x0;
    Hwi_create (98、sciRXFIFOISR、 hwi_params、&b); 

    最后、要读取数据、我使用下一个代码:

    while (SCI_FIFO_RX0!= SCI_getRxFIFOStatus (SCIB_BASE)){
    uint16_t byte = SCI_readCharNonBlocking (SCIB_BASE);
    Task_sleep(1);
    } 

    此致、

    Adria

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我发现了为什么每个接收到的字节调用 ISR 两次。 这是因为我首先执行:

    SCI_clearOverflowStatus (SCIB_BASE);
    SCI_clearInterruptStatus (SCIB_BASE、SCI_INT_RXFF); 

    然后我读取字节:

    while (SCI_FIFO_RX0!= SCI_getRxFIFOStatus (SCIB_BASE)){
    uint16_t byte = SCI_readCharNonBlocking (SCIB_BASE);
    Task_sleep(1);
    } 

    如果我只读操作、然后清除溢出状态和中断状态、那么每个接收到的字节都会调用一次 ISR。

    关于无法在 Hwi ISR 中执行 SCI driverlib API 的事实、您能帮我解决吗?

    此致、

    Adria

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    我没有点击"这解决了我的问题"。 那么、您能否将其标记为"未解决"或告诉我如何处理? 我没有看到任何选项可以实现它。

    此致、

    Adria
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Adria、

    您能否澄清您当前与 SYSBIOS 相关的状态? 似乎您做了第一个帖子、然后有些事情可以正常工作、但这是否在 SYSBIOS 环境中?

    如果 Interrupt_initModule()执行以下操作:
    IER = 0x0000U;
    IFR = 0x0000U;

    这显然是一个巨大的问题。 基本上、这就是禁用所有中断并清除任何在系统中已经被标记的中断。 这将撤消 SYSBIOS 本来应该完成的任何中断配置。

    不要在 initComms()中调用这些 API:
    //
    //初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
    //
    interrupt_initModule();

    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //
    interrupt_initVectorTable();

    //
    //此示例中使用的中断被重新映射到
    //此文件中的 ISR 函数。
    //
    interrupt_register (INT_SCIB_RX、sciRXFIFOISR);

    //
    //启用全局中断(INTM)和实时中断(DBGM)
    //
    EINT;
    ERTM;
    ----------------------------------------------------
    床可能可以被称为:

    INTERRUPT_ENABLE (INT_SCIB_RX);
    INTERRUPT_ENABLE (INT_SCIB_TX);

    INTERRUPT_clearACKGROUP (INTERRUPT_ACK_group9);
    ----------------------------------------------------

    initComms 应该在 main()中或在 main()之前调用。

    你需要在你想要使用的中断上创建一个 Hwi (我想你说的中断#28?) 使用函数 sciRXFIFOISR()
    但从函数声明中删除_interrupt 关键字


    犹大

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,犹大,

    感谢您的回答。

    在我的回答中、我标记为"解决我的问题"(这不是目的问题、如果有人告诉我如何撤消或自行撤消问题、我会很感激)、您可以看到我在回答完惠特尼后、如何做您所说的工作。 我删除了对中断模块的所有调用。 然后出现了两个新问题。 其中一个我解决了问题,另一个仍然存在。

    问题是、我无法在 Hwi ISR 内调用任何 SCI (来自 driverlib) API。 这使得我必须从一个与 Hwi ISR 不同的运行环境中调用 SCI API (以读取接收到的字节并清除 SCI 溢出状态和中断标志)。 我现在要做的是在 Hwi ISR 内发布一个事件、该事件会唤醒一个执行 SCI 操作的任务。 但是、如果我需要在 Hwi ISR 上下文中执行这些操作、该怎么办呢? 我该怎么做?

    此致、

    Adria

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在 Hwi 函数中调用 SCI 驱动程序应该没有任何错误。 您为什么说不能? 您尝试时是否遇到错误?

    关于帖子的已解决状态、我不知道如何撤消-我将需要询问一些专家以了解是否有办法。 该主题仍被视为打开、因为您继续回复它、所以它仍在我的支持队列中。

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Adria、

    感谢您的说明...好的,我看到您现在在哪里。

    您可以尝试的一件事是...从代码中删除这3行。 我不知道为什么你这么做、但这3行
    当您处理这个中断时、您已经打开了所有中断来抢占它、包括您自己。 通常是中断
    应该在运行时自行设置(这是默认的 BIOS 行为、如果删除这3行、则应该会发生此情况)。

    Hwi_params.maskSetting = Hwi_MaskingOption_bitmask;
    Hwi_params.disableMask = 0x0;
    Hwi_params.restoreMask = 0x0;

    您应该使用的另一条线是确认线。 如果您在 ISR 中确认中断
    您可能不需要此行。

    Hwi_params.enableAck = true;

    我是第二个 Whitney、SCI 驱动程序 API 应该可以从您的 BIOS ISR 调用。 我不知道这些 API 到底在做什么、但是
    通常、驱动程序 API 会配置硬件的寄存器、不会与通用芯片中断内容混淆
    BIOS 正在做什么。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    我再次尝试从 Hwi 中调用 SCI API、现在我没有问题。 我想、当我遇到更多错误时(在这个线程的开头)、我只是通过从 Hwi 中删除 SCI 代码并将其添加到另一个任务中来使其工作。 在所有其他错误都被解决后、我仍然认为 Hwi 中的 SCI 代码是一个问题。

    感谢大家!

    此致、

    Adria
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很高兴听到这个消息! 问题现在是否已完全解决? 我可以闭合线程吗?

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的惠特尼:

    当然!

    Adria