functions - udf volatile vba



Elenco de matriz volátil para matriz não volátil (3)

Eu tenho um volatile unsigned char buffer[10] volátil global para o qual os dados são gravados em uma interrupção. Eu tenho uma função que leva unsigned char * e armazena esse valor para hardware (EEPROM) void storeArray(unsigned char *array) , neste exemplo os três primeiros valores. É seguro converter o array volátil em um array não volátil como esse?

storeArray((unsigned char *) buffer);

Eu li o seguinte, que eu não entendo muito bem, mas que me preocupa:

6.7.3: 5 Se for feita uma tentativa de se referir a um objeto definido com um tipo qualificado volátil através do uso de um lvalor com tipo qualificado não volátil, o comportamento é indefinido.

Isso afeta meu código?

Então eu tenho esta pergunta de acompanhamento: A matriz de buffer só tem uma seção de dados que eu quero armazenar (não posso mudar isso), para este exemplo começando com o terceiro valor. É legítimo fazer o seguinte?

storeArray((unsigned char *) buffer + 3);

Se for, como o elenco é afetado, se 3 é adicionado ao array? BR e obrigado!

EDIT: @Cacahuete Frito vinculado uma pergunta muito semelhante: É `memcpy ((void *) dest, src, n)` com um array `volatile` seguro?


Answer #1
  1. Se a matriz for alterada na interrupção, você precisará fornecer um mecanismo para acessar e modificar sua forma atômica. Se você não tiver nenhuma operação RW ou RMW, ela poderá falhar e os dados serão inconsistentes.

  2. Você acessa os dados voláteis, tornando os parâmetros f / untion voláteis também. storeArray(volatile unsigned char *) e nenhum cast será necessário. O elenco só remove o aviso. Mesmo que você passe dados não voláteis para ele, também funcionará.


Answer #2

Como você descobriu, você está confiando em "comportamento indefinido". No entanto, dependendo entre outras coisas na separação de unidades de compilação (e coisas como "otimização de todo o programa" (WPO)), provavelmente funcionará. Na maioria dos casos, o compilador (pelo menos o gcc) não é "inteligente o suficiente" para otimizar os acessos do array entre funções em diferentes unidades de compilação. Dito isso, a maneira limpa, segura e portátil seria copiar o array, tornando a dependência dos valores do array não-volátil nos voláteis visíveis para o compilador.


Answer #3

Você encontrou a seção correta do padrão, esse código leva a um comportamento indefinido.

Uma função que escreve algo "para hardware" provavelmente deve ter um parâmetro -qualifier volatile , dependendo do que é "hardware". Se for um registrador mapeado por memória, um buffer DMA ou memória não volátil, então o parâmetro definitivamente deve ter sido volatile unsigned char* (ou opcionalmente, volatile uint8_t* que também deve ser considerado como um tipo de caractere).

Detalhes: C nos permite iterar através de qualquer pedaço de dados usando um ponteiro de caractere, C17 6.3.2.37:

Quando um ponteiro para um objeto é convertido em um ponteiro para um tipo de caractere, o resultado aponta para o menor byte endereçado do objeto. Incrementos sucessivos do resultado, até o tamanho do objeto, geram ponteiros para os bytes restantes do objeto.

A parte que você cita sobre o acesso a um "lvalue" refere-se ao acesso a dados por meio de um tipo de ponteiro diferente do que está armazenado naquele local. Claramente: não importa o quanto você lança vários ponteiros apontando para ele, os dados atuais mantêm o seu tipo original.

Acessar os dados através do tipo de ponteiro errado normalmente não é permitido, mas novamente o acesso de caracteres é uma exceção especial à "regra de aliasing restrita", C17 6.5 / 7:

Um objeto deve ter seu valor armazenado acessado apenas por uma expressão lvalue que tenha um dos seguintes tipos:
...
- um tipo de personagem.

Assim, você pode acessar qualquer tipo de dado por meio de um ponteiro de caractere, mas se esse ponteiro não for volátil, você invoca o comportamento indefinido de acordo com a parte citada, C17 6.7.3 / 5.

Na prática, usar um tipo de ponteiro não volátil pode fazer com que o compilador otimize o acesso de maneiras inesperadas. Então, isso não é apenas "linguagem-lawyering" teórica, você poderia, na prática, obter um código muito estranho gerado com otimizações ativadas. Muito difícil de encontrar erros em sistemas embarcados se originam de tal volatile ausente.

Em relação à sua pergunta de acompanhamento, o elenco e o buffer + 3 não mudam nada: você ainda está lidando com um ponteiro de personagem sem qualificador volatile - o mesmo tipo. Os dados atuais permanecem do tipo volatile unsigned char , então você não pode acessá-lo da função através de um unsigned char* .





volatile