2014-02-03 4 views
0

У меня есть 32-разрядный микроконтроллер и только что записал двойной флеш-память. Теперь я хочу прочитать двойную память из памяти, но я делаю что-то незаконное, так как микроконтроллер идет на жесткий обработчик ошибок.Прочтите двойной файл с 32-разрядной флеш-памятью

Сначала я попробовал:

double Flash_Read64(uint32_t address) 
{ 
    return *((double *) address); 
} 

, но это не сработало. Это потому, что адрес 32-битный, а (double *) ожидает 64-битный?

тогда я попробовал:

double Flash_Read64(uint32_t address) 
{ 
    uint64_t temp; 
    double * tempPtr = (double *) &temp; 

    //Increment address. 
    address += 4; 

    //Get MSB. 
    temp = (*((uint32_t *) (address))); 

    //Shift MSB to upper half. 
    temp = (temp << 32); 

    //Decrement address. 
    address -= 4; 

    //Get LSB. 
    temp |= (*((uint32_t *) address)); 

    return *tempPtr; 
} 

, но до сих пор не работает.

Любые предложения?

EDIT: (., Который я думаю, что это проблема выравнивания, которая вызывает печаль)

bool_t Flash_Write64Address(uint32_t address, double data) 
{ 
    uint32_t MSB, LSB; 
    uint32_t * tempPtr = (uint32_t *) &data; 

    //Get LSB. 
    LSB = tempPtr[0]; 

    //Write LSB to flash. 
    flashStatus = FLASH_ProgramWord(address, LSB); 
    if(flashStatus != FLASH_COMPLETE) 
    { 
     DEBUG("Failed to write to flash at address: %u", (unsigned int) address); 
     return FALSE; 
    } 

    //Increment address. 
    address += 4; 

    //Get MSB. 
    MSB = tempPtr[1]; 

    //Write MSB to flash. 
    flashStatus = FLASH_ProgramWord(address, MSB); 
    if(flashStatus != FLASH_COMPLETE) 
    { 
     DEBUG("Failed to write to flash at address: %u", (unsigned int) address); 
     return FALSE; 
    } 

    return TRUE; 
} 
+0

Покажите свою функцию записи. BTW: У вашей платформы есть 'uint64_t'? – chux

+0

Маленький Endian или Big Endian вашей системы? Возможно, вы можете сначала взглянуть на [это] (http://stackoverflow.com/questions/20451688/c-serialize-double-to-binary-file-in-little-endian) –

+0

@chux: Да, он имеет uint64_t , – Phat

ответ

1

Чтобы упростить и избежать проблем с выравниванием

typedef union { 
    double d; 
    uint32_t u[2]; 
} Xlate; 

bool_t Flash_Write64Address(uint32_t address, double data) { 
    Xlate x; 
    x.d = data; 
    for (int i=0; i < 2; i++) { 
    int flashStatus = FLASH_ProgramWord(address, x.u[i]); 
    address += 4; 
    if(flashStatus != FLASH_COMPLETE) { 
     return FALSE; 
    } 
    return TRUE; 
    } 

double Flash_Read64(uint32_t address) { 
    Xlate x; 
    x.u[0] = *((uint32_t *) address); 
    x.u[1] = *((uint32_t *) (address + 4)); 
    return x.d; 
} 

[Редактировать]
I Предполагая, что address представляет адрес с четырехбайтовым выравниванием (его наименьшие 2 бита равны 0). Если address не было 8-byte alignment (его как минимум в 3 бита равны 0) и требуется его double доступа, то

return *((double *) address); 
// or 
return *tempPtr; 

может вызвать неисправность шины. Если это так, вышеуказанный код должен решить эту проблему.
В качестве альтернативы код может застраховать address имеет 8-byte alignment.

+1

. Спасибо, что указали проблемы выравнивания памяти. Так было. При записи/чтении двойника из ячейки памяти, где (адрес% 2) == 0, он работает! В документации также говорится, что к памяти обращаются как 16-разрядные, так что это имеет смысл. Спасибо, chux! – Phat