Следите! Уже сделано так. Все имеют доступ к printf(), внутри него,
когда сообщение готово, вызывается _write() в котором сообщение
отправляется в завернутый в критическую обертку StreamBufferSend().
В задаче из завернутого в критическую обертку StreamBufferRecieve()
это сообщение копируется, его длина и адрес передается в DMA, пуск
DMA, начинается транзакция в UART, задача ставится на ожидание,
пока от прерывания DMA не придет уведомление о завершении
транзакции. C приходом этого уведомления от DMA задача разблокируется и начинает ждать новое сообщение или же сразу начинает вытягивать уже появившееся к этому моменту из StreamBufferRecieve() сообщение и т.д. и т.д. Никто, кроме этой задачи больше не имеет доступа к каналу ДМА, и никто кроме канала ДМА не имеет доступ к UART. Пока высвечивается один узкий момент времени - ДМА выставил флаг о завершении транзакции, а UART еще не успел вытолкать последнее слово, и тогда ....? Но пока подобных проблем в работе не замечал.