バイナリ シリアル データ ストリームを受信するアプリケーションがあり、このデータ ストリームをさまざまな長さの個別の変数 (uint16_t
とuint32_t
) に分割する必要があります。
今、私は超単純なことをしています:
#define OFFSET_iTOW 0
volatile uint8_t temp[128];
volatile uint32_t recBytes;
void main()
{
while (1)
{
recBytes = temp[OFFSET_iTOW+3];
recBytes <<= 8;
recBytes |= temp[OFFSET_iTOW+2];
recBytes <<= 8;
recBytes |= temp[OFFSET_iTOW+1];
recBytes <<= 8;
recBytes |= temp[OFFSET_iTOW+0];
}
}
(データはリトル エンディアンで送信されます。これOFFSET_iTOW
は、データ パケットのさまざまなセクションの約 30 のオフセット (通常はヘッダー ファイルで定義されます) の 1 つです)
ただし、これにより、かなり膨大なアセンブリ出力が得られます (対象のセクションがわずかに切り捨てられます)。
void main()
{
recBytes = 0;
12e: 10 92 04 02 sts 0x0204, r1
132: 10 92 05 02 sts 0x0205, r1
136: 10 92 06 02 sts 0x0206, r1
13a: 10 92 07 02 sts 0x0207, r1
while (1)
{
recBytes = temp[OFFSET_iTOW+3];
13e: 80 91 03 02 lds r24, 0x0203
142: 90 e0 ldi r25, 0x00 ; 0
144: a0 e0 ldi r26, 0x00 ; 0
146: b0 e0 ldi r27, 0x00 ; 0
148: 80 93 04 02 sts 0x0204, r24
14c: 90 93 05 02 sts 0x0205, r25
150: a0 93 06 02 sts 0x0206, r26
154: b0 93 07 02 sts 0x0207, r27
recBytes <<= 8;
158: 80 91 04 02 lds r24, 0x0204
15c: 90 91 05 02 lds r25, 0x0205
160: a0 91 06 02 lds r26, 0x0206
164: b0 91 07 02 lds r27, 0x0207
168: ba 2f mov r27, r26
16a: a9 2f mov r26, r25
16c: 98 2f mov r25, r24
16e: 88 27 eor r24, r24
170: 80 93 04 02 sts 0x0204, r24
174: 90 93 05 02 sts 0x0205, r25
178: a0 93 06 02 sts 0x0206, r26
17c: b0 93 07 02 sts 0x0207, r27
recBytes |= temp[OFFSET_iTOW+2];
180: 20 91 04 02 lds r18, 0x0204
184: 30 91 05 02 lds r19, 0x0205
188: 40 91 06 02 lds r20, 0x0206
18c: 50 91 07 02 lds r21, 0x0207
190: 80 91 02 02 lds r24, 0x0202
194: 90 e0 ldi r25, 0x00 ; 0
196: a0 e0 ldi r26, 0x00 ; 0
198: b0 e0 ldi r27, 0x00 ; 0
19a: 82 2b or r24, r18
19c: 93 2b or r25, r19
19e: a4 2b or r26, r20
1a0: b5 2b or r27, r21
1a2: 80 93 04 02 sts 0x0204, r24
1a6: 90 93 05 02 sts 0x0205, r25
1aa: a0 93 06 02 sts 0x0206, r26
1ae: b0 93 07 02 sts 0x0207, r27
recBytes <<= 8;
1b2: 80 91 04 02 lds r24, 0x0204
1b6: 90 91 05 02 lds r25, 0x0205
1ba: a0 91 06 02 lds r26, 0x0206
1be: b0 91 07 02 lds r27, 0x0207
1c2: ba 2f mov r27, r26
1c4: a9 2f mov r26, r25
1c6: 98 2f mov r25, r24
1c8: 88 27 eor r24, r24
1ca: 80 93 04 02 sts 0x0204, r24
1ce: 90 93 05 02 sts 0x0205, r25
1d2: a0 93 06 02 sts 0x0206, r26
1d6: b0 93 07 02 sts 0x0207, r27
recBytes |= temp[OFFSET_iTOW+1];
1da: 20 91 04 02 lds r18, 0x0204
1de: 30 91 05 02 lds r19, 0x0205
1e2: 40 91 06 02 lds r20, 0x0206
1e6: 50 91 07 02 lds r21, 0x0207
1ea: 80 91 01 02 lds r24, 0x0201
1ee: 90 e0 ldi r25, 0x00 ; 0
1f0: a0 e0 ldi r26, 0x00 ; 0
1f2: b0 e0 ldi r27, 0x00 ; 0
1f4: 82 2b or r24, r18
1f6: 93 2b or r25, r19
1f8: a4 2b or r26, r20
1fa: b5 2b or r27, r21
1fc: 80 93 04 02 sts 0x0204, r24
200: 90 93 05 02 sts 0x0205, r25
204: a0 93 06 02 sts 0x0206, r26
208: b0 93 07 02 sts 0x0207, r27
recBytes <<= 8;
20c: 80 91 04 02 lds r24, 0x0204
210: 90 91 05 02 lds r25, 0x0205
214: a0 91 06 02 lds r26, 0x0206
218: b0 91 07 02 lds r27, 0x0207
21c: ba 2f mov r27, r26
21e: a9 2f mov r26, r25
220: 98 2f mov r25, r24
222: 88 27 eor r24, r24
224: 80 93 04 02 sts 0x0204, r24
228: 90 93 05 02 sts 0x0205, r25
22c: a0 93 06 02 sts 0x0206, r26
230: b0 93 07 02 sts 0x0207, r27
recBytes |= temp[OFFSET_iTOW+0];
234: 20 91 04 02 lds r18, 0x0204
238: 30 91 05 02 lds r19, 0x0205
23c: 40 91 06 02 lds r20, 0x0206
240: 50 91 07 02 lds r21, 0x0207
244: 80 91 00 02 lds r24, 0x0200
248: 90 e0 ldi r25, 0x00 ; 0
24a: a0 e0 ldi r26, 0x00 ; 0
24c: b0 e0 ldi r27, 0x00 ; 0
24e: 82 2b or r24, r18
250: 93 2b or r25, r19
252: a4 2b or r26, r20
254: b5 2b or r27, r21
256: 80 93 04 02 sts 0x0204, r24
25a: 90 93 05 02 sts 0x0205, r25
25e: a0 93 06 02 sts 0x0206, r26
262: b0 93 07 02 sts 0x0207, r27
266: 6b cf rjmp .-298 ; 0x13e <loop+0x10>
これは、16 Mhz で動作する 8 ビット マイクロプロセッサ上で動作する割り込みサービス ルーチンの GPS データ パーサーの一部であり、これらの変換を多数行う必要があるため、上記の結果は少し過剰です。
これは ISR にあるため、割り込み中にさまざまなデータが変更されないことを確信できます。基本的に、個々のバイトを long でアドレス指定できるようにしたいと考えています。これは 8 ビット アーキテクチャであるため、コンパイラは数個の操作 (アセンブリの観点から long のバイトは直接アドレス指定可能であるため、C の 1 行あたり 3 ~ 4 個) まで最適化できるように思われます)。
変数は宣言されvolatile
ているため、何もしないループに最適化されません。実際のアプリケーションでは、それらはextern
ISR から書き込まれる構造体ですが、アイドル ループから読み取られます (読み取りが中断されるのを防ぐための適切な ISR ガード付き)。ただし、正確な動作を示すコンパクトなスニペットを作成する方法がわかりません。