Ну да. Не вижу противоречий. Как только взводится TXE, сразу
кидайте следующий байт. Но кидать больше байт, чем у вас длина
транзакции - не нужно. Кинули последний, выключили прерывание по
TXE и ждёте падения BSY. Всё. Транзакция закончилась ровно тем
количеством байт, которое отправили в буфер передачи. Так получите
полностью слитную посылку. Забирать байты по приёму обязательно все, даже если часть из них вам не нужна. Доходило до того, что я настраивал DMA на приём и ставил указатель на volatile переменную-пустышку - чтобы сбрасывать приём. Иначе падает в ошибку OVF.
Сколько в буфер передачи байт положили, столько и придёт на приём, если у вас мастер. По приёму, разумеется, последний байт (или слово) придёт после того, как закончится его передача. Поэтому, разумеется, между записью в DR и взводом RXNE может пройти почти два символа. И это нормально!
Первый символ уходит в сдвиговый регистр передачи и сразу же, буквально на следующем такте шины, взводится TXE. Поэтому два первых байта идут практически дуплетом. И последний символ по приёму, действительно придёт через ДВА символьных интервала. И это нормально. Ждите падения BSY когда всё передали. И когда отработан последний RXNE, а это будет прямо в момент падения BSY, получите все символы транзакции.
*путаю байты и слова. Читайте всё как "символ". А уж какого он размера, 8 бит или 16 - настраивается.