хранение короткой подписи в младших 16 битах целого числа без знака - PullRequest
5 голосов
/ 16 сентября 2011

Я программирую C на встроенной системе.Архитектура процессора - 32 бита (sizeof(int) - 32 бита, sizeof(short) - 16 бит).Существует 32-битная переменная, которая является отображаемым в памяти управляющим регистром (CTRL_REG), который указан как только используемые младшие 16 битов, и они содержат целочисленное значение со знаком 16 бит (запись в старшие биты не имеет никакого эффекта).Доступ к памяти должен быть выровнен по 32-битной системе, поэтому я не могу просто навести указатель на пару байтов, а также не могу предположить, что они имеют порядок байтов.Я обеспокоен тем, что автоматическое продвижение типов может испортить все, что я храню, расширив бит до 31, а не оставляя его в 15, где я хочу.Каков наилучший способ хранения чего-либо в этом месте?

Вот мой оригинальный код, который, я почти уверен, неверен:

#define CTRL_REG   *((volatile unsigned int *)0x4000D008u)
short calibrationValue;

CTRL_REG = -2 * calibrationValue;

Тогда я попробовал это, но я думаю, что этовсе еще может быть предметом целочисленного повышения в точке назначения:

CTRL_REG = (short)(-2 * calibrationValue);

Тогда, наконец, я подумал об этом:

CTRL_REG = (unsigned short)(short)(-2 * calibrationValue);

Я не могу оценить эти варианты очень хорошо, потому что онивсе работает в моих тестах, потому что calibrationValue оказывается отрицательным (это калибровочный параметр, специфичный для каждого устройства, и поэтому может быть положительным на некоторых устройствах), поэтому после умножения на -2 я в итоге сохраняю положительное значение и, таким образом,на самом деле не сталкивайтесь с проблемой, которую я ожидаю в своих тестах.

Ваша помощь очень ценится, даже если она просто говорит: «Вы слишком много думаете».

Ответы [ 4 ]

4 голосов
/ 16 сентября 2011

Подумайте, как -16 (например) выглядит в 16 битах: «0xFFF0» и в 33 битах: «0xFFFFFFF0».Расширение знака - это именно то, что вы хотите, чтобы бит знака был в нужном месте.Поскольку верхние 16 не имеют значения, их можно заполнить единицами.Поэтому создайте 32-разрядное значение со знаком, затем приведите его к 32-значному знаку без знака, чтобы поместить его в регистр:

  Int32 calreg= -2L * calibrationValue;
   CTRl_REG = (Uint32)calreg;

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

4 голосов
/ 16 сентября 2011

Вместо целого числа без знака определите объединение целого числа без знака и двух кратных целых чисел со знаком.

Вот так я обрабатываю «забавные аппаратные регистры управления» в моих системах ARM, где довольно часто встречаются нечетные битыздесь и там либо «пофиг», либо «им не должно быть написано 1».

Rgds, Martin

0 голосов
/ 16 сентября 2011
#define SS2L(sh,sl) ( ((sh) <<16) | ((sl) & 0xffff) )

Для объединения двух 16-битных шортов в один 32-битный.

Лучше всего делать битопы с использованием беззнаковых типов;продвижение в Int может захватить вас.Возможно, также добавьте некоторые дополнительные приведения к unsigned в вышеупомянутом макросе.

0 голосов
/ 16 сентября 2011

Если значения, записанные в старшие 16 бит, игнорируются, я думаю, вы можете смело полагаться на преобразование типов.В общем, вас не волнуют старшие биты.

#define CTRL_REG   *((volatile signed int *)0x4000D008u)
short calibrationValue;

CTRL_REG = -2 * calibrationValue;

Обратите внимание, что CTRL_REG теперь объявлен как подписанное целое число.

...