UNION SFR e STRUCT.

Software e Hardware para linha ARM

Moderadores: 51, guest2003, Renie, gpenga

Mensagempor MarcusPonce » 25 Nov 2009 20:15

Fabim,

Naquela struct tem alguns _padNN que estão definidos como short e um que está definido como long.
Eu coloquei aqui no Keil e a struct do jeito que estava ocupa 236 bytes.
Então eu mudei todos os __padNN para char e aí ocupou 131 bytes.
Acho que é isso, estou colocando abaixo com "<---------" aonde eu alterei.

volatile union{
char controle[131]; //aqui faltava um ";"

__packed struct{ //STRT END 0xE0024000
_u char ilr; // Interrupt Location Register
_u char _pad0[3];
_u short ctc; // Clock Tick Counter
_u char _pad1[2]; // <------------------------------------------
_u char ccr; // Clock Control Register
_u char _pad2[3];
_u char ciir; // Counter Increment Interrupt Register
_u char _pad3[3];
_u char amr; // Alarm Mask Register
_u char _pad4[3];
_u long ctime0; // Consolidated Time Register 0
_u long ctime1; // Consolidated Time Register 1
_u long ctime2; // Consolidated Time Register 2
_u char sec; // Seconds Register
_u char _pad5[3];
_u char min; // Minutes Register
_u char _pad6[3];
_u char hour; // Hours Register
_u char _pad7[3];
_u char dom; // Day Of Month Register
_u char _pad8[3];
_u char dow; // Day Of Week Register
_u char _pad9[3];
_u short doy; // Day Of Year Register
_u char _pad10[2];
_u char month; // Months Register
_u char _pad11[3];

_u short year; // Years Register // 0xE002403C

_u char _pad12[33];//33 BYTES perdidos <----------------------------

//STRT END 0xE0024060
_u char alsec; // Alarm Seconds Register
_u char _pad13[3];
_u char almin; // Alarm Minutes Register
_u char _pad14[3];
_u char alhour; // Alarm Hours Register
_u char _pad15[3];
_u char aldom; // Alarm Day Of Month Register
_u char _pad16[3];
_u char aldow; // Alarm Day Of Week Register
_u char _pad17[3];
_u short aldoy; // Alarm Day Of Year Register
_u char _pad18; // <--------------------------------------------
_u char almon; // Alarm Months Register
_u char _pad19[3];
_u short alyear; // Alarm Years Register
_u char _pad20; // <--------------------------------------------
_u short preint; // Prescale Value Register (integer)
_u char _pad21; // <----------------------------------------------
_u short prefrac; // Prescale Value Register (fraction)
_u char _pad22; //FIM END 0xE0024087 <------------------------------------
} configs;
}controle __at(0xE0024000);
MarcusPonce
Byte
 
Mensagens: 166
Registrado em: 12 Fev 2007 13:58
Localização: Campinas - SP

Mensagempor fabim » 25 Nov 2009 20:49

cara, hehe, fui melhorando e editando algumas coisas, e não observei que não troquei as edições originais, pois fui no famoso CTRL+H...

nossa, isto não é um gato, é um trigue!!!!

TKS novamente amigo !!! tu é bem observador.

To tão extressado, que até essas coisas estou deixando passar despercebido!!!

TKS!!
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor MarcusPonce » 25 Nov 2009 21:05

De nada, valeu !
MarcusPonce
Byte
 
Mensagens: 166
Registrado em: 12 Fev 2007 13:58
Localização: Campinas - SP

Mensagempor msamsoniuk » 26 Nov 2009 00:08

duas observacoes:

a) search e replace _u por unsigned... nao custa nada e fica muito mais legivel... eu acho que um define para unsigned virar u eh o mesmo que define para if virar while e while virar if ou entao for virar abobora.

b) em devices mapeados, semaforos ou qq coisa onde otimizacoes para registros vao dar problema, eu sempre uso volatile. tambem dah para evitar uso de _at usando ponteiro:

struct uart *uart0 = endereco_uart0, *uart1 = endereco_uart1;

