1. почему линкер не выравнивает переменные, размера меньше чем
слово, по адресу, кратному слову? Не обязан по умолчанию. Volatile расценивается что читаться будут битов по разрядности size_t в случае arm(extends do the holding register в типо оригинале), что автоматом приводит к косяку (если переменная не выровнена) или нет (если так свезло)
2. как заставить линкер производить выравнивание адреса размещения переменных внутри одного модуля по границам слова, хотя бы для ускорения доступа к этим переменным?
Директива
#pragma (push, 4)
бла бла бла
#pragma (pop)
3. как заставить линкер производить выравнивание адреса размещения переменных при переходе к другому модулю?
см п.2
4. что за херня? как эта дурацкая опция влияет на генерирование кода с невыровненным адресом переменных модулей?
Это плохая вообще идея делать volatile для uint8_t.
5. предполагаю, что имеется ошибка в GCC: работающий код может думать, что переменная размещена по выровненному адресу, а реально она находится по невыровненному
Очень врядли.
ситуация многократно обсосана на стековерфло и коммунити.арм