ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
3 мая
748269 Топик полностью
Apтём (07.04.2017 23:33 - 08.04.2017 02:03, просмотров: 123) ответил Ксения на Но здесь я не вижу разрешения коллизии, когда вызван SendBuffer(), когда DMA еще не окончил предыдущее задание. Разве запуск новой передачи StartDMATx() не повредит окончанию старой?
Коллизии нет никакой - надо просто правильно сделать (ошибку заложить конечно можно). 
когда вызван SendBuffer(), когда DMA еще не окончил предыдущее задание.
Если ДМА ещё работает, то естественно его не трогаем. Только изменяем TxNext (обязательно в критической секции). У нас получается 2 случая: 1) Дма не активно - копируем данные, запускаем транзакцию и разрешаем прерывания ДМА 2) Дма работает - просто копируем данные и переносим TxNext. В прерывании ДМА запускаем новую транзакцию или запрещаем прерывания ДМА (в зависимости от того пуст буфер или нет). Типа как с прерыванием USARTxx_DRE: void ExtUartDriver_t::Write(uint8_t *data, uint16_t length) { uint16_t tx_next=TxBuffer.Next; for (uint16_t i=0; i<length; i++) { TxBuffer.Buffer[tx_next]=*data++; if (++tx_next>=sizeof(TxBuffer.Buffer)) tx_next=0; } CRITICAL_SECTION(); TxBuffer.Next=tx_next; if ((EXT_UART.CTRLA&USART_DREINTLVL_gm)==0) EXT_UART.CTRLA|=USART_DREINTLVL_LO_gc; } ISR(USARTF0_DRE_vect) { if (TxBuffer.NotEmpty()) EXT_UART.DATA=TxBuffer.ReadByte(); else EXT_UART.CTRLA&=~USART_DREINTLVL_gm; }