combinando dados compactados com acesso alinhado à memória
Estou tentando executar uma otimização de memória que deveria ser teoricamente possível, mas que estou começando a duvidar que esteja dentro da capacidade do arm-elf-gcc. Por favor, mostre-me que estou errado.
Eu tenho um sistema incorporado com uma quantidade muito pequena de memória principal e uma quantidade ainda menor de nvram com bateria. Estou armazenando dados de configuração de soma de verificação no nvram para que na inicialização eu possa validar a soma de verificação e continuar uma execução anterior ou iniciar uma nova, se a soma de verificação for inválida. Durante a execução, atualizo vários campos de vários tamanhos nesses dados de configuração (e não há problema em invalidar a soma de verificação até que seja recalculada posteriormente).
Tudo isso é executado no espaço de endereço físico - o sram normal é mapeado em um local e o nvram é mapeado em outro. Aqui está o problema - todo o acesso ao nvram deve ser feito em palavras de 32 bits; nenhum acesso de byte ou meia palavra é permitido (embora esteja obviamente bom na memória principal).
Assim, eu posso: a) armazenar uma cópia de trabalho de todos os meus dados de configuração na memória principal e copiá-la para o nvram quando recalcular a soma de verificação ou b) trabalhar diretamente com ela no nvram, mas de alguma forma convencer o compilador de que todas as estruturas são embalado e todos os acessos não devem ser apenas de 32 bitsalinhado, mas também de 32 bitsLargo.
A opção a) desperdiça preciosa memória principal, e eu preferiria fazer a troca em tempo de execução para salvá-la (embora não se o tamanho do código acabar desperdiçando mais do que economizo no tamanho dos dados) através da opção b).
Eu estava esperando que__attribute__ ((packed, aligned(4)))
ou alguma variação disso poderia ajudar aqui, mas todas as leituras e experiências que fiz até agora me decepcionaram.
Aqui está um exemplo de brinquedo do tipo de dados de configuração com os quais estou lidando:
#define __packed __attribute__ ((packed))
struct __packed Foo
{
uint64_t foo;
struct FooFoo foofoo;
}
struct __packed Bar
{
uint32_t something;
uint16_t somethingSmaller;
uint8_t evenSmaller;
}
struct __packed PersistentData
{
struct Foo;
struct Bar;
/* ... */
struct Baz;
uint_32 checksum;
}
Você pode imaginar threads diferentes (um para executar as funções Foo, Bar e Baz) atualizando suas próprias estruturas conforme apropriado e sincronizando em algum momento para declarar que é hora de recalcular a soma de verificação e adormecer.