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.

[参考译文] MSP432E401Y:将 MSP432置于低功耗模式、而不是轮询环路

Guru**** 2391415 points
Other Parts Discussed in Thread: MSP432E401Y

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/899761/msp432e401y-putting-msp432-in-low-power-mode-instead-of-polling-loop

器件型号:MSP432E401Y

我使用 MSP432E401Y 通过以太网将多个 ADC 的数据传输到 PC。  数据速率为1kHz。  ADC 在 MSP432上触发中断、其 ISR 通过 SPI 读取数据、然后将数据发送到以太网端口。  读取数据后、MSP432进入软件轮询循环、等待设置信号量。  在 ISR 中设置信号量。  数据收集和传输过程所需的时间不到250us、因此 MSP432在等待循环中花费的时间超过75%。

我想在等待 ADC 中断时将 MSP432置于低功耗模式。  我 没有在 MSP432上使用任何睡眠或低功耗模式、因此我想了解一些有关如何实现这一点的建议。  我在没有 RTOS 的情况下运行、并且正在使用 lwIP 库。

1) 1) Resource Explorer 中是否有任何我可以参考的示例?

2) 2)是否有其他资源可用于展示如何将 MSP432置于低功耗模式并通过外部中断唤醒?

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

    如果始终有一个 ISR 来设置/释放信标、最简单的第一步就是将"__WFI ();"插入轮询循环。 这将显著降低功耗。

    我不记得看到过任何 TI 示例。 MSP432E 系列在低功耗模式下性能较差。 这是休眠模块、您可以减慢时钟速度。 (不过、我认为实际运行以太网需要完整的120MHz。)

    但我们观察到、除了简单的 WFI、电路板电源主要由以太网电路控制、这种电路(除非您的电路板设计考虑了这一点)不能轻易关闭。

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

    Bruce、

    谢谢。  这似乎已经足够简单了、所以我已经尝试了、但看起来 CPU 在中断发生时不会被唤醒。  我甚至尝试 了这里描述的程序 ,但运气不好。  我肯定会错过其他一些东西。  可能无法使用外部 GPIO 中断唤醒 WFI?

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

    不会在 ISR 未执行的情况下唤醒、还是只是从 WFI 中唤醒?

    WFI 定义为在任何中断时唤醒(即使全局禁用中断、有时也会很方便)。 您能否发布您正在使用的序列?

    AppNote 使其听起来很简单、但 SLEEPONEXIT 和 DeepSleep 都应在应用级别进行设计。 我建议一次采取一个步骤。

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

    以下是我的代码的相关部分:

    这是我要进入睡眠状态的循环。  在以下代码之前、我已经配置了外设并注册了 GPIO ISR。  START 命令包含 UDP 封包,由 udpReceive()回调处理。

    PCB = UDP_NEW (); //为传入的主机命令创建新的 UDP 结构
    UDP_recv (PCB、udpReceive、NULL); //将传入的 UDP 数据包与其回调函数相关联
    UDP_BIND (PCB、IP4_ADDR_ANY、UDPPORT); //最后将 PCB 绑定到端口 UDPPORT 上的任何主机
    
    while (!running); //等待主机发出的启动命令
    
    UARTprintf ("已请求启动。\n");
    
    while (正在运行) //直到收到 STOP 命令
    {
    while (!dataReady); //等待 TXbuffer 中的有效数据
    dataReady = false; //清除数据就绪信标
    
    struct pbuf *p = pbuf_alloc (PBUF_transport、sizeof (TXbuffer)、PBUF_RAM);//分配一个新的 pbuf 发送响应
    if (p = NULL){return;}
    
    memcpy (p->payload、TXbuffer、sizeof (TXbuffer));//将响应数据包数据复制到 pbuf 中
    udp_send (PCB、p); //发送响应
    pbuf_free (p); //释放 pbuf
    
    __WFI ();
    } 

    这里是我要从睡眠模式唤醒的 GPIO 的 ISR。  GPIO 由 ADC 的数据就绪输出触发。  我已确认数据就绪以预期的速率切换。

    void adcReadyFxn (uint_least8_t index)
    {
    内部 SPIINDEX = 1;
    uint16_t 校验和= 0;
    int i;
    
    CS_ADC1;
    ADC_DATA (&TXbuffer[SPIindex]); //读取一个 ADC 数据字
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    校验和+= TXbuffer[SPIindex++]; //并添加到校验和
    }
    CS_ADC2;
    ADC_DATA (&TXbuffer[SPIindex]);
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    校验和+= TXbuffer[SPIindex++];
    }
    CS_ADC3;
    ADC_DATA (&TXbuffer[SPIindex]);
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    校验和+= TXbuffer[SPIindex++];
    }
    CS_ADC4;
    ADC_DATA (&TXbuffer[SPIindex]);
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    校验和+= TXbuffer[SPIindex++];
    }
    CS_ADC5;
    // ADC_DATA (&TXbuffer[SPIindex]); //附加 ADC 通道的占位符
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    TXbuffer[SPIindex]= 0x00;
    校验和+= TXbuffer[SPIindex++];
    }
    CS_ADC6;
    // ADC_DATA (&TXbuffer[SPIindex]);
    对于(I = 0;I < ADS1283_DATA_WORDSIZE;I++){
    TXbuffer[SPIindex]= 0x00;
    校验和+= TXbuffer[SPIindex++];
    }
    CS_NONE; //读取所有通道后,禁用所有 CSS
    
    TXbuffer[txBufSize-4]= smplCount; //将采样计数器值插入 TX 缓冲区
    *((uint16_t *)&TXbuffer[txBufSize-3])=校验和;//将校验和插入 TX 缓冲器(两个字节)
    
    smplCount =(smplCount+1)% 256; //递增8位采样计数器(取值256)
    
    dataReady = true; //最后设置数据就绪信标以通知 UDP 发送函数
    }
    
    

    如果我删除了__WFI()语句,它将按预期运行。   使用__WFI()语句,我永远不会从 udp_send()命令中捕获任何数据。

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

    通常情况下、可以将 WFI 置于忙环路中、例如

    > while(!dataReady) __WFI();

    但这并不能解释你的症状,我也不能想到任何其他东西。 看起来您使用的是 TI 驱动程序;我想知道这种驱动程序的功能是否不寻常。  

    您是否相当确定(例如断点) adcReadyFxn 未被调用? 如果您在调试器中暂停、它在哪里执行?

    lwIP 还从 ISR (定时器/以太网)运行。 网络是否正在运行?

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

    我会在忙环路中尝试 WFI、就在忙环路之后、在等待环路的末尾(在上面的代码中)、但这些都不起作用。

    有关使用调试器的好建议。  当我暂停时,它卡在 Default_Handler()例程中。  PSR 异常寄存器表示硬件故障。  NVIC 故障状态表示精确的数据总线错误、总线故障地址寄存器有效。  FAULT_ADDR 寄存器指向标记为"EMAC0_EMAC_DMARIS"的存储器位置、因此很明显 EMAC DMA 中断有问题、但我不确定可能是什么。

    NVIC 挂起寄存器表示 GPIO 端口 N 上有一个挂起的中断、这是 ADC 就绪引脚的连接位置、因此我相信 NVIC 已经看到了外部中断、但很明显、在它处理中断之前、会导致硬件故障。

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

    我认为你的描述使我的神经元着火了。 我这里没有我的材料、但如果你能使用一些模糊的回忆:

    >MAP_IntPrioritySet (INT_EMAC0、ETHERNET_INT_PRIORITY);
    >MAP_IntPrioritySet (FAULT_SysTick、SysTK_INT_PRIORITY);

    enet_lwip.c 示例包含这些行(以及说明)。 我的症状是无法解释的硬故障、显然是从 SysTick 处理程序返回的。 我通过(我认为)将这两个优先级设置为相同的方式来解决这个问题、(我认为)这两个优先级都设置为 SysTick 优先级(即非0)。

    此后不久、我就转而使用 FreeRTOS、它有自己的优先级规则、因此我从未进一步研究过。 无论如何、可能有些东西会被骗。

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

    我在代码中的这两行(以及 GPIO 的附加优先级设置)位于我之前在此线程中复制的段的上方。  我也从 lwIP 示例中获得了它们。  我尝试将所有三个优先级都设置为 SysTick 优先级、并将 EMAC 设置为最高优先级、但并不幸运。

    由于此主题与原始请求的距离很远、您认为我应该发布一个有关 EMAC 中断引起的硬故障的新主题吗(在我先搜索现有解决方案后)?

    更新了: 如果我在"while (running)"语句中设置了一个断点、然后使用 F8在循环中循环、我看不到故障、并且按预期收集数据。  一旦我移除断点、就会出现一个硬故障。

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

    新线程可能更容易引起 True Wizard 的注意。 (抱歉。"这应该很容易。")

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

    谢谢您的帮助。  它让我指向我需要的方向。