Página 1 de 1

Compilador Keil e variáveis

MensagemEnviado: 07 Fev 2022 14:17
por vtrx
Estou tentando achar um 'bug' num projeto portado.
Compilador Keil 5 com opção C99,ja que os sources usam definição de variáveis dentro do corpo das rotinas.
Em um trecho de rotina,uma parte das variéveis esta definido assim:
Código: Selecionar todos
void ApplyDirection(TEffectState effect, int32_t force, int32_t* axes)

Esta variável recebe de retorno os argumentos:
Código: Selecionar todos
      axes[0] += (int32_t)(FfbCos(angle) * fForce);
      axes[1] += (int32_t)(FfbSin(angle) * fForce);


Minha dúvida é como a variável axes é carregada.
axes[0] representa a parte alta(dois bytes) da variavel,tipo.xxxxxxxx xxxxxxxx 00000000 00000000 ?

Re: Compilador Keil e variáveis

MensagemEnviado: 08 Fev 2022 19:48
por andre_luis
Tem de ver como foi definido a variavel usada no argumento axes quando instancia a função ApplyDirection. Certamente foi declarada como um array de duas ou mais variaveis int32_t. Nesse caso axes[0] representaria o valor total carregado.
Se estiver sendo feito diferente disso (ex.: axes declarado como int16_t) não é usual misturar tipos.

Re: Compilador Keil e variáveis

MensagemEnviado: 09 Fev 2022 09:18
por cfreund
vtrx escreveu:
Código: Selecionar todos
void ApplyDirection(TEffectState effect, int32_t force, int32_t* axes)

Esta variável recebe de retorno os argumentos:
Código: Selecionar todos
      axes[0] += (int32_t)(FfbCos(angle) * fForce);
      axes[1] += (int32_t)(FfbSin(angle) * fForce);


Minha dúvida é como a variável axes é carregada.
axes[0] representa a parte alta(dois bytes) da variavel,tipo.xxxxxxxx xxxxxxxx 00000000 00000000 ?


axes aponta para uma variável de 32bits. Se você está passando um vetor int32_t de pelo menos 2 posições na chamada da função, tá tudo certo.

Vai acontecer o seguinte:

Suponhamos que a variável int32_t myAxes[2] está no endereço de memória 0x1000 e que se trata de um microcontrolador de 32bit:

Você chama ApplyDirection(effet, force, myAxes);

A função ApplyDirection vai modificar o conteúdo do endereço 0x1000 e 0x1001. axes[0] vai apontar para 0x1000 e axes[1] vai apontar para 0x1001.

---------------------------------

Se, myAxes, em vez de int32_t, for definida como int16_t e tiver apenas duas posições, teu BUG está aí - se for int16_t myAxes[4] tá tudo certo. ApplyDirection vai continuar modificando 0x1000 e 0x1001 e cagando pro que você fez lá na chamada.

Re: Compilador Keil e variáveis

