EmbDev.net

Forum: ARM programming with GCC/GNU tools Structure for pins in GCC to address them like LCD.DB0=0


von Dima B. (mrengineer)


Rate this post
useful
not useful
Hello! Please, help me.

I use Eclipse + gcc + JTAG to programm AT91SAM7S64. I get universal code
to use with my LCD with controller (hereunder). The lines like LCD.E=0;
Delay(>20ms); should be modified correctly and structure LCD with pins
sould be declared. I would like to understand how to use constructions
like LCD.E=1. Currently I use mask in my code:
In board.h define pins of LCD ----------------
#define DB0  (1<<0)      // DB0 pin of LCD
#define DB1  (1<<1)      // DB1 pin of LCD
#define DB2  (1<<2)      // DB2 pin of LCD
#define DB3  (1<<3)      // DB3 pin of LCD
#define A0   (1<<4)      // A0  pin of LCD
#define RDRW (1<<5)      // Read/Write pin
#define E    (1<<6)      // E pin
#define DB7  (1<<7)      // DB7
#define DB6  (1<<9)      // DB6
#define DB5  (1<<10)      // DB5
#define DB4  (1<<11)      // DB4


#define MY_MASK  (DB0|DB1|DB2|DB3|A0|RDRW|E|DB7|DB6|DB5|DB4)
--------------------------------------------
And in main.c I write to init LCD something like  this:

/// Swith off all pins
pPIO->PIO_CODR = E; //OFF
pPIO->PIO_CODR = A0; //OFF
pPIO->PIO_CODR = RDRW; //OFF
pPIO->PIO_CODR = DB7; //OFF
pPIO->PIO_CODR = DB6; //OFF
pPIO->PIO_CODR = DB5; //OFF
pPIO->PIO_CODR = DB4; //OFF
pPIO->PIO_CODR = DB3; //OFF
pPIO->PIO_CODR = DB2; //OFF
pPIO->PIO_CODR = DB1; //OFF
pPIO->PIO_CODR = DB0; //OFF

// Step 1
wait(150);

pPIO->PIO_CODR = E; //OFF
wait(10);
pPIO->PIO_CODR = A0; //OFF
pPIO->PIO_SODR = DB5; //ON
pPIO->PIO_SODR = DB4; //ON
pPIO->PIO_SODR = E; //ON

// Step 3
wait(100);

pPIO->PIO_CODR = E; //OFF
wait(10);
pPIO->PIO_SODR = DB5; //ON
......
----------------------------------------------

In PIC C I can make something like this

LCD={E==portA.1,A0==PortA.5, RDRW==portA.4, DB7==portA.7, ....,
DB0==portB4};

And use LCD.E=0; or LCD.1=0; in code. Or write LCD = 0x0040; without
pPIO->PIO_CODR etc.

How can I bild some structure with links to set of pins in gcc? And how
can I work with it without commands like "pPIO->" using just "=" and
HEX, DEC or binary numbers? I would like to use downloaded code
hereunder:



UNIVERSAL CODE FOR LCD: --------------------


#define  MT10S1    //Type of LCD

#define  Len1  8  //Symbols in first line of LCD
#define  Len2  2  //Symbols in second line of LCD
#define  Len3  0  //In 3th
#define  Len4  0  //In 4th
const char Text1[Len1]={  'M','E','L','T',' ','1','0','S'    };
const char Text2[Len2]={  '1',24          };


void main(void) {
int i;

  LCDinit();
  WriteCmd(0x80);    //Set cursor in start of first line
#if Len1>0
  for(i=0;i<Len1;i++) { WriteData(Text1[i]); }
#endif

#if Len3>0
  for(i=0;i<Len3;i++) { WriteData(Text3[i]); }
#endif
  WriteCmd(0x80+0x40);  //Set in start of second line
#if Len2>0
  for(i=0;i<Len2;i++) { WriteData(Text2[i]); }
#endif
#if Len4>0
  for(i=0;i<Len4;i++) { WriteData(Text4[i]); }
#endif
}

void LCDinit(void) {
  LCD.E=0; Delay(>20ms);
//Set data pins for exit if needed
  LCD.RW=0; LCD.A0=0; LCD.D=0x30;  //8 bit interface setup
  Delay(>40ns);    //Pause
  LCD.E=1; Delay(>230ns);  //Время предустановки данных попало сюда
(tDSW)
  LCD.E=0; Delay(>40us);  //Пауза между командами
  LCD.E=1; Delay(>230ns);  //Минимально допустимая длительность сигнала
E=1
  LCD.E=0; Delay(>40us);  //Пауза между командами
  LCD.E=1; Delay(>230ns);
  LCD.E=0; Delay(>270ns);  //Минимально допустимый интервал между
сигналами E=1
//Здесь индикатор входит в рабочий режим с установленным типом
интерфейса и можно подавать команды как обычно
  WriteCmd(0x3A);    //Настройка правильного режима ЖКИ
  WriteCmd(0x0C);    //Включение индикатора, курсор выключен
  WriteCmd(0x01);    //LCD CLEAR
  WriteCmd(0x06);    //Установка режима ввода данных: сдвигать курсор
вправо
}

