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.

[参考译文] EK-TM4C123GXL:ISR 的触发次数超过计划

Guru**** 2478765 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/692182/ek-tm4c123gxl-isr-gets-triggered-more-than-planned

器件型号:EK-TM4C123GXL

您好!

我已经编写了一个工作中断驱动的 SSI、用于与 Winbond 闪存通信。 下面是伪代码:

====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

//在主设备和从设备之间传输数据字节

SSI_TRANSSFUSion{

  • 将 SS 拉至低电平
  • SSIIntEnable (SSI0_BASE、SSI_TXFF | SSI_RXFF | SSI_RXTO);
    • 中断应在此处开始发生...
  • while 循环、等待 SS 线路为高电平(一旦 ISR 中的数据事务完成、将被拉高)

// SSI 的中断处理程序

SSI ISR{

检查并保存中断状态、然后将其清除

IF (STATUS &(SSI_RXFF | SSI_RXTO)){

while (1){

继续读取 RX FIFO

如果 RX FIFO 为空、则中断循环

如果接收完所需的数据(RX 字节计数达到0)、禁用 SSI_RXFF

if (已发送和接收所有必需的数据字节){

将 SS 上拉

if (status & SSI_TXFF){

for loop (最多可填充8次 TX FIFO){

如果传输完所需的数据(TX 字节计数达到0)、则禁用 SSI_TXFF

如果 TX FIFO 已满、则中断循环

============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================


我将使用一个示例来说明我的问题、比如我何时要读取的器件 ID 和制造商 ID

Winbond 闪存。 闪存需要主器件发送 WW_READ_ID、后跟3个0x00字节、然后闪存将发送

输出设备 ID +制造商 ID。

下面是一个用于说明传输的图:

XX =无关

   //传输4个数据字节,需要两个字节的设备 id +制造商 id

   TX                                        RX    
   WB_READ_ID                  XX
   0x00                      二十
   0x00                                   XX
   0x00                                   XX

   //主设备需要驱动时钟以允许将 man_id 和 dev_id 移出

   0x00                                   man_id
   0x00                                   DEV_id

为了读取器件 ID +制造商 ID、我的代码将/应该:

  • 标志 SSI_TXFF、因为 TX FIFO 最初为空
  • 进入 ISR (第一次)
  • 加载6个数据字节
    • Wb_read_ID
    • 0x00
    • 0x00
    • 0x00
    • 0x00
    • 0x00
  • TX 计数达到0意味着不再有数据要发送
  • 禁用 TX 中断
  • 离开 ISR

  • 将 SSI_RXFF 标记为从器件已接收到这6个字节并将6个字节发送回主器件
  • 进入 ISR (第二次)
  • 读取 RX FIFO、6个字节
    • 二十
    • 二十
    • 二十
    • 二十
    • man_id
    • DEV_id
  • RX 计数达到0意味着不再接收数据
  • 禁用 RX 中断
  • 将 SS 上拉
  • 离开 ISR

中断等待 SSI_TRANSSOP 输出高电平的 while 环路

程序结束。

大家可以看到、根据我的代码的逻辑、在本例中、我应该只进入 ISR 两次。 时间

我对我的代码进行分步调试(在 ISR 中插入断点)、我能够看到程序恰好进入两次。 但是、

当我执行完整运行时、我会得到3个 ISR 条目、这是怪异的(我插入了一个计数器来保持 ISR 条目计数、我也是如此

尝试切换 GPIO 以使用逻辑分析仪监控 ISR 的进入/退出)。

我对代码或 cortex M4的中断机制有什么不正确的理解吗...等等?

此致、提前感谢您!

Jacky

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的逻辑分析仪图像可以很好地显示正在发生的情况。 第一个中断是因为 TX FIFO 为空。 第二个中断是 RXFF。 当接收 FIFIO 为半满时、该中断发生。 如您所见、它在第四次传输后发生。 在接收到第五个和第六个字节之前、中断例程将占用四个字节的 RX FIFO。 在接收到第五个和第六个字节后、不再接收到字节、一段时间后、您会得到 RX 超时中断。

    如果在闪存中设置命令序列时、您将使用"volatile"全局变量来表示要发送和接收的字节数、则会更好地为您提供服务。 您可能还需要为指向传输缓冲区和接收缓冲区的指针设置全局变量。 最后是接收完成时的"易失性"全局变量(SSI 忙标志)。

    以您的 ID 读取为例、您创建了一个例程来开始传输、将长度(发送和接收的字节数)一个指向 TX 缓冲区的指针和一个指向 RX 缓冲区的指针传递给它。 此函数将全局易失性标志设置为表明 SSI 现在正忙(如果它已经忙、您应该返回错误)、然后它将中断例程 TX 计数初始化为6、 中断 RX 计数到6、中断例程的 TX 缓冲区和 RX 缓冲区指针副本。 然后、它启用 TXFF、RXFF 和 RXTO 中断。

    由于 TX FIFO 为空、所以会发生中断例程。 它加载 TX FIFO、递增指向 TX 缓冲区的指针、递减 TX 计数。 在这种情况下、FIFO 计数在 TXFIFO 满前变为零、因此 TXFF 中断被禁用。 如果要传输的字节数大于8、则中断例程将使能 TXFF 中断。 一旦 TX FIFO 变为半空、您将获得另一个 TXFF 中断、并且中断例程可以将接下来的4个字节填充到 FIFO 中。

    一旦四个值被传输、您就会得到一个 RXFF 中断。 接收例程读取 FIFO 并使用 RX 缓冲器指针存储数据。 它还会减少预期的 RX 计数。 由于只有四个可用值、RX 计数保持为2、中断例程返回时不会禁用中断或清除 SSI 忙标志变量。

    在接收到另外两个字节并且超时时间结束后、您将获得 RXTO 中断。 中断例程读取另外两个字节并将它们存储在 RX 缓冲区的末尾。 它还会递减 RX 计数。 当 RX 计数递减到0时、中断例程将禁用 RXFF 和 RXTO 中断。 它还会清除 SSI 忙标志变量。

    一旦主例程开始传输、它就允许中断处理程序执行所有的工作。 然后主例程可以轮询 SSI 忙标志。 当它变得清晰时、主例程可以读取 RX 缓冲区中的数据。 它还可以启动下一个传输。

    此方法适用于任何大小的数据传输。 FIFO 的使用为中断例程提供了更多的时间来在数据丢失风险之前做出响应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Bob:

    非常感谢您的详细解释。 我还有几件事要澄清。

    在您对分析仪屏幕截图进行解释和进一步分析后、如果我理解正确、 数据将在第一个字节被发送到 TX FIFO 后立即开始传输、即使触发了中断或当前正在发生中断、主器件和从器件之间的数据传输也将持续进行?

    2.使全局计数变量"易失性"的原因是什么? 它们是否会以某种方式得到优化? 如果是、这种情况会发生在哪里?

    谢谢、

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

    为了确保我完全了解中断触发器、下面是另一个显示读取256字节数据的分析器屏幕截图。

    因此、前4个字节0x03 0x00 0x01 0x00是命令/地址字节、这意味着从0x000100的起始地址读取字节。 因为闪存大部分是空的。 大多数返回字节为0xFF。

    因此、由于 TX FIFO 为空、因此会首先触发 TX 中断。 然后、在第3个和第4个数据字节之间发生另一个中断、我认为这同样是 TX 中断、因为第4个数据字节已离开 TX FIFO (MOSI 线路在离开 FIFO 后稍晚获得第4个数据字节) 这会使 TX FIFO 减半或更少、因此 TX FIFO 会再次被填满。 然后、在接收到4个数据字节后立即触发 RX 中断。 然后重复相同的操作,TX,RX 中断... 我的理解是否正确?

    谢谢、

    Jacky

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

    [引用用户="Jacky Wang43"]2. 使全局计数变量"易失性"背后的原因是什么? 它们是否会以某种方式得到优化? 如果是、这种情况会发生在哪里?
    [/报价]

    将变量声明为"volatile"会告知优化器不会消除对该变量的任何读取或写入操作。 当变量在两个不同的线程中使用时、例如在主线程和中断例程中、它可能会意外更改。 如果变量未声明为易失性、例如、优化器可以将变量读取到寄存器一次、然后仅检查寄存器值、而不再次重新读取 RAM 位置。 在极端情况下、如果优化器没有看到某个变量在线程中被"使用"、则它可能完全消除对该变量的所有读取和写入。 这方面的一个典型示例是软件延迟、例如空 for loop:

    对于(i = 0;i < 100;i++);