MensagemEnviado: 09 Fev 2022 23:22
por vtrx
Obrigado a vcs.
To fazendo com calma.
Mandei um email para um dos autores do projeto,que é do final de 2016,e ele me retornou que não chegou a terminar completamente a versão em C,mas me orientou a verificar uma versão final em C#.
Se para mim é longo ler o código em C++,imagine em C#.
O principal trecho a analisar é este relacionado a esta rotina.
Mais uma;
int16_t p_axis[2] = {0,0};,deve guardar dois valores entre 0 e 255,seria eixo X e eixo Y.
Vejam se a definição esta correta.
p_axis[0] = 255
p_axis[1] = 127
Isso carrega a parte alta e a parte baixa correto?
Esse valores são passados para a rotina abaixo:
Código: Selecionar todos
void FfbGetFeedbackValue(int16_t* axisPosition, int32_t* out)
{
   int32_t x_y_force[2] = {0,0};
...etc

A função é chamada assim:
FfbGetFeedbackValue(&p_axis[0],forces_data);
Como faço para passar os dois bytes(p_axis[0] e [1]) para a função?
Do modo que fiz acho que só vai uma parte,o compilador não aceita somente p_axis

PS:aproveitando,se a variável for int16_t ,o compilador aceitará que eu carregue a parte alta com um valor entre 0 e 255 e a parte baixa com 0 ou 255 ou seguirá a regra de um numero negativo?
Caso negativo,deixarei p_axis como sem sinal e extrairei a parte alta e baixa separadamente.

Re: Compilador Keil e variáveis

MensagemEnviado: 12 Fev 2022 17:26
por cfreund
Código abaixo deve imprimir "12345678".

Código: Selecionar todos
#include <stdio.h>
#include <stdint.h>

void FfbGetFeedbackValue(int16_t* axisPosition, int32_t* out)
{
    *out   = 0;
    *out   = axisPosition[0];
    *out <<= 16;
    *out  |= axisPosition[1];
}

int main()
{
    int16_t p_axis[2] = {0x1234,0x5678};
    int32_t forces_data;
   
    FfbGetFeedbackValue(p_axis, &forces_data);
   
    printf("%x", forces_data);

    return 0;
}

Re: Compilador Keil e variáveis

MensagemEnviado: 14 Fev 2022 08:55
por xultz
Ó, faz tempo que não programo em C, e eu nem tentei compilar o código abaixo, mas eu faria algo semelhante a isto:

Código: Selecionar todos
#include <stdio.h>
#include <stdint.h>

void FfbGetFeedbackValue(int16_t* axisPosition, int32_t* out)
{
((unsigned char *)&out)[0] = ((unsigned char *)&axisPosition[0])[0];
((unsigned char *)&out)[1] = ((unsigned char *)&axisPosition[0])[1];
((unsigned char *)&out)[2] = ((unsigned char *)&axisPosition[1])[0];
((unsigned char *)&out)[3] = ((unsigned char *)&axisPosition[1])[1];
}

int main()
{
    int16_t p_axis[2] = {0x1234,0x5678};
    int32_t forces_data;
   
    FfbGetFeedbackValue(p_axis, &forces_data);
   
    printf("%x", forces_data);

    return 0;
}

Re: Compilador Keil e variáveis

MensagemEnviado: 15 Fev 2022 23:15
por vtrx
No repositório do autor ele deixou o sistema em C#.
Como uso a implementação em C# para programar o STM?
O framework USB que uso é implementado no Keil,não sei como utilizar as rotinas em C#.

Re: Compilador Keil e variáveis

MensagemEnviado: 16 Fev 2022 08:09
por cfreund
C sharp não foi feito para microcontroladores. Deve ter algumas "gambiarras" intituladas microframeworks, mas sempre com ressalvas.

Esta tentando portar https://github.com/JakaSimonic/ForceFee ... re-library? Isso foi feito para computador normal. Não acredito que, mesmo tendo um framework que suporte seu STM, esse código irá funcionar.

O caminho é o que você está fazendo: aproveitando a ideia e REESCREVENDO o código calculando as limitações do seu STM. Mas tenha claro o conceito de ponteiros e alocação de memória no C. Isso é requisito básico.

Re: Compilador Keil e variáveis

MensagemEnviado: 16 Fev 2022 21:09
por vtrx
cfreund escreveu:C sharp não foi feito para microcontroladores. Deve ter algumas "gambiarras" intituladas microframeworks, mas sempre com ressalvas.

Esta tentando portar https://github.com/JakaSimonic/ForceFee ... re-library? Isso foi feito para computador normal. Não acredito que, mesmo tendo um framework que suporte seu STM, esse código irá funcionar.

O caminho é o que você está fazendo: aproveitando a ideia e REESCREVENDO o código calculando as limitações do seu STM. Mas tenha claro o conceito de ponteiros e alocação de memória no C. Isso é requisito básico.

O repositório é esse,o código é funcional usando Keil e o STM,mas contem erros de calculo.
O autor me indicou a usar como refrencia a implementação em C#:https://github.com/JakaSimonic/VjoyWrapper

Re: Compilador Keil e variáveis

MensagemEnviado: 16 Fev 2022 22:46
por cfreund
Keil compilando código escrito em C#?

Re: Compilador Keil e variáveis

MensagemEnviado: 18 Fev 2022 11:42
por vtrx
cfreund escreveu:Keil compilando código escrito em C#?

Não,o Keil compila o exemplo em C,que roda com erros de calculo,que não afeta o teste final.
A parte em C#,foi o autor do código em C que me indicou a verificar para tentar corrigir o código em C.
Não mandei mais email para ele porque ele pensa que é um projeto comercial e porque também não tenho tanto conhecimento para ficar incomodando ele com perguntas 'repetitivas'.
Mas voltando,consegui portar 90% do código que foi escrito em C++(Arduino) para O keil em C puro,mas estou apanhando em utilizar structs que estão nos Headers,dependendo do trecho o compilador indica 'duplicidade' na refrencia.
Á noite vou montar um questionamento para ver se me ajudam a solucionar a utilização e inicialização destas struct que estão no arquivo .h original,não movi de lugar.
Se alguém também souber C++ utilizado no Arduino,tenho duas rotinas que não sei como transcrever para C,uma inicia com ~ao lado do nome da rotina.

Re: Compilador Keil e variáveis

MensagemEnviado: 18 Fev 2022 22:01
por vtrx
Estou apanhando aqui.
1-Inicar valores de um struct.
No inicio de um arquivo header existem duas struct definidas assim:
Código: Selecionar todos
struct Gains{
  uint8_t totalGain         ;
   uint8_t constantGain      ;
   uint8_t rampGain          ;
   uint8_t squareGain        ;
   uint8_t sineGain          ;
   uint8_t triangleGain      ;
   uint8_t sawtoothdownGain  ;
   uint8_t sawtoothupGain    ;
   uint8_t springGain        ;
   uint8_t damperGain        ;
   uint8_t inertiaGain       ;
   uint8_t frictionGain      ;
   uint8_t customGain        ;
};

struct EffectParams{
    int32_t springMaxPosition               ;
    int32_t springPosition                  ;

    int32_t damperMaxVelocity             ;
    int32_t damperVelocity                   ;

    int32_t inertiaMaxAcceleration       ;
    int32_t inertiaAcceleration          ;

    int32_t frictionMaxPositionChange ;
    int32_t frictionPositionChange      ;
};

   //force feedback gain
   struct Gains* m_gains;

   //force feedback effect params
   struct EffectParams* m_effect_params;


No código em C++,os elementos são iniciado diretamente.
Código: Selecionar todos
struct Gains{
    uint8_t totalGain         = FORCE_FEEDBACK_MAXGAIN;
   uint8_t constantGain      = FORCE_FEEDBACK_MAXGAIN;
   uint8_t rampGain          = FORCE_FEEDBACK_MAXGAIN;
   uint8_t squareGain        = FORCE_FEEDBACK_MAXGAIN;
   uint8_t sineGain          = FORCE_FEEDBACK_MAXGAIN;
   uint8_t triangleGain      = FORCE_FEEDBACK_MAXGAIN;
   uint8_t sawtoothdownGain  = FORCE_FEEDBACK_MAXGAIN;
   uint8_t sawtoothupGain    = FORCE_FEEDBACK_MAXGAIN;
   uint8_t springGain        = FORCE_FEEDBACK_MAXGAIN;
   uint8_t damperGain        = FORCE_FEEDBACK_MAXGAIN;
   uint8_t inertiaGain       = FORCE_FEEDBACK_MAXGAIN;
   uint8_t frictionGain      = FORCE_FEEDBACK_MAXGAIN;
   uint8_t customGain        = FORCE_FEEDBACK_MAXGAIN;
};

struct EffectParams{
    int32_t springMaxPosition = 0;
    int32_t springPosition = 0;

    int32_t damperMaxVelocity = 0;
    int32_t damperVelocity = 0;

    int32_t inertiaMaxAcceleration = 0;
    int32_t inertiaAcceleration = 0;

    int32_t frictionMaxPositionChange = 0;
    int32_t frictionPositionChange = 0;
};

Não consigo iniciar no keil,toda tentativa apresenta um erro.
Preciso acessar estas duas struct no Main,mas se eu incluir o header onde elas estão,o compilador apresenta erro de duplicidade entre o Main e outro arquivo .c que precisa de outras structs que o header tem.

Re: Compilador Keil e variáveis

MensagemEnviado: 19 Fev 2022 21:26
por cfreund
Monte o header dessa forma:
Código: Selecionar todos
#ifndef _STRUCTS_FILE_H_
#define _STRUCTS_FILE_H_

typedef struct
{
   uint8_t totalGain         ;
   uint8_t constantGain      ;
   uint8_t rampGain          ;
   uint8_t squareGain        ;
   uint8_t sineGain          ;
   uint8_t triangleGain      ;
   uint8_t sawtoothdownGain  ;
   uint8_t sawtoothupGain    ;
   uint8_t springGain        ;
   uint8_t damperGain        ;
   uint8_t inertiaGain       ;
   uint8_t frictionGain      ;
   uint8_t customGain        ;
} GAINS;

typedef struct
{
   int32_t springMaxPosition         ;
   int32_t springPosition            ;

   int32_t damperMaxVelocity         ;
   int32_t damperVelocity            ;

   int32_t inertiaMaxAcceleration    ;
   int32_t inertiaAcceleration       ;

   int32_t frictionMaxPositionChange ;
   int32_t frictionPositionChange    ;
} EffectParams;

//force feedback gain
GAINS *m_gains;

//force feedback effect params
EffectParams *m_effect_params;

#endif


No arquivo .c:
Código: Selecionar todos
#include structs_file.h

GAINS Gains =
{
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN,
    FORCE_FEEDBACK_MAXGAIN
};

void main()
{

}

Re: Compilador Keil e variáveis

MensagemEnviado: 20 Fev 2022 11:27
por vtrx
Valeu cfreund,mas ficou muito difícil continuar tentando seguir como C++ like.
Peguei todas as rotinas do arquivo.c e mais a estrutura que ele usava e coloquei tudo no main.
Pelo menos ficou tudo resolvido.