STM32F4 Keil de __align komutu ne işe yarar?

Başlatan XX_CİHAN_XX, 21 Kasım 2012, 18:29:22

XX_CİHAN_XX

Aşağıdaki gibi bir yapımız olsun
typedef struct USB_OTG_handle
{
  USB_OTG_CORE_CFGS    cfg;
  USB_OTG_CORE_REGS    regs;
#ifdef USE_DEVICE_MODE
  DCD_DEV     dev;
#endif
#ifdef USE_HOST_MODE
  HCD_DEV     host;
#endif
#ifdef USE_OTG_MODE
  OTG_DEV     otg;
#endif
}
USB_OTG_CORE_HANDLE , *PUSB_OTG_CORE_HANDLE;


Ve aşağıdaki gibi bir tanımlamamız olsun.
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined   (__GNUC__)        /* GNU Compiler */
    #define __ALIGN_END    __attribute__ ((aligned (4)))
    #define __ALIGN_BEGIN         
  #else                           
    #define __ALIGN_END
    #if defined   (__CC_ARM)      /* ARM Compiler */
      #define __ALIGN_BEGIN    __align(4)  
    #elif defined (__ICCARM__)    /* IAR Compiler */
      #define __ALIGN_BEGIN 
    #elif defined  (__TASKING__)  /* TASKING Compiler */
      #define __ALIGN_BEGIN    __align(4) 
    #endif /* __CC_ARM */  
  #endif /* __GNUC__ */ 
#else
  #define __ALIGN_BEGIN
  #define __ALIGN_END   
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */



Şimdi bunlar yapıldıktan sonra program da yazılacak aşağıdaki gibi bir komut satırı tam olarak ne iş yapar?
__ALIGN_BEGIN USB_OTG_CORE_HANDLE    USB_OTG_Core __ALIGN_END ;


Merak ettiğim bu kod satırı ile aşağıdaki aynı işi mi yapar?

USB_OTG_CORE_HANDLE          USB_OTG_Core;

Yani USB_OTG_Core adında yeni bir USB_OTG_CORE_HANDLE türünden yapı mı tanımlamış oluyoruz. Bu __ALIGN olayının espirisini anlayamadım  :o
Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

XX_CİHAN_XX

#1
Hocam bu harika açıklama için çok teşekkür ederim. Yalnız sizeof dan 12 dönmesi beni çok şaşırttı. Oraya kadar her şeyi tamam çok iyi anladım derken 12 nereden çıktı böyle  ???


mesaj birleştirme:: 21 Kasım 2012, 21:38:35

Sanırım anladım :)
deneme nin yerleştirileceği adresi 16 nın katına çekmek için fazladan eklenen baytlar sonucu denemenin boyutu 12 bayta çıkmış olmalı değil mi hocam?
Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

XX_CİHAN_XX

Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

mufitsozen

Alıntı yapılan: XX_CİHAN_XX - 22 Kasım 2012, 09:06:50
Anladım hocam çok teşekkür ederim.

Sayin @gerbayin detayli aciklamasina kucuk bir ekleme yapmak isterim.

Bu alignment sirasinda bos kalan yerlerde herhangi bir icerik olabilir. Bu yuzden "pack" edilmemis structure'lar karsilastirilmaz (kucuk, buyuk yada esitlik icin)

Cok yapilan bir hata oldugu icin bahsedeyim dedim.

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Klein

Coocox ile  GCC kullanıyorım.

manuelinde
http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

__attribute__ ((__packed__))

bu şekilde yapın demiş, ama  iiçinde "packed" geçen hiç bir şeyi kabul etmiyor.

mufitsozen

Alıntı yapılan: Klein - 22 Kasım 2012, 12:56:23
Coocox ile  GCC kullanıyorım.

manuelinde
http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

__attribute__ ((__packed__))

bu şekilde yapın demiş, ama  iiçinde "packed" geçen hiç bir şeyi kabul etmiyor.

Sayin @klein hocam __attribute__((packed)) olmasin?
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Klein

Hocam dokümanların birinde de öye yapın diyor. ama yok onu da yemiyor.

packed kelimesi içinde geçen tüm harflerin kombinasyonunu yaptım yine yemedi :)

z

typedef struct __attribute__((packed)) _test_t
{
  int i;
  short s;
  char ch;
  char c;
} test_t;


Yapmak daha iyi olmazmı?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Klein

#8
Buna neden ihtiyaç duyduk. Neden struct  söz dizimi değişti?
_test_t