void WriteCmd(byte b) { WriteByte(b,0); }

void WriteData(byte b) { WriteByte(b,1); }

void WriteByte(byte b, bit cd) {
//Сначала проверим готовность индикатора
//При необходимости настроить здесь шину данных на ввод
  LCD.RW=1; LCD.A0=0;  //Чтение флага занятости
  Delay(>40ns);    //Это время предустановки адреса (tAS)
  LCD.E=1; Delay(>230ns);  //Это минимально допустимая длительность
сигнала E=1 (информация на шину данных индикатором будет выдана раньше,
не более чем через 120нс)
  while(LCD.D.7==1);  //Ждать сброса флага занятости
  LCD.E=0; Delay(>270ns);  //Минимально допустимый интервал между
сигналами E=1
//При необходимости настроить здесь шину данных на вывод
  LCD.RW=0; LCD.A0=cd; LCD.D=b;
  Delay(>40ns);    //Это время предустановки адреса (tAS)
  LCD.E=1; Delay(>230ns);  //Время предустановки данных попало сюда
(tDSW)
  LCD.E=0; Delay(>270ns);  //Минимально допустимый интервал между
сигналами E=1
}

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Dima Bulkin wrote:
> I would like to understand how to use constructions
> like LCD.E=1.

Theoretically this is possible with bitfields which are mapped to the
hardware-address of a register. But AFAIK gcc does not create "correct"
32-bit read/writes and may "optimize" to 8-bit which will throw an
exception. This issue has been mentioned in this forum before (several
month ago). There is a patch for this in the gcc bugzilla but it did not
work for me. I have asked the author of the patch and he admitted that
it is not correct. Have to add: I tested sometime in May or June so
maybe this is already fixed.

Also for GPIO the Target has to allow some kind of direct write to a
register (not just CLR/SET "Flip-Flop"-access). Most newer
ARM-controllers provide this. Better try to modify the downloaded code
and use some macros or inline-functions which can be easily modified for
different targets (hardware abstraction layer i.e. LCD_RW_LOW,
LCD_RW_HIGH etc.) so you do not need any specific compiler feature or
non-standard-extension (i.e. IAR ICCARM has an extension for this kind
of access). The "hal" will save you a lot of time later when you reuse
your components for another compiler/target.

Martin Thomas

von Dima B. (mrengineer)


Rate this post
useful
not useful
Thank you for advice, Martin. I will choose that way.

von Frikkie T. (frix)


Rate this post
useful
not useful
Hi there

Martin Thomas wrote:
> Theoretically this is possible with bitfields which are mapped to the
> hardware-address of a register. But AFAIK gcc does not create "correct"
> 32-bit read/writes and may "optimize" to 8-bit which will throw an
> exception. This issue has been mentioned in this forum before (several
> month ago). There is a patch for this in the gcc bugzilla but it did not
> work for me.

I've run into this exact same problem, trying to configure my
peripherals via structures, containing bitfields. I'm running a ST
STR912, under GCC 4.3.1, Newlib, OpenOCD and Eclipse, options:
--target=arm-elf --with-cpu=arm966e-s

I've seen in the GCC compiler options page
(http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/ARM-Options.html#ARM-Options
and
http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/MCore-Options.html#MCore-Options)
that the MCore architecture has an option: -mwide-bitfields, that forces
the access to the bitfield address as an int. I think a similar options
should solve the problem for ARMs.

ARM has a similar compiler option, but I think that this applies to the
structure as a whole, and not individual members of the structure:
"
-mstructure-size-boundary=n
The size of all structures and unions will be rounded up to a multiple
of the number of bits set by this option...
"


Could you perhaps provide me with the bugzilla entry, so that I could
follow it up with the GCC authors?

BTW - could you see with newer GCCs if it was resolved?

Regards,
Frikkie Thirion

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Frikkie Thirion wrote:
> Could you perhaps provide me with the bugzilla entry, so that I could
> follow it up with the GCC authors?
Please see the old thread: http://en.mikrocontroller.net/topic/81611#new

> BTW - could you see with newer GCCs if it was resolved?
Sorry, I don't know. I will try again once I have gcc 4.3.1 installed.

von Frikkie T. (frix)


Rate this post
useful
not useful
Martin Thomas wrote:
> Frikkie Thirion wrote:
>> Could you perhaps provide me with the bugzilla entry, so that I could
>> follow it up with the GCC authors?
> Please see the old thread: http://en.mikrocontroller.net/topic/81611#new
>
>> BTW - could you see with newer GCCs if it was resolved?
> Sorry, I don't know. I will try again once I have gcc 4.3.1 installed.

Thank you for the reply.
I've tested the bitfield accesses on the HiTex (www.hitex.com)
instruction set simulator: HiTOP 5 (with GCC 4.1.1), which is quite
good. I could see in the disassebled view in the debugger that the
assembler used to implement my C code is using "ldrb" and "strb", which
are byte accesses when I manipulate bitfield structures.

If I access the memory location with a 32-bit pointer, I could see in
the disassebled that "ldr" and "str" is used.

Maybe I should rethink my register accesses to move away from bitfields
all together - what a pitty...

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.