STM32F767ZI Обработка внешних прерываний

Я пытаюсь создать правильный интерфейс ведомого SPI для ADC AD7768-4. АЦП имеет интерфейс SPI, но не выводит преобразования через SPI. Вместо этого есть выходные данные, которые синхронизируются на отдельных выводах GPIO. Таким образом, мне в основном нужно разбивать данные на биты и выводить их в SPI, чтобы получить надлежащий интерфейс ведомого SPI. Пожалуйста, не спрашивайте, почему я так делаю, это было поручено мне.

У меня проблема с прерываниями. Я использую процессор STM32F767ZI - он работает на частоте 216 МГц, и мои данные АЦП ДОЛЖНЫ БЫТЬ синхронизированы на частоте 20 МГц. Я настроил свои NMI, но я не вижу, когда система вызывает или указывает на обработчик прерываний.

Я использовал программное обеспечение STMCubeMX, чтобы назначать контакты и генерировать код настройки, и в stm32F7xx.c файл, он показывает NMI_Handler() функция, но я не вижу указатель на него в системных файлах. Я также нашел пустым HAL_GPIO_EXTI_IRQHandler() функция в STM32F7xx_hal_gpio.c, который, кажется, проверяет, подтвержден ли вывод, и очищает все ожидающие биты, но не сбрасывает флаг прерывания и не проверяет его, и опять же, я не вижу указателя на эту функцию.

Чтобы более тщательно все усложнить, у меня есть 10 тактов, чтобы определить, какой флаг установлен (1 из двух за раз), сбросить его, задать переменную и переместить данные из регистров GPIO. Я считаю, что это возможно, но опять же, я не уверен в том, что делает система, как только прерывание отключается.

Есть ли у кого-нибудь опыт работы с внешними прерываниями на этом процессоре, который мог бы пролить свет на то, как эта конкретная система обрабатывает вещи? Опять же - 10 тактов, чтобы сделать то, что мне нужно... перемещение данных займет у меня всего 1-2 такта, а у меня 8 для обработки прерываний...

РЕДАКТИРОВАТЬ:

Мы изменили частоту DCLK на 5,12 МГц (20,48 МГц MCLK/4), потому что на 2,56 МГц у нас было ровно 12,5 микросекунд для передачи данных и настройки для следующего импульса DRDY, а скорость 80 кГц дает нам ровно нулевой запас. На частоте 5,12 МГц у меня есть 41 такт для запуска процедуры прерывания, которую я могу немного уменьшить, если пропущу проверку второго флага и просто обработаю входящие данные. Но я чувствую, что должен по крайней мере использовать проверку флага DRDY и использовать подпрограмму для включения второго прерывания, иначе я буду постоянно прерывать, потому что DCLK на АЦП всегда работает. Это позволяет мне считать данные 6,12 микросекунды и 6,25 микросекунды, чтобы вытаскивать их до следующего импульса DRDY. Я должен быть в состоянии сделать это на частоте SPI32 МГц (ведомый), но, скорее всего, это будет делать на частоте 50 МГц. Это мой текущий код прерывания:

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); 
          }
   }
}  

Я по-прежнему обеспокоен тактовыми циклами, и я полагаю, что смогу обойтись только проверкой флага DRDY, если я оперирую предположением, что единственный другой флаг EXTI, который сработает, - это тактовый вывод. Хотя я спрашиваю, как это будет работать, если SYS_TICK работает в фоновом режиме... Я должен выяснить.

Мы исследуем более быстрый процессор для обработки битов, но сейчас похоже, что PI3 не сможет справиться с этим, если он работает под управлением Linux, и я не знаю слишком много более быстрых процессоров, которые работают либо очень маленькая надежная ОСРВ, или может быть просто запрограммирована в крайнем случае...

3 ответа

10 тактов, чтобы сделать то, что мне нужно... перемещение данных займет у меня всего 1-2 такта, а у меня останется 8 для обработки прерываний...