ou, se faz questao de nao usar ponteiro, cria um linker script e posiciona exatamente a variavel no endereco fisico desejado. mesmo sobre o _packed, se vc alinhar corretamente vc na pratica nao precisa dele:

Código: Selecionar todos
struct
{
  unsigned char a;
  unsigned char b;
  unsigned short c;
} d;


produz um sizeof(d) = 4 no gcc sem atributo extra. eh soh evitar coisas como:

Código: Selecionar todos
struct
{
  unsigned char a;
  unsigned short c;
  unsigned char b;
} d;


que produz um sizeof(d) = 6... uma sutileza simples... sei lah, o codigo fica menos zuado...
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor fabim » 26 Nov 2009 07:30

sim tchelo, obrigado.
Veja que virei homi da modis.
essa estrutura tinha um monte de UINT32 e UINT16 e UINT8, eu odeio essas definições de processador.
Se a IDE é ANSI, pra que ficar trocando nome e ficar portanto types.h ?

As modificações que eu fiz foi no CTRL+h, para UINTXX, depois troquei alguns outros por char, e onde era pra ser UINT16, virou short, eu falei pra ele que era dois bytes[2], pra ficar melhor pra eu fuçar, só que confundi que no keil short é 2 bytes, e não troquei por char.

ontem a noite eu estava estudando mais 3 datasheet´s referente ao RTC, e observei que o 1766 por exemplo não perde aqueles 33 bytes no meio, é menos.

Só que há uma particularicade em comum com todos eles, até no LPC2103.
Sobre o RTC, são todos os mesmos nomes dos registradores e alocados todos iguais, apenas do year pra frente que tem um vacuo pra depois entrar na região de setagem do alarme!!

O que eu fiz, desmembrei a struct em duas partes. Uma para seta hora, e outra para seta alarme. Ficou legalzim e funcionou de premera!!

Vou fazer mais um testim e posto aqui pro pessoal usar tambem.

Obrigado pelas dicas!!

Fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor fabim » 26 Nov 2009 08:29

Marcus, liguei o lab aqui e fui debugar.
Observe que no datasheet que eu passei.
Todas as SFR´s ocupam uma long, porem é utilizado o LSB.

Onde eu coloquei nome nos piolhos, e depois criei o array abaixo, com 2 ou 3 char´s, foi intencional para poder pular estes bytes inuteis.
Ao que você deixou como char, e retirou a definição de comprimento[2], que faz mensão ao pulo dos 2 ou 3 bytes MSB, o pacote ficou desorientado e havendo setagem de bytes que estão fora da posição correta.

To debugando aqui, e acertando os comprimentos, só acabar eu ja coloco aqui ajustadinho proc´s verem como ficou.

Obrigado novamente.
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor MarcusPonce » 26 Nov 2009 08:40

Sobre o "__packed struct" :
Eu também prefiro não usar __packed pois possivelmente vai ficar mais rápido sem ele. Porém, na primeira struct que o Fabim colocou havia o uso de vários "short x:1" e "short y:n" e no Keil não estava sendo possível fazer aquela struct ficar exatamente casada em cima dos 32bits do registrador do ARM em questão. Estava ficando maior. Ou seja, como a idéia era criar um membro da struct para cada bit ou grupo de bits, o jeito foi usar o __packed mesmo.

Sobre os typedef:
O ideal seria seguir o ANSI, mas também ter a _esperança_ que um código escrito para micros de 8 bits também pudesse compilar para 32 bits com um mínimo de alterações, pelo menos as rotinas que não lidam com I/O.
Não sei se está todo mundo lembrando, mas na revisão mais recente do padrão ANSI para C criou-se um include que é o <stdint.h>. Hoje faz parte da maioria dos compiladores, pois isso já aconteceu há uma década.
Entre outras coisas, ele define:
uint8_t; uint16_t; uint32_t; uint64_t;
int8_t; int16_t; int32_t; int64_t;

Colocando o include <stdint.h> e usando exatamente estes tipos conseguiríamos melhorar bastante a portabilidade.

