(Надеюсь) упрощенная версия моей проблемы:
Скажем, я использую каждый порт GPIO моего микроконтроллера Cortex M-4, чтобы делать одно и то же, например, читать порт при изменении уровня контактов. Я упростил свой код, чтобы он не зависел от порта, но у меня возникли проблемы с хорошим решением для повторного использования одной и той же функции обработчика прерываний.
- Есть ли способ использовать ту же функцию обработчика прерываний, имея метод определения того, какой порт вызвал прерывание? В идеале некоторые O(1)/не масштабируются в зависимости от количества портов на плате.
- Должен ли я просто иметь разные обработчики для каждого порта, которые вызывают одну и ту же функцию, которая принимает параметр порта? (Лучшее, что я смог придумать до сих пор)
Итак, как:
void worker (uint32_t gpio_id) {
*work goes here*
}
void GPIOA_IRQ_Handler(void) { worker(GPIOA_id); }
void GPIOB_IRQ_Handler(void) { worker(GPIOB_id); }
void GPIOC_IRQ_Handler(void) { worker(GPIOC_id); }
...
Моя актуальная проблема:
Я изучаю и возился с FreeRTOS и создаю простые драйверы для отладки / стандартного UART, некоторые кнопки, которые есть на моем dev. доска и тд. До сих пор я делал драйверы для определенного периферийного устройства/порта.
Теперь я хочу создать драйвер I2C, не зная, какой интерфейс я буду использовать (в моем микроконтроллере 10 портов I2C), и потенциально разрешить использование кода драйвера на нескольких портах одновременно. Я бы знал все порты, используемые во время компиляции.
У меня есть довольно хорошая идея о том, как сделать драйвер независимым от порта, за исключением того, что я зациклен на выяснении хорошего способа найти, какой порт вызвал прерывание, используя единственную функцию-обработчик. (помимо циклического перебора регистра статуса прерывания каждого порта, поскольку это O (n)).
Как я уже сказал, лучшее, что я придумал, это не иметь единого обработчика, а вместо этого иметь разные обработчики в векторной таблице, которые все вызывают в ней одну и ту же рабочую функцию и передают параметр порта. Этот метод загромождает код драйвера, но это O(1) (если вы не принимаете во внимание сложность кода).
- Я делаю все это неправильно и должен просто сделать это простым и глупым и реализовать драйвер в соответствии с портом (ами) / вариантом использования, который мне действительно понадобится, самым простым способом? (даже не планирую использовать несколько шин I2C, хотя было бы интересно реализовать)
Заранее спасибо, надеюсь, пост не будет слишком двусмысленным или длинным (я чувствую, что он довольно длинный, извините).
*handler() { ...}
строки, потому что они предоставляют определенные аргументы и обычно устанавливают векторы. Использование хитрых приемов сборки сделало бы исходный код ужасным в обслуживании. -- Я бы начал с двух обработчиков, каждый из которых реализован в своем собственном обработчике. Затем я разработаю окончательный алгоритм, DMA или что-то еще. Только тогда я бы исследовал, в чем заключаются различия, и рассмотрел бы рефакторинг в смысле DRY. - person the busybee   schedule 03.07.2020