Jump to content

    

SPI, DMA, как убрать прерывание транзакции?

 

17 минут назад, _pv сказал:

ну ещё можно сделать костыли, наоборот, в виде выделения дополнительных 4х байт заранее в том буфере откуда данные берутся, потом дописывать перед ними адрес и отправлять всё целиком.

Да, ViKo уже предлагал это выше. Можно, но неудобно.

Share this post


Link to post
Share on other sites

Можно, конечно, повтыкать в RM и, возможно, на монстре из каскадных таймеров и каналов DMA реализовать то, что ТС требуется. Но стоит ли оно того...

 

Например, механизм чтения...

image.thumb.png.61af72e06864b4285cc572ccba8fc81e.png

 

Берутся 2 таймера. Обзовем их TIM1 и TIM2 (к аппаратным блокам TIM1/2 STM32 тут отношения нет).

1. TIM1 настраиваем на режим сравнения с периодом больше времени передачи одной порции (байт?) данных по SPI.

Счетчик повторений TIM1 настраиваем на количество байт управляющих данных для записи.

2. В TIM2 настраиваем общий период переполнения таймера, больший удвоенного времени передачи одной порции данных по SPI.

Один из каналов сравнения (COMPARE 1) настраиваем на период, чуть больший времени передачи одной порции данных по SPI (как в TIM1).

Канал сравнения COMPARE 2 настраиваем на время, чуть меньшее общего периода переполнения TIM2.

Счетчик повторений TIM2 настраиваем на количество желаемых считываемых данных.

TIM2 делаем включаемым по событию UPDATE от TIM1 каскадом (не помню, можно ли так).

Между тем, событие сравнения TIM1 привязываем к одному из каналов DMA, который осуществляет пересылку данных из управляющей структуры в SPI с инкрементом адреса в памяти.

Канал 2 DMA настраиваем на COMPARE 1 TIM2, который будет швырять пустые транзакции записи в SPI (настроить надо без инкремента в памяти).

Канал 3 DMA настраиваем на COMPARE 2 TIM2, который будет швырять пришедшие данные из SPI DR в память (настроить надо с инкрементом адреса буфера в ОЗУ).

3. Запускаем TIM1.

Каждое событие сравнения TIM1 будет формировать DMA-запрос на пересылку данных из структуры управления в SPI.

Как только данных на передачу больше не будет, обнулится счетчик повторений TIM1 и сформируется его событие UPDATE, по которому запустится каскадный таймер TIM2. TIM1 при этом выключится (one pulse mode потому что).

Событие COMPARE 1 толкнет (через DMA) "пустую" передачу по SPI, провоцируя ведомого заполнить постепенно входящий DR SPI-блока STM32. Когда транзакция завершится, подоспеет событие COMPARE 2, по которому входящие данные из SPI DR передадутся в ОЗУ приложения. И так M раз (M - количество данных, записанное в счетчике повторений TIM2). В конце концов, счетчик повторений TIM2 обнулится, возникнет событие UPDATE у этого таймера и он выключится, как и TIM1 однажды.

 

По сути, надо будет заполнить только управляющую структуру, количество данных для чтения и (при предварительно настроенных таймерах, DMA и т.д.) включить TIM1.

Прерывание по UPDATE TIM2 будет сигналом окончания чтения.

Но теперь глянуть бы на возможности по роутингу сигналов DMA-контроллера от блоков таймеров и SPI STM32, чтобы понять, реально ли так сделать...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now