Pena que K. e R. não conseguiram fazer assim desde o início.
MarcusPonce
Byte
 
Mensagens: 166
Registrado em: 12 Fev 2007 13:58
Localização: Campinas - SP

Mensagempor MarcusPonce » 26 Nov 2009 08:45

OK, Fabim, eu busquei chegar no tamanho 131, mas deveria ter lembrado de tirar o controle[131] para ter certeza de detectar que a struct não iria ficar menor, se eu trocasse um short por um char onde não era vetor ( ou seja, com o [n] ) como você escreveu.
MarcusPonce
Byte
 
Mensagens: 166
Registrado em: 12 Fev 2007 13:58
Localização: Campinas - SP

Mensagempor msamsoniuk » 26 Nov 2009 10:07

ah, eu nao tinha visto os pads hehehe

eu teria montado um pouco diferente, pq no 68000 os devices costumam se alinhar em metade do bus, requerendo um pad:

http://xstep.sourceforge.net/xstep-4.1/ ... /mc68901.h

por exemplo, para setar um bit no timer:

device->timer.controlb.reset = 1

ou entao, se mapear usando linker script:

device.timer.controlb.reset = 1;

ou mesmo usando um conjunto de macros para esconder o caminho

#define TBRESET timer.controlb.reset

daih usando:

device->TBRESET = 1;

na serial, por exemplo:

#define RXSTATUS serial.rxstatus.data
#define RXSTATUS_RDY serial.rxstatus.ready

e por ae vai... o conceito eh um pouco cru pq esse codigo eh meio velho :P
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor fabim » 26 Nov 2009 11:51

ó, cabei de simular tudo certinho, os endereços estão batendo exatamente com os registradores, e seus tipos.

Código: Selecionar todos
 #include <LPC214X.h>
#include <absacc.h>
#define _u  unsigned

   volatile union{
 
  _u char controle[132];

  __packed  struct{ //STRT END 0xE0024000
  _u char    ilr;        // Interrupt Location Register
  _u char    _pad0[3];
  _u short    ctc;        // Clock Tick Counter
  _u short   _pad1[2];
  _u char    ccr;        // Clock Control Register
  _u char    _pad2[3];
  _u char    ciir;       // Counter Increment Interrupt Register
  _u char    _pad3[3];
  _u char    amr;        // Alarm Mask Register
  _u char    _pad4[3];
  _u long    ctime0;     // Consolidated Time Register 0
  _u long    ctime1;     // Consolidated Time Register 1
  _u long    ctime2;     // Consolidated Time Register 2
  _u char    sec;        // Seconds Register
  _u char    _pad5[3];
  _u char    min;        // Minutes Register
  _u char    _pad6[3];
  _u char    hour;       // Hours Register
  _u char    _pad7[3];
  _u char    dom;        // Day Of Month Register
  _u char    _pad8[3];
  _u char    dow;        // Day Of Week Register
  _u char    _pad9[3];
  _u short    doy;        // Day Of Year Register
  _u char    _pad10[2];
  _u char    month;      // Month Register
  _u char    _pad11[3];
 
      // 0xE002 403F
  _u short    year;       // Years Register
  _u char    _pad12[32]; //33 BYTES perdidos
 
                  //STRT END 0xE0024060
  _u char    alsec;      // Alarm Seconds Register
  _u char    _pad13[3];
  _u char    almin;      // Alarm Minutes Register
  _u char    _pad14[3];
  _u char    alhour;     // Alarm Hours Register
  _u char    _pad15[3];
  _u char    aldom;      // Alarm Day Of Month Register
  _u char    _pad16[3];
  _u char    aldow;      // Alarm Day Of Week Register
  _u char    _pad17[3];
  _u short    aldoy;      // Alarm Day Of Year Register
  _u char    _pad18[2];
  _u char    almon;      // Alarm Months Register
  _u char    _pad19[3];
  _u short    alyear;     // Alarm Years Register
  _u char    _pad20[2];
  _u short    preint;    // Prescale Value Register (integer)
  _u char    _pad21[2];
  _u short    prefrac;   // Prescale Value Register(fraction)
  _u char    _pad22[2];//FIM END 0xE0024087
  }configs;   
  }controle __at(0xE0024000);


