Перейти к содержанию
    

Dandula

Свой
  • Постов

    86
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Dandula

  • Звание
    Частый гость
    Частый гость

Контакты

  • Сайт
    Array
  • ICQ
    Array
  1. Написал тестовую программку под STM32F0Discovery, чтобы проверить метод. Возможно кому-то поможет с настройкой. Пины платы PA8 и PA9, PA10 и PA11 попарно соединены джамперами. На пинах PA8 и PA10 ловлю фронты таймером TIM1 (1 и 3 каналы таймера соответственно). Пины PA10 и PA11 вручную устанавливаю/сбрасываю. По захвату на каждом из каналов DMA копирует младший или старший байт порта GPIOB (в зависимости от "сработавшего" канала) в старший байт порта GPIOC. В младшем и старшем байтах порта GPIOB записаны такие значения, при копировании которых загорается синий или зеленый светодиоды. #include "stm32f0xx.h" #include <stdint.h> int main(void) { //uint8_t port = 0x01; RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_DMA1EN; RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9; GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9); GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9); GPIOC->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0; GPIOA->AFR[1] |= (2 << ((8 - 8) << 2)) | (2 << ((10 - 8) << 2)); GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 | GPIO_OSPEEDER_OSPEEDR11; GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10 | GPIO_OTYPER_OT_11); GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10 | GPIO_PUPDR_PUPDR11); GPIOA->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_0; DMA1_Channel2->CNDTR = 1; DMA1_Channel2->CPAR = (uint32_t)&GPIOC->ODR + 1; DMA1_Channel2->CMAR = (uint32_t)&GPIOB->ODR; DMA1_Channel2->CCR |= DMA_CCR_EN | DMA_CCR_DIR | DMA_CCR_CIRC | DMA_CCR_PL ; // из CMAR в CPAR, циклическая передача, размер данных - 8 бит DMA1_Channel5->CNDTR = 1; DMA1_Channel5->CPAR = (uint32_t)&GPIOC->ODR + 1; DMA1_Channel5->CMAR = (uint32_t)&GPIOB->ODR + 1; DMA1_Channel5->CCR |= DMA_CCR_EN | DMA_CCR_DIR | DMA_CCR_CIRC | DMA_CCR_PL; // из CMAR в CPAR, циклическая передача, размер данных - 8 бит TIM1->CCMR1 |= TIM_CCMR1_CC1S_0; // Настраиваем канал 1 на вход без ремапа, фильтр отключен TIM1->CCMR2 |= TIM_CCMR2_CC3S_0; // Настраиваем канал 3 на вход без ремапа, фильтр отключен TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC3E; // Настраиваем каналы 1 и 3 на захват фронта и включаем их TIM1->DIER |= TIM_DIER_CC1DE | TIM_DIER_CC3DE; // Захваты по каналам 1 и 3 сгенерируют запросы DMA GPIOB->ODR = 0x0102; for(;;) { GPIOA->BSRR = GPIO_BSRR_BR_11 | GPIO_BSRR_BS_9; for (int i = 0; i < 500; i++) __NOP(); GPIOA->BSRR = GPIO_BSRR_BR_9 | GPIO_BSRR_BS_11; for (int i = 0; i < 500; i++) __NOP(); } }
  2. Я имел в виду немного другое. Как задается задается тип события, по которому возникает запрос DMA? Т.е как задается, что нужно реагировать на изменение уровня на канале, а не скажем на Update Event таймера? То, что разные каналы разных таймеров закреплены за разными каналами DMA в курсе. В любом случае спасибо! :rolleyes:
  3. А как в данном случае DMA понимает, что транзакцию нужно запускать по фронту/спаду на заданном канале а не по какому-либо другому событию таймера?
  4. Можете показать пример кода? Кстати, а вообще допустимо ли с одного в/в в другой пихать или обязательно нужен промежуточный буфер?
  5. Здравствуйте! Собственно, возможно ли в STM32F0 запустить передачу посредством DMA по фронту/спаду сигнала на одном из выходов МК? Если да, то как в таком случае необходимо сконфигурировать МК? EXTI не годится. Как оценить время реакции (время между фронтом внешнего сигнала и началом передачи контроллером DMA)? Посредством DMA будут передаваться данные с одного порта в/в на другой.
  6. На сколько я понял PUBLIC - это аналог EXPORT и GLOBAL, но из других компиляторов. Потому как в Keil его нет. Чтобы показать линковщику откуда брать код, нужно либо прототип функции указать с директивой EXTERN, либо определение функции с директивой GLOBAL. Так? Startup-файл с прототипом функции-обработчика прерывания я трогать не хочу. Вот и указываю определение с директивой EXPORT (она же GLOBAL). Обработчик сейчас и так в отдельном файле. С табличными переходами логика понятна. Спасибо!
  7. Буду иметь в виду, перенесу сброс флага ближе к началу обработчика. Однако в функции EXTI_ClearITPendingBit() из STM32F0xx SPL этих инструкций нет. И доках от ST об этом тоже ничего.
  8. Тут случай особый. Это функция-обработчик прерывания. И её прототип указывается в ASM-файле начальной инициализации, который трогать нежелательно. Поэтому в определении функции необходимо директива EXPORT или её синоним GLOBAL. В моей ситуации необходимо как можно быстрее после входа в обработчик считать регистр порта в/в. Но в любом случае, это лишнее. Сброс флага внешнего прерывания нормально отрабатывает и непосредственно перед выходом из обработчика. Написал обработчик на ASMе. Время входа в прерывание удалось сократить до 500 нс. Этого пока достаточно. Как сделать табличные переходы не соображу. Вот, что получилось: EXTI_BASE EQU 0x40010400 GPIOA_BASE EQU 0x48000000 GPIOB_BASE EQU 0x48000400 GPIOC_BASE EQU 0x48000800 EXTI_PR_OFFSET EQU 0x14 GPIO_IDR_OFFSET EQU 0x10 GPIO_BSRR_OFFSET EQU 0x18 GPIO_BRR_OFFSET EQU 0x28 MACRO asmexti_exit LDR r0, =EXTI_BASE ; загрузить в регистр r0 адрес модуля EXTI MOVS r1, #0x01 ; загрузить в регистр r1 значение 0x01 LSLS r1, #8 ; логический сдвиг влево на 8 бит значения в регистре r1 STR r1, [r0, #EXTI_PR_OFFSET] ; сохранить слово из регистра r1 в регистр EXTI->PR BX lr ; возврат из функции ALIGN MEND AREA ASMEXTI, CODE, READONLY EXTI4_15_IRQHandler PROC EXPORT EXTI4_15_IRQHandler LDR r0, =GPIOC_BASE ; загрузить в регистр r0 адрес порта GPIOC LDRH r0, [r0, #GPIO_IDR_OFFSET] ; загрузить в регистр r0 полуслово из регистра GPIOC->IDR LSRS r1, r0, #9 ; логический сдвиг вправо на 9 бит значения в регистре r0 и сохранение результата в регистр r1 MOVS r2, #0x0B ; загрузить в регистр r2 значение 0x0B ANDS r1, r2 ; побитовое И регистра r1 с регистром r2 CMP r1, #0x02 ; сравнить вычитанием из регистра r1 значения 0x02 BEQ C ; условный переход на метку C, если результат операции нулевой CMP r1, #0x00 ; сравнить вычитанием из регистра r1 значения 0x00 BEQ A ; условный переход на метку A, если результат операции нулевой CMP r1, #0x01 ; сравнить вычитанием из регистра r1 значения 0x01 BEQ B ; условный переход на метку B, если результат операции нулевой asmexti_exit A MOVS r1, #0xFF ; загрузить в регистр r1 значение 0xFF ANDS r0, r1 ; побитовое И регистра r0 с регистром r1 LSLS r1, #16 ; логический сдвиг влево на 16 бит значения в регистре r1 ORRS r0, r1 ; побитовое ИЛИ регистра r0 с регистром r1 LDR r2, =GPIOA_BASE ; загрузить в регистр r2 адрес порта GPIOA STR r0, [r2, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r0 в регистр GPIOA->BSRR asmexti_exit B MOVS r1, #0x60 ; загрузить в регистр r1 значение 0x60 ANDS r0, r1 ; побитовое И регистра r0 с регистром r1 LSLS r1, #16 ; логический сдвиг влево на 16 бит значения в регистре r1 ORRS r0, r1 ; побитовое ИЛИ регистра r0 с регистром r1 LDR r2, =GPIOB_BASE ; загрузить в регистр r2 адрес порта GPIOB STR r0, [r2, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r0 в регистр GPIOB->BSRR asmexti_exit C MOVS r1, #0x0F ; загрузить в регистр r1 значение 0x0F LSLS r2, r1, #4 ; логический сдвиг влево на 4 бита значения в регистре r1 и сохранение результата в регистр r2 ANDS r2, r0 ; побитовое И регистра r2 с регистром r0 LSLS r2, #4 ; логический сдвиг влево на 4 бита значения в регистре r2 LSLS r3, r1, #24 ; логический сдвиг влево на 24 бита значения в регистре r0 и сохранение результата в регистр r3 ORRS r2, r3 ; побитовое ИЛИ регистра r2 с регистром r3 LDR r3, =GPIOA_BASE ; загрузить в регистр r2 адрес порта GPIOA STR r2, [r3, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r2 в регистр GPIOA->BSRR ANDS r0, r1 ; побитовое И регистра r0 с регистром r1 LSLS r0, #8 ; логический сдвиг влево на 8 бит значения в регистре r0 LSLS r2, r1, #24 ; логический сдвиг влево на 24 бита значения в регистре r0 и сохранение результата в регистр r3 ORRS r0, r2 ; побитовое ИЛИ регистра r0 с регистром r2 LDR r1, =GPIOB_BASE ; загрузить в регистр r1 адрес порта GPIOB STR r0, [r1, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r0 в регистр GPIOB->BSRR asmexti_exit ENDP END
  9. Что-то я подобного не замечал. Написал то же самое на Си и скомпилировал, никакие дополнительные регистры не стекируются (только те, что автоматом). При этом в полученном коде инструкция BX следует сразу за STR.
  10. В Reference manual сказано так: "The prefetch buffer is 3 blocks wide where each block consists of 4 bytes." Видимо как раз те самые 32 бита. В STM32F0 кэша точно нет. Тут типа намекают, что адреса переходов лучше делать кратными 8 байтам: "The implementation of this prefetch buffer makes a faster CPU execution possible as the CPU fetches one word at a time with the next word readily available in the prefetch buffer. This implies that the acceleration ratio will be of the order of 2 assuming that the code is aligned at a 64-bit boundary for the jumps." ОК, как слеплю окончательный код, выложу на суд. Пока разобрался как задействовать код из asm-файла. Не хватало всего одной директивы: EXPORT EXTI4_15_IRQHandler Очень помогло: Mixing C, C++, and Assembly Language Вот, целиком в текущем виде: EXTI_BASE EQU 0x40010400 GPIOA_BASE EQU 0x48000000 GPIOB_BASE EQU 0x48000400 GPIOC_BASE EQU 0x48000800 EXTI_PR_OFFSET EQU 0x14 GPIO_IDR_OFFSET EQU 0x10 GPIO_BSRR_OFFSET EQU 0x18 AREA ASMEXTI, CODE, READONLY EXTI4_15_IRQHandler PROC EXPORT EXTI4_15_IRQHandler LDR r0, =GPIOB_BASE ; загрузить в регистр r0 адрес порта GPIOB MOVS r1, #0x01 ; копировать в регистр r1 значение 0x01 LSLS r2, r1, #12 ; логический сдвиг влево на 12 бит значения в регистре r1 и сохранение результата в регистр r2 STR r2, [r0, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r2 в регистр GPIOB->BSRR LDR r0, =EXTI_BASE ; загрузить в регистр r0 адрес модуля EXTI LSLS r1, #8 ; логический сдвиг влево на 8 бит значения в регистре r1 STR r1, [r0, #EXTI_PR_OFFSET] ; сохранить слово из регистра r1 в регистр EXTI->PR BX lr ENDP END
  11. При текущей частоте задержка флэш составляет 1 Wait State. Это значит что при выполнении кода из флеша к длительности всех команд можно добавить 1 машинный цикл? Как оценить на сколько в такой ситуации ускоряет выполнение буфер предварительной выборки? Задержка доступа к периферии определяется исключительно частотой шины, на которой она сидит, и собственными предделителями конкретной периферии? Или есть еще влияющие факторы? Спасибо за ссылку! Фейспалм мне, что ненагуглил эту тему раньше. Написал в отдельном файле простой обработчик, который для начала будет просто устанавливать пин в единицу и сбрасывать флаг прерывания. Среда компилирует файл. Но не могу понять как задействовать его в основной программе? EXTI_BASE EQU 0x40010400 GPIOA_BASE EQU 0x48000000 GPIOB_BASE EQU 0x48000400 GPIOC_BASE EQU 0x48000800 EXTI_PR_OFFSET EQU 0x14 GPIO_IDR_OFFSET EQU 0x10 GPIO_BSRR_OFFSET EQU 0x18 AREA EXTI, CODE, READONLY EXTI4_15_IRQHandler PROC LDR r0, =GPIOB_BASE ; загрузить в регистр r0 адрес порта GPIOB MOVS r1, #0x01 ; копировать в регистр r1 значение 0x01 LSLS r2, r1, #12 ; логический сдвиг влево на 12 бит значения в регистре r1 и сохранение результата в регистр r2 STR r2, [r0, #GPIO_BSRR_OFFSET] ; сохранить слово из регистра r2 в регистр GPIOB->BSRR LDR r0, =EXTI_BASE ; загрузить в регистр r0 адрес модуля EXTI LSLS r1, #8 ; логический сдвиг влево на 8 бит значения в регистре r1 STR r1, [r0, #EXTI_PR_OFFSET] ; сохранить слово из регистра r1 в регистр EXTI->PR BX LR ENDP END
  12. Описание команд там есть. По нем и разбираюсь. Но где указана длительность не заметил. Можете тыкнуть носом? :laughing:
  13. if (!(db & (0x01 << 12))) необходима, чтобы в случае невыполнения условия, как можно быстрее выйти из прерывания. Да, Вы правы. Осталась после предыдущих версий кода. Сейчас не нужна. Но на сколько я могу судить, компилятор ее проигнорировал (в дизассемблере ее не нашел, обычное считывание регистра). Сейчас и из Си убрал. Остальное переделал: 68: { 0x08000240 B410 PUSH {r4} 69: uint_fast16_t db = GPIOC->IDR; 70: 0x08000242 4819 LDR r0,[pc,#100] ; @0x080002A8 0x08000244 8A00 LDRH r0,[r0,#0x10] 71: GPIOB->BSRR = GPIO_BSRR_BS_12; 72: 0x08000246 2101 MOVS r1,#0x01 0x08000248 4A18 LDR r2,[pc,#96] ; @0x080002AC 0x0800024A 0309 LSLS r1,r1,#12 0x0800024C 6191 STR r1,[r2,#0x18] 73: if (!(db & (0x01 << 12))) { 0x0800024E 04C1 LSLS r1,r0,#19 68: { 69: uint_fast16_t db = GPIOC->IDR; 70: 71: GPIOB->BSRR = GPIO_BSRR_BS_12; 72: 73: if (!(db & (0x01 << 12))) { 0x08000250 D424 BMI 0x0800029C 74: switch (db & (0x03 << 9)) { 75: case 0x0000: 0x08000252 2103 MOVS r1,#0x03 0x08000254 0249 LSLS r1,r1,#9 76: GPIOA->BSRR = (0xFF << 16) | (db & 0xFF); 0x08000256 4B16 LDR r3,[pc,#88] ; @0x080002B0 0x08000258 4001 ANDS r1,r1,r0 0x0800025A D008 BEQ 0x0800026E 0x0800025C 39FF SUBS r1,r1,#0xFF 0x0800025E 39FF SUBS r1,r1,#0xFF 0x08000260 1E89 SUBS r1,r1,#2 0x08000262 D00A BEQ 0x0800027A 0x08000264 39FF SUBS r1,r1,#0xFF 0x08000266 39FF SUBS r1,r1,#0xFF 0x08000268 2902 CMP r1,#0x02 0x0800026A D117 BNE 0x0800029C 0x0800026C E00B B 0x08000286 0x0800026E 21FF MOVS r1,#0xFF 0x08000270 B2C0 UXTB r0,r0 0x08000272 0409 LSLS r1,r1,#16 0x08000274 1840 ADDS r0,r0,r1 0x08000276 6198 STR r0,[r3,#0x18] 77: break; 78: case 0x0200: 0x08000278 E010 B 0x0800029C 79: GPIOB->BSRR = (0x03 << 21) | (db & (0x03 << 5)); 0x0800027A 2160 MOVS r1,#0x60 0x0800027C 4008 ANDS r0,r0,r1 0x0800027E 0409 LSLS r1,r1,#16 0x08000280 1840 ADDS r0,r0,r1 0x08000282 6190 STR r0,[r2,#0x18] 80: break; 81: case 0x0400: 0x08000284 E00A B 0x0800029C 82: GPIOA->BSRR = (0x0F << 24) | ((db & 0xF0) << 4); 0x08000286 21F0 MOVS r1,#0xF0 0x08000288 4001 ANDS r1,r1,r0 0x0800028A 010C LSLS r4,r1,#4 0x0800028C 210F MOVS r1,#0x0F 0x0800028E 0609 LSLS r1,r1,#24 0x08000290 1864 ADDS r4,r4,r1 0x08000292 619C STR r4,[r3,#0x18] 83: GPIOB->BSRR = (0x0F << 24) | ((db & 0x0F) << 8); 84: break; 85: } 86: } 0x08000294 0700 LSLS r0,r0,#28 0x08000296 0D00 LSRS r0,r0,#20 0x08000298 1840 ADDS r0,r0,r1 0x0800029A 6190 STR r0,[r2,#0x18] 87: EXTI->PR = EXTI_PR_PR8; 0x0800029C 20FF MOVS r0,#0xFF 0x0800029E 4905 LDR r1,[pc,#20] ; @0x080002B4 0x080002A0 3001 ADDS r0,r0,#0x01 0x080002A2 6148 STR r0,[r1,#0x14] 88: } 0x080002A4 BC10 POP {r4} 0x080002A6 4770 BX lr 0x080002A8 0800 DCW 0x0800 0x080002AA 4800 DCW 0x4800 0x080002AC 0400 DCW 0x0400 0x080002AE 4800 DCW 0x4800 0x080002B0 0000 DCW 0x0000 0x080002B2 4800 DCW 0x4800 0x080002B4 0400 DCW 0x0400 0x080002B6 4001 DCW 0x4001 Сейчас как раз этим и занимаюсь. Не подскажите где посмотреть длительность каждой команды в машинных циклах?
  14. Да, этот момент я упустил. Сомневался нормально ли отработает установка/сброс одних и тех же битов. Перечитал мануал и переделал: 68: { 0x08000240 B410 PUSH {r4} 69: uint_fast16_t db = GPIOC->IDR & 0x1FFF; 70: uint_fast8_t data/* = db & 0xFF*/; 71: 0x08000242 481A LDR r0,[pc,#104] ; @0x080002AC 0x08000244 8A00 LDRH r0,[r0,#0x10] 72: GPIOB->BSRR = GPIO_BSRR_BS_12; 73: 0x08000246 4A1A LDR r2,[pc,#104] ; @0x080002B0 0x08000248 04C1 LSLS r1,r0,#19 0x0800024A 0CC9 LSRS r1,r1,#19 0x0800024C 2001 MOVS r0,#0x01 0x0800024E 0300 LSLS r0,r0,#12 0x08000250 6190 STR r0,[r2,#0x18] 74: data = db & 0xFF; 75: 0x08000252 B2C8 UXTB r0,r1 76: if (!(db & (0x01 << 12))) { 0x08000254 04CB LSLS r3,r1,#19 68: { 69: uint_fast16_t db = GPIOC->IDR & 0x1FFF; 70: uint_fast8_t data/* = db & 0xFF*/; 71: 72: GPIOB->BSRR = GPIO_BSRR_BS_12; 73: 74: data = db & 0xFF; 75: 76: if (!(db & (0x01 << 12))) { 0x08000256 D423 BMI 0x080002A0 77: switch (db & (0x03 << 9)) { 78: case 0x0000: 0x08000258 2303 MOVS r3,#0x03 0x0800025A 025B LSLS r3,r3,#9 0x0800025C 4019 ANDS r1,r1,r3 79: GPIOA->BSRR = (0xFF << 16) | data; 0x0800025E 4B15 LDR r3,[pc,#84] ; @0x080002B4 0x08000260 D008 BEQ 0x08000274 0x08000262 39FF SUBS r1,r1,#0xFF 0x08000264 39FF SUBS r1,r1,#0xFF 0x08000266 1E89 SUBS r1,r1,#2 0x08000268 D009 BEQ 0x0800027E 0x0800026A 39FF SUBS r1,r1,#0xFF 0x0800026C 39FF SUBS r1,r1,#0xFF 0x0800026E 2902 CMP r1,#0x02 0x08000270 D116 BNE 0x080002A0 0x08000272 E00A B 0x0800028A 0x08000274 21FF MOVS r1,#0xFF 0x08000276 0409 LSLS r1,r1,#16 0x08000278 4308 ORRS r0,r0,r1 0x0800027A 6198 STR r0,[r3,#0x18] 80: break; 81: case 0x0200: 0x0800027C E010 B 0x080002A0 82: GPIOB->BSRR = (0x03 << 21) | (data & (0x03 << 5)); 0x0800027E 2160 MOVS r1,#0x60 0x08000280 4008 ANDS r0,r0,r1 0x08000282 0409 LSLS r1,r1,#16 0x08000284 1840 ADDS r0,r0,r1 0x08000286 6190 STR r0,[r2,#0x18] 83: break; 84: case 0x0400: 0x08000288 E00A B 0x080002A0 85: GPIOA->BSRR = (0x0F << 24) | ((uint16_t)HINIBBLE(data) << 8); 0x0800028A 0301 LSLS r1,r0,#12 0x0800028C 0C09 LSRS r1,r1,#16 0x0800028E 020C LSLS r4,r1,#8 0x08000290 210F MOVS r1,#0x0F 0x08000292 0609 LSLS r1,r1,#24 0x08000294 1864 ADDS r4,r4,r1 0x08000296 619C STR r4,[r3,#0x18] 86: GPIOB->BSRR = (0x0F << 24) | ((uint16_t)LONIBBLE(data) << 8); 87: break; 88: } 89: } 0x08000298 0700 LSLS r0,r0,#28 0x0800029A 0D00 LSRS r0,r0,#20 0x0800029C 1840 ADDS r0,r0,r1 0x0800029E 6190 STR r0,[r2,#0x18] 90: EXTI->PR = EXTI_PR_PR8; 0x080002A0 20FF MOVS r0,#0xFF 0x080002A2 4905 LDR r1,[pc,#20] ; @0x080002B8 0x080002A4 3001 ADDS r0,r0,#0x01 0x080002A6 6148 STR r0,[r1,#0x14] 91: } 0x080002A8 BC10 POP {r4} 0x080002AA 4770 BX lr 0x080002AC 0800 DCW 0x0800 0x080002AE 4800 DCW 0x4800 0x080002B0 0400 DCW 0x0400 0x080002B2 4800 DCW 0x4800 0x080002B4 0000 DCW 0x0000 0x080002B6 4800 DCW 0x4800 0x080002B8 0400 DCW 0x0400 0x080002BA 4001 DCW 0x4001 Заказчику действительно все равно как будет реализована задача, но в данном конкретном случае требование заказчика состоит в реализации задачи на имеющейся аппаратной базе, а дальше крутись как хочешь. В данный момент в коде включена обработка только ОДНОГО прерывания.
×
×
  • Создать...