Я пытаюсь создать правильный интерфейс ведомого 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. Я должен быть в состоянии сделать это на частоте SPI 32 МГц (ведомый), но, скорее всего, это будет делать на частоте 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, и я не знаю слишком много более быстрых процессоров, которые работают либо очень маленькая надежная ОСРВ, или может быть просто запрограммирована в крайнем случае …
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.
страница 53
На AD7768 интерфейс может быть настроен для вывода преобразования
данные на одном, двух или восьми выводах DOUTx. Конфигурация DOUTx
для AD7768 выбирается с помощью выводов FORMATx (см. таблицу 33).
стр. 66 таблица 34: (для AD7768-4)
стр. 67, рисунок 98:
FORMAT0 = 1
Все каналы выводятся на вывод DOUT0, на выходе TDM. Используется только DOUT0.
Ты можешь использовать SAI
с FS
знак равно DRDY
и четыре слота, 32 бита / слот