agora vem a parte que me enteressa, para facilitar o uso do rtc para qualquer ARM7 ou no caso linha 175X e 176X LPC...

Código: Selecionar todos
 void acerta_hora(char hora, char minuto, char segundos){
 controle.configs.hour = hora;
 controle.configs.min  = minuto;
 controle.configs.sec  = segundos;
 }

 void le_hora(char *hora, char *minuto, char *segundos){
 hora = controle.configs.hour;
 minuto = controle.configs.min;
 segundos = controle.configs.sec;

 }


para o le_hora(...
o keil esta reclamando bagarai, que:

lpcRTC.h(75): error: #513: a value of type "unsigned char" cannot be assigned to an entity of type "char *"

que eu me lembre bem.

char *dado;

*dado = &endereço;
dado = o valor que eu vou colocar na variavel do endereço;


porque raioz de motivos o keil esta buffando?

Abraços
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor fabim » 26 Nov 2009 12:31

hehe, desonfiei da mão, e fui bizoiar de novo, as folhas que eu imprimi, tava com uma folha do um2138 e outra do 2148...rsrs

CM3, tem nada haver!!rsrs

Vou fazer para o CM3...

dispois eu posto tambem.

Braços

Mais uma dica.
Eu ainda não tinha aberto um header de processador pra poder ver como é feito...
Esquece, estrutura só quando não tiver jeito mesmo..rsrs
fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor MarcusPonce » 26 Nov 2009 19:48

Ok, ótimo .
Acho que quanto mais alto nível, mais maneiras diferentes de fazer a mesma coisa: struct, #define, etc.
Qual usar ? Depende... de ficar mais fácil de entender, de ficar mais rápido, etc.


Sobre o erro que o Keil está reclamando: tem que colocar os " * " e ficará assim:

void le_hora(char *hora, char *minuto, char *segundos)
{
*hora = controle.configs.hour;
*minuto = controle.configs.min;
*segundos = controle.configs.sec;
}

Quando definimos:

char *dado;

Temos que o valor de "dado" é o endereço da posição de memória para onde o ponteiro aponta. Já " *dado " é o conteúdo da posição de memória apontada.

Você poderia pensar assim: aquele " * " significa "apontado por"
MarcusPonce
Byte
 
Mensagens: 166
Registrado em: 12 Fev 2007 13:58
Localização: Campinas - SP

Mensagempor fabim » 27 Nov 2009 09:04

Marcus, tu se engonou viu.

char *data;
char a=0;

*data = &a;
data = 10;

agora a = 10;;;

"*" indica endereço; pois o asterisco fala que é o endereço do ponteiro.

data = variavel propriamente dita, o qual o ponteiro dela aponta.

Abraços
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Djalma Toledo Rodrigues » 27 Nov 2009 11:58

Saudades do 8080 Fabim

HL Endereço da Ram , Atual Ponteiro

(HL) o conteúdo, o byte da Ram , do endereço apontado por HL

Incr L ---> endereço seguinte lógico

Incr H ---> página seguinte

além de H L usos outros .

DJ
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor Jorge_Francisco » 27 Nov 2009 12:08

fabim escreveu:Marcus, tu se engonou viu.

char *data;
char a=0;

*data = &a;
data = 10;

agora a = 10;;;

"*" indica endereço; pois o asterisco fala que é o endereço do ponteiro.

data = variavel propriamente dita, o qual o ponteiro dela aponta.

Abraços


Fabim,

Engana-se você, olha aí:

Código: Selecionar todos
char *data; //ponteiro
char a = 0;// variável

data = &a;//ponteiro recebe endereço da variável, ou seja, ambos tem o mesmo endereço
*data = 10;// o valor 10 é inserido no espaço de memória.


Entendeu?

Vlw
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

AnteriorPróximo

Voltar para ARM

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x