2016-01-20 6 views
-1

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

В соглашении говорится, что функция копирования является C-функцией, которая принимает в качестве адреса периферийного устройства 8-разрядный адрес, который записывается в определенный регистр. Внешняя периферия использует это внутренне. Тем не менее, я имитируя вещь в C и испытать полную функциональность я делаю что-то вроде следующего MWE:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc,char *argv[]){ 

    //stack-array to copy 
    char array[4] = {3,32,-12,99}; 
    //naive emulation of the peripheral memory space 
    char peripheral_array[4]; 

    //herein lies the address send as a value 
    char address_reg = (char*)(peripheral_array); 

    //assume this is the peripheral side 
    //set ptr to the address of the peripheral_array 
    char *ptr = (char*) address_reg; 
    memcpy((void*)ptr,array,sizeof(char)*4); 

    return EXIT_SUCCESS; 
} 

я получаю segmentation fault.

  • В чем проблема?

  • Как я могу сохранить указатель массива в качестве значения, отправить его, переделать его успешно как адрес массива и выполнить memcpy?

+0

Я хотел бы изменить '' char' к беззнаковому char', если он представляет интересы периферического адресного пространства. –

+0

Кроме того: вам не нужно указывать 'void *' с '(void *) ptr', то для типа' void * 'для' memcpy' указывается, что он принимает любой тип указателя. –

+1

Код не компилируется. Является ли address_reg идентичным адресу? – Ctx

ответ

3

Вы хотите эмулировать что-то с 8-разрядным адресным пространством в среде с 32-разрядным или 64-разрядным адресным пространством, и, следовательно, у вас есть некоторые трудности, потому что он не преобразуется тривиально. В частности, эта строка char address_reg = (char*)(peripheral_array) использует широкий указатель на 8-битное значение и теряет большую часть указателя, что означает, что вы не сможете преобразовать обратно.

Решение выдвинуть дальше имитацию и эмулировать ваши назначения 8-разрядное адресное пространство:

  • Typedef 8-битный указатель (очиститель): typedef uint8_t ptr8;
  • возвещать 8-битный адрес назначения пространство : uint8_t my_destination_memory[256]
  • Определить вы владеете тетсру скопировать в этом адресном пространстве:
    void my_memcpy(ptr8 addr_dest, const void * src, int len) { 
        memcpy(my_destination_memory + addr_dest, src, len); 
    } 
    

Таким образом, вы можете в год ss вокруг вашего 8-битного указателя типа ptr8 (или как вы его назовете) и скопируйте на него без проблем.
Обратите внимание, что я предположил, что ваше адресное пространство источника не имеет значения, но вы также можете эмулировать его. Вы должны иметь возможность эмулировать 16-битное или даже 24-битное адресное пространство одинаково (вы можете использовать собственные указатели, если вам нужно 32-битное).

+0

Будет преследовать этот. –

1

Зачем хранить его в char? переменная, которая может содержать адрес char, - это char* - На обеих машинах - ваш компьютер и встроенный MCU!

На вашем MCU sizeof(char*) может быть 1 или 2, а на вашем ПК может быть 4 или 8;

Если вы хотите написать совместимый с платформой код, используйте char*.

Если вы хотите сделать еще несколько шагов для моделирования адресного пространства машин, тогда вы должны предоставить собственные реализации стандартных функций lib. Так что они интерпретируют адреса в машинах как адресное пространство как индексы для некоторого определенного массива памяти, который вы определили.

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

0

Прежде всего, обратите внимание, что сохранение целочисленных значений в char является опасным, так как это тип с определенными приложением подписью. Он никогда не должен использоваться ни для чего, кроме строк.

Вместо этого всегда используйте либо int8_t (подпись), либо uint8_t (без знака).


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

Существует uintptr_t в stdint.h, который гарантирует себя достаточно большим, чтобы содержать адрес.

Просто замените

char address_reg = (char*)(peripheral_array); 

с

uintptr_t address_reg = (uintptr_t)peripheral_array; 
Смежные вопросы