gpt4 book ai didi

c++ - STM32F767ZI 外部中断处理

转载 作者:太空宇宙 更新时间:2023-11-04 06:49:38 28 4
gpt4 key购买 nike

我正在尝试为 AD7768-4 ADC 创建合适的 SPI 从接口(interface)。 ADC 有一个 SPI 接口(interface),但它不通过 SPI 输出转换。相反,有数据输出在各个 GPIO 引脚上同步输出。所以我基本上需要位爆炸数据,并输出到 SPI 以获得适当的从属 SPI 接口(interface)。请不要问我为什么要这样做,这是分配给我的。

我遇到的问题是中断。我正在使用 STM32F767ZI 处理器 - 它以 216 MHz 运行,我的 ADC 数据必须以 20MHz 时钟输出。我已经设置了我的 NMI,但我没有看到系统调用或指向中断处理程序的位置。

我使用STMCubeMX软件分配引脚并生成设置代码,在stm32F7xx.c文件中,它显示了NMI_Handler()函数,但我没有在系统文件中的任何地方都可以看到指向它的指针。我还在 STM32F7xx_hal_gpio.c 中发现了 void HAL_GPIO_EXTI_IRQHandler() 函数,它似乎检查引脚是否有效,并清除任何未决位,但它不会重置中断标志,或检查它,再次,我没有看到指向此函数的指针。

为了更彻底地使事情复杂化,我有 10 个时钟周期来确定设置了哪个标志(一次两个中的一个),重置它,增加一个变量,并从 GPIO 寄存器移动数据。我相信这是可能的,但同样,我不确定中断被触发后系统正在做什么。

有没有人有在这个处理器上处理外部中断的经验,可以阐明这个特定系统是如何处理事情的?再次 - 10 个时钟周期来完成我需要做的事情......移动数据只需要我 1-2 个时钟周期,剩下 8 个时钟周期来处理中断......

编辑:

我们将 DCLK 速度更改为 5.12 MHz(20.48 MHz MCLK/4),因为在 2.56 MHz 时,我们有恰好 12.5 微秒的时间来传输数据并为下一个 DRDY 脉冲进行设置,而 80 kHz 的速度使我们的余量恰好为零。在 5.12 MHz 时,我有 41 个时钟周期来运行中断例程,如果我跳过检查第二个标志并只处理传入数据,我可以稍微减少。但我觉得我至少必须使用 DRDY 标志检查,并使用例程启用第二个中断,否则我会不断中断,因为 ADC 上的 DCLK 一直在运行。这让我有 6.12 微秒的时间读取数据,并有 6.25 微秒的时间在下一个 DRDY 脉冲之前将其洗牌。我应该能够在 32 MHz SPI 时钟(从)下执行此操作,但很可能会在 50MHz 下执行此操作。这是我当前的中断代码:

void NMI_Handler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
{
count = 0;
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
HAL_GPIO_EXTI_Callback(GPIO_PIN_0);
// __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);

HAL_NVIC_EnableIRQ(GPIO_PIN_1);
}
else
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_1) != RESET)
{
data_pad[count] = GPIOF->IDR;
count++;
if (count == 31)
{
data_send = !data_send;
HAL_NVIC_DisableIRQ(GPIO_PIN_1);
}
__ HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);
HAL_GPIO_EXTI_Callback(GPIO_PIN_1);
// __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);
}
}
}

我仍然担心时钟周期,并且我相信如果我在假设唯一会跳闸的其他 EXTI 标志是针对时钟引脚的情况下操作,我可以只检查 DRDY 标志。尽管我质疑如果 SYS_TICK 在后台运行,这将如何工作……我必须找出答案。

我们正在研究一种更快的处理器来处理位碰撞,但是现在,如果 PI3 运行 Linux,它似乎无法处理它,而且我不知道有太多更快的处理器可以运行非常小的可靠 RTOS,或者可以在紧要关头进行裸机编程...

最佳答案

10 clock cycles to do what I need to... moving data should only take me 1-2 clock cycles, leaving me 8 to handle interrupts...

没办法。即使在 Cortex-M7 上,中断进入(推送寄存器、获取 vector 和填充流水线)也需要 10-12 个周期。然后考虑一个非常简单的中断处理程序,只需将输入数据位移动到缓冲区并清除中断标志:

uint32_t *p;
void handler(void) {
*p++ = GPIOA->IDR;
EXTI->PR = 0x10;
}

它被翻译成这样

handler:
ldr r0, .addr_of_idr // load &GPIOA->IDR
ldr r1, [r0] // load GPIOA->IDR
ldr r2, .addr_ofr_p // load &p
ldr r3, [r2] // load p
str r1, [r3] // store the value from IDR to *p
adds r3, r3, #4 // increment p
str r3, [r2] // store p
ldr r0, .addr_of_pr // load &EXTI->PR
movs r1, #0x10
str r1, [r0] // store 0x10 to EXTI->PR
bx lr
.addr_of_p:
.word p
.addr_of_idr
.word 0x40020010
.addr_of_pr
.word 0x40013C14

所以它是 11 条指令,每条指令至少需要一个周期,中断进入之后。这是假设代码、 vector 表和堆栈都在最快的 RAM 区域中。我不确定文字池是否完全适用于 ITCM,使用立即文字会增加 3 个周期。算了。

这得用硬件来解决。

Controller 有6个SPI接口(interface),选4个。将 DRDY 连接到所有四个 NSS 引脚,将 DCLK 连接到所有 SCK 引脚,并将每个 DOUT 引脚到一个 MISO 引脚。现在每个 SPI 接口(interface)处理一个 channel ,并且可以在其内部 FIFO 中收集多达 32 位。

然后我会在其中一个 NSS 引脚的上升沿设置中断(即使该引脚处于备用功能模式,EXTI 仍然有效),并且一次读取所有数据。

编辑

事实证明,STM32 SPI 在NSS 下降和SCK 上升之间需要过多的延迟,AD7768 不提供,因此它无法工作。

Sigma-Delta 接口(interface)

STM32F767 具有 DFSDM 外设,旨在从外部 ADC 接收数据。它可以接收多达 8 个 channel 的 20 MHz 串行数据,甚至可以执行您的应用程序可能需要的一些预处理。

问题是DFSDM 没有DRDY 输入,我不知道如何同步数据传输。它可能会通过断言 START# 信号来重置通信来工作。

如果这不起作用,那么您可以尝试使用计时器和 DMA 启动 DFSDM channel 。将DRDY连接到TIM1TIM8的外部触发器(其他定时器不会工作,因为它们连接到较慢的APB1总线和其他 DMA Controller ),在 ETR 的上升沿启动它,让它在 ~20 ns 后生成 DMA 请求。然后让DMA将启动 channel 所需的值写入DFSDM channel 配置寄存器。对其他三个 channel 重复上述操作。

关于c++ - STM32F767ZI 外部中断处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53301251/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com