读取32位字存储器中的连续3个字节

时间:2018-02-03 17:19:15

标签: c arm embedded microcontroller

我有一个32位字可寻址存储器,我的数据部分可以在存储器内的任何字节处开始和结束。

假设我的数据部分从字0x3的字节2(0是最低字节)开始。

然后我必须从字0x3的字节2和3以及字0x4的字节0读取数据。在此之后,我必须读取字0x4的字节1,2和3,依此类推......只有当我所有3个字节为零或我的数据部分结束时才停止。下一节有可扩展的边界,它可以移动到我的数据部分,因此结束的字或字节不固定。

您对解决此问题的最佳算法有任何建议吗?我想出了一种方法来创建两个总共24位的掩码,我可以在单词中移动,但这看起来有些过分并且给了我很大的代码。我试图用尽可能少的C指令来解决它。期待您的建议。

2 个答案:

答案 0 :(得分:1)

从你的陈述中暗示你一次只能读取32位字,没有16位或8位,这也意味着你不必思考/谈论对齐。

就像支持字节可寻址内存的处理器一样,如果你有一个地址0x1002并且你有一些24位项目那么你可以用同样的方式实现它

0x1002 = 0b0001000000000010低位两位描述字中的字节高位字数字/地址0b00010000000000 0b10所以字地址0x400以字节2开始(字节顺序当然是一个因素,假设很少)。你也知道4 - 0b10 = 2意味着这个单词中还剩下两个字节,如果你需要第三个,你可以从下一个单词的偏移0开始。

所以你可以做一些类似这个未经测试的代码:

unsigned int get24 ( unsigned int x )
{  
    unsigned int ra;
    unsigned int ret;
    unsigned int wa;
    unsigned int shift;
    unsigned int rb;

    ret=0;
    wa=x>>2;
    shift=(x&3)<<3;
    rb=load32(wa);
    for(ra=0;ra<3;ra++)
    {
       ret<<=8;
       ret|=(rb>>shift)&0xFF;
       shift+=8;
       if(shift>=32)
       {
           wa++;
           rb=load32(wa);
           shift=0;
       }
    }
}

你可以在另一个答案中采用基于字节的方法,但你必须确保编译器知道你的基于字的内存限制,它不能被允许进行字节读取(很好地取决于架构),也不允许未对齐的访问(取决于架构)。

您可以尝试使用基于表格的

//0x00000000 0x00FFFFFF
//0x00000000 0xFFFFFF00
//0x000000FF 0xFFFF0000
//0x0000FFFF 0xFF000000

unsigned int al[4]={0,0,24,16};
unsigned int ar[4]={0,0,8,8};
unsigned int bl[4]={8,0,16,24};
unsigned int br[4]={8,8,16,24};

unsigned int wa;
unsigned int off;
unsigned int ra;
unsigned int rb;
unsigned int ret;

wa=byte_address>>2;
off=byte_address&3;
rb=load32(wa);
ret=(rb<<bl[off])>>br[off];
//ret=(rb<<bl[off])>>(off<<3);
if(off&2)
{
    ra=load32(wa+1);
    //ret|=(ra<<al[off])>>ar[off];
    ret|=(ra<<al[off])>>8;
}

或基于跳转表

wa=byte_address>>2;
rb=load32(wa);
//if(byte_address&0xC)
ra=load32(wa+1);
switch(byte_address&3)
{
    case 0:
    {
        ret=(rb<<8)>>8;
        break;
    }
    case 1:
    {
        ret=rb>>8;
        break;
    }
    case 2:
    {
        ret=(rb<<16)>>16;
        ret|=(ra<<24)>>8;
        break;
    }
    case 3:
    {
        ret=(rb<<24)>>24;
        ret|=(ra<<16)>>8;
        break;
    }
}

答案 1 :(得分:0)

我真的不明白你的意思下一节可扩展边界它可以移动。忽略以下代码应该用于读取数据:

int start_word = 3;
int start_byte = 2;
int end_word = 100;
uint8_t* p = data + start_word * 4 + start_byte;
uint8_t* end = data + end_word * 100;

while (p + 3 <= end) { // 3 more bytes must be available
    uint8_t b0 = *p++;
    uint8_t b1 = *p++;
    uint8_t b2 = *p++;
    if (b0 == 0 && b1 == 0 && b2 == 0)
         break;
    // do something with the 3 bytes
}

这个想法不是过分关注单词和字节工作。