Bunu yapmadan da hata vermedi. 
Genel alışkanlıkla paket tanımını "struct" tanımlayıcısının önüne koyduğum için kızmış.   
Nasıl align ettiğini denemedim. programın bu parçası bitince ancak deneyebileceğim.


mesaj birleştirme:: 22 Kasım 2012, 14:56:11

Alıntı yapılan: z - 22 Kasım 2012, 14:12:37
typedef struct __attribute__((packed)) _test_t
{
  int i;
  short s;
  char ch;
  char c;
} test_t;


Yapmak daha iyi olmazmı?

Sanırım aradaki boşluklar, paketin nasıl hizalandığı daha iyi görülebilsin diye böyle ortaya karışık yapmış hocam.

Klein

#9
Bir kaç tane struct ve bir tane de  içinde bu tipten yapı barındıran struct var ise;
Tüm yapıların tek tek align edilmesi mi gerekir, sadece taşıyıcı yapının align edilmesi yeterli midir?

(Aslında kendi kendime deneyerek öğrenebileceğim konularla kimseyi uğraştırmak istemiyorum. bunları deneyerek bulabilirim. Ama GCC'de ASM list çıktısı alma opsiyonunu bir türlü bulamadım.  Ancak debug penceresinden ASM listini görebiliyorum, o da çok uğraştırıcı oluyor.)

fatih6761

@Klein hocam GCC'de Assembly çıktısını şu şekilde alabiliyoruz:
gcc -S -o asm_output.s code.c
Aynı çıktıyı g++'dan da alabiliyoruz.

Klein

Sanırım bu  .c uzantılı tek dosyanın derlendikten sonra ASM çıktısını almak için. Şimdilik bu da işimi görür.

Link sonrasında programımızın  son aldığı şeklin çıktısını alabileceğimiz bir  Linker parametresi var mı?

mufitsozen

#12
Alıntı yapılan: Klein - 24 Kasım 2012, 14:40:16
Sanırım bu  .c uzantılı tek dosyanın derlendikten sonra ASM çıktısını almak için. Şimdilik bu da işimi görür.

Link sonrasında programımızın  son aldığı şeklin çıktısını alabileceğimiz bir  Linker parametresi var mı?

ld icin map alma, ve map-file'a yazma opsiyonlari olmasi lazim



mesaj birleştirme:: 24 Kasım 2012, 15:04:31

http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html#SEC3 alinti:

-M
--print-map
    Print a link map to the standard output. A link map provides information about the link, including the following:

        Where object files and symbols are mapped into memory.
        How common symbols are allocated.
        All archive members included in the link, with a mention of the symbol which caused the archive member to be brought in.

-Map mapfile
    Print a link map to the file mapfile. See the description of the `-M' option, above.



mesaj birleştirme:: 24 Kasım 2012, 15:17:11

biraz google'layinca soyle bir blog buldum, isinize yarayabilir.

'gcc -c -g -Wa,-ahl=test.s test.c'. This produces the following output in test.s:

    12 main:
    13 .LFB2:
    14 .file 1 "test.c"
    1:test.c **** int main(void)
    2:test.c **** {
    15 .loc 1 2 0
    16 0000 8D4C2404 leal 4(%esp), %ecx
    17 .LCFI0:
    18 0004 83E4F0 andl $-16, %esp
    19 0007 FF71FC pushl -4(%ecx)
    20 .LCFI1:
    21 000a 55 pushl %ebp
    22 .LCFI2:
    23 000b 89E5 movl %esp, %ebp
    24 .LCFI3:
    25 000d 51 pushl %ecx
    26 .LCFI4:
    27 000e 83EC10 subl $16, %esp
    28 .LCFI5:
    3:test.c **** int dummy;
    4:test.c **** for( dummy = 6; dummy > 0; dummy– );
    29 .loc 1 4 0
    30 0011 C745F806 movl $6, -8(%ebp)
    30 000000
    31 0018 EB04 jmp .L2
    32 .L3:
    33 001a 836DF801 subl $1, -8(%ebp)
    34 .L2:
    35 001e 837DF800 cmpl $0, -8(%ebp)
    36 0022 7FF6 jg .L3
    5:test.c **** }
    37 .loc 1 5 0
    38 0024 83C410 addl $16, %esp
    39 0027 59 popl %ecx
    40 0028 5D popl %ebp
    41 0029 8D61FC leal -4(%ecx), %esp
    42 002c C3 ret

That looks quite nice already and for example you can now clearly see where the loop starts and ends – great!

An alternative way is to use 'objdump'. This method only works if you have compiled the code with debug information, e.g. 'gcc -g test.c -o test.o'. You can use 'objdump -dS test.o' to get some nice looking assembly output:

    08048344 <main>:
    int main(void)
    {
    8048344: 8d 4c 24 04 lea 0×4(%esp),%ecx
    8048348: 83 e4 f0 and $0xfffffff0,%esp
    804834b: ff 71 fc pushl -0×4(%ecx)
    804834e: 55 push %ebp
    804834f: 89 e5 mov %esp,%ebp
    8048351: 51 push %ecx
    8048352: 83 ec 10 sub $0×10,%esp
    int dummy;
    for( dummy = 6; dummy > 0; dummy– );
    8048355: c7 45 f8 06 00 00 00 movl $0×6,-0×8(%ebp)
    804835c: eb 04 jmp 8048362 <main+0x1e>
    804835e: 83 6d f8 01 subl $0×1,-0×8(%ebp)
    8048362: 83 7d f8 00 cmpl $0×0,-0×8(%ebp)
    8048366: 7f f6 jg 804835e <main+0x1a>
    }
    8048368: 83 c4 10 add $0×10,%esp
    804836b: 59 pop %ecx
    804836c: 5d pop %ebp
    804836d: 8d 61 fc lea -0×4(%ecx),%esp
    8048370: c3 ret

Note: if you declared 'int dummy' in the sample code as volatile the resulting assembly code would look like this:

    08048344 <main>:
    int main(void)
    {
    8048344: 8d 4c 24 04 lea 0×4(%esp),%ecx
    8048348: 83 e4 f0 and $0xfffffff0,%esp
    804834b: ff 71 fc pushl -0×4(%ecx)
    804834e: 55 push %ebp
    804834f: 89 e5 mov %esp,%ebp
    8048351: 51 push %ecx
    8048352: 83 ec 10 sub $0×10,%esp
    int volatile dummy;
    for( dummy = 6; dummy > 0; dummy– );
    8048355: c7 45 f8 06 00 00 00 movl $0×6,-0×8(%ebp)
    804835c: eb 09 jmp 8048367 <main+0×23>
    804835e: 8b 45 f8 mov -0×8(%ebp),%eax
    8048361: 83 e8 01 sub $0×1,%eax
    8048364: 89 45 f8 mov %eax,-0×8(%ebp)
    8048367: 8b 45 f8 mov -0×8(%ebp),%eax
    804836a: 85 c0 test %eax,%eax
    804836c: 7f f0 jg 804835e <main+0x1a>
    }
    804836e: 83 c4 10 add $0×10,%esp
    8048371: 59 pop %ecx
    8048372: 5d pop %ebp
    8048373: 8d 61 fc lea -0×4(%ecx),%esp
    8048376: c3 ret

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Klein

Hocam derleyici Map çıktısı veriyor. Ancak sembollerin hafızadaki yerleşimi var sadece.  Toplam ne kadar ram  kullanmışım, kod ne kadar , sabitler ne tutmuş gibi bilgilerin hiç birisi yok.

ASM list çıktısı için bir deneme yaptım, ancak dosyalar , kütüphaneler vs.. ayrı yerde olduğu için bazı dosyaları bulamadı , bıraktım. Daha sonra sadece main.c'den  oluşan bir deneme programı yazıp deneyeceğim.

Konuyu biraz dağıttım sanırım.  Konuyu toparlamak için  sorumu tekrar soraym.

Bir kaç tane struct ve bir tane de  içinde bu tipten yapı barındıran struct var ise;
Tüm yapıların tek tek align edilmesi mi gerekir, sadece taşıyıcı yapının align edilmesi yeterli midir?



Klein

Bu güne kadar bu sorunu hiç yaşamamıştım. Yaşamamış olmamın sebebi aslında bir dizi tesadüf.

Uzun süredir 16 bit işlemciler ile çalışıyorum. Tüm projelerde Modbus kullandığım için, tüm verilerimi hep 16 bite göre ayarlıyordum.
Bir struct içeriğini eeproma kaydedeceğim zaman , son 2 bayt hep CRC oluyor ve  kayıt uzunluğunu sabit vermeyip, sizeof() ile yapının uzunluğunu bularak ayarlıyordum. Buyüzden de dizi align edilmemiş bile olsa ben bunun farkında olmuyordum.

Şimdi pack yaptığımda align edilip edilmediğini görebiliyorum aslında. Ama yine bazı tesadüflerin kurbanı olup olmadığıma emin olmak için , hem ASM kodlarını kontrol edeyim, hem de bir bilenin ağzından teyit edeyim diye konuyu biraz deşiyorum.