Ни за что. Ввод прерывания (проталкивание регистров, выборка вектора и заполнение конвейера) занимает 10-12 циклов даже на Cortex-M7. Затем рассмотрим очень простой обработчик прерываний, просто переместив биты входных данных в буфер и очистив флаг прерывания:

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 инструкций, каждая из которых занимает по крайней мере один цикл после ввода прерывания. Это при условии, что код, векторная таблица и стек находятся в самой быстрой области ОЗУ. Я не уверен, работают ли литералы литералов в ITCM вообще, использование непосредственных литералов добавило бы еще 3 цикла. Забудь это.

Это должно быть решено с помощью оборудования.

Контроллер имеет 6 интерфейсов SPI, выберите 4 из них. соединять DRDY всем четырем NSS булавки, DCLK все SCK булавки, и каждый DOUT прикрепить к одному MISO штырь. Теперь каждый интерфейс SPI обрабатывает один канал и может собирать до 32 бит в своем внутреннем FIFO.

Тогда я бы установил прерывание на переднем крае на одном из NSS булавки (EXTI по-прежнему работает, даже если контакт находится в режиме альтернативной функции), и считывает все данные одновременно.

РЕДАКТИРОВАТЬ

Оказывается, что SPM STM32 требует чрезмерной задержки между NSS падение и SCK повышение, которое AD7768 не обеспечивает, поэтому не будет работать.

Сигма-Дельта интерфейс

STM32F767 имеет периферийное устройство DFSDM, предназначенное для приема данных от внешних АЦП. Он может принимать до 8 каналов последовательных данных с частотой 20 МГц и даже выполнять некоторую предварительную обработку, которая может понадобиться вашему приложению.

Проблема в том, что DFSDM не имеет DRDY На входе я точно не знаю, как можно синхронизировать передачу данных. Это может работать, утверждая START# Singal для сброса связи.

Если это не сработает, вы можете попробовать запустить каналы DFSDM, используя таймер и DMA. соединять DRDY к внешнему триггеру TIM1 или же TIM8 (другие таймеры не будут работать, потому что они подключены к более медленной шине APB1 и другому контроллеру DMA), запустите его на переднем фронте ETRи пусть он генерирует запрос DMA через ~20 нс. Затем позвольте DMA записать значение, необходимое для запуска канала, в регистр конфигурации канала DFSDM. Повторите для трех других каналов.

Есть файл запуска, сгенерированный перед компиляцией: startup_stm32f767xx.s - который содержит все указатели на функции.

Под маркером g_pfnVectors: является .word NMI_Handler указывая на функцию для обработки немаскированных прерываний и двух других указателей, .word EXTI0_IRQHandler а также .word EXTI1_IRQHandler как векторы для внешних обработчиков прерываний. Далее в том же файле находятся следующие директивы компилятора:

.weak      NMI_Handler  
.thumb_set NMI_Handler,Default_Handler

.weak      EXTI0_IRQHandler         
.thumb_set EXTI0_IRQHandler,Default_Handler

.weak      EXTI1_IRQHandler         
.thumb_set EXTI1_IRQHandler,Default_Handler  

Это была информация, которую я искал, чтобы иметь возможность контролировать мои прерывания с большей точностью и меньшим количеством тактов.

Я внимательно прочитал AD7768 DS и обнаружил, что он может передавать данные четырех каналов на один вывод DOUT. Итак, я снова говорю о последовательном аудио интерфейсе (SAI).

Если вы можете снизить DCLK Частота до 2,5 МГц, чем вы можете понизить частоту с соотношением 1:8 (как отношение от 2,5 МГц до 20 МГц) с частотой дискретизации при полной тактовой частоте АЦП.

Если вы направите все 4 канала на один выход DOUT0, вы уменьшите частоту дискретизации только в соотношении 1: 4.

AD7768-4 DS

страница 53

На AD7768 интерфейс может быть настроен для вывода данных преобразования на один, два или восемь выводов DOUTx. Конфигурация DOUTx для AD7768 выбирается с помощью выводов FORMATx (см. Таблицу 33).

страница 66 таблица 34: (для AD7768-4) страница 67 рисунок 98:

FORMAT0 = 1 Все каналы выводятся на вывод DOUT0, на выходе TDM. Используется только DOUT0.

Ты можешь использовать SAI с FS знак равно DRDY и четыре слота, 32 бита / слот

Другие вопросы по тегам