Голый металл Raspberry Pi 3: неожиданное поведение массивов и операторов switch - PullRequest
0 голосов
/ 16 июня 2019

В настоящее время у меня есть простая программа, которая устанавливает фрейм-буфер, в который можно записывать.

Я сталкиваюсь с поведением, когда значения, хранящиеся в массивах, после извлечения возвращаются как кажущиеся случайными значениями, без связи с оригиналами. Я также заметил несколько странное и неожиданное поведение операторов switch - я подозреваю, что это как-то связано с тем, как массивы и операторы switch статически размещаются в памяти.

В качестве примера, здесь у меня есть некоторый код, который должен рисовать жестко закодированное число, а затем 7 других жестко закодированных чисел, которые были сохранены в массиве:

unsigned int cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
drawNum(&display, 0x1234ABCD);
for (int i=0; i<7; i++)
  drawNum(&display, cols[i]);

Первый drawNum() вызов с жестко заданным значением работает нормально, но все вызовы с доступом к массиву дают на первый взгляд случайные результаты.

Назначение значений массива во время выполнения не имеет этой проблемы, например:

unsigned int cols[7];
cols[0] = 0xFFFF0000;
cols[1] = 0xFFFF7F00;
cols[2] = 0xFFFFFF00;
cols[3] = 0xFF00FF00;
cols[4] = 0xFF0000FF;
cols[5] = 0xFF4B0082;
cols[6] = 0xFF9400D3;
drawNum(&display, 0x1234ABCD);
drawNum(&display, (int)cols);
for (int i=0; i<7; i++)
  drawNum(&display, cols[i]);

Я также столкнулся с непредсказуемым поведением при возврате значений из операторов switch.

Не могу сказать точно, но это заставляет меня поверить, что это проблема с используемым компилятором или компоновщиком - я использую arm-none-eabi.

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

И вот мой выстрел в темноте. Вы перезаписываете память где угодно, и это убивает cols[]. Если вы переместите переменную из глобальной области в локальную область, результат будет другим. Добавьте некоторый код «детектора»:

volatile unsigned int cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
drawNum(&display, 0x1234ABCD);

//test code
drawNum(&display, cols[0]==0xFFFF0000);    
drawNum(&display, cols[1]==0xFFFF7F00);

for (int i=0; i<7; i++)
  drawNum(&display, cols[i]);      

//test code
drawNum(&display, cols[0]==0xFFFF0000);    
drawNum(&display, cols[1]==0xFFFF7F00);

Я добавил ключевое слово volatile, чтобы избежать оптимизации компилятором. Это не должно маскировать наблюдаемый неправильный вывод.

0 голосов
/ 17 июня 2019

Просто выстрел в темноте, но вы можете попробовать другое значение в вашем массиве, где максимальный бит равен 0 вместо 1, как в жестко заданном примере.

unsigned int cols[7] = { 0x7FFF0000, 0x7FFF7F00, 0x7FFFFF00, 0x7F00FF00, 0x7F0000FF, 0x7F4B0082, 0x7F9400D3 };

Это предполагает, чтоdrawNum принимает int вместо неподписанного int.У вас может быть проблема с конверсией.Не видя, что делает drawNum, трудно сказать.

...