Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: PIC24F реальный размер const во флеше.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
YAM
Имеем PIC24F, MPLAB + C30
Я правильно понял, что
массив из const char mass[10]; реально займет 15 байт флэша,
массив из const int mass[10]; реально займет 30 байт флэша,
массив из const long mass[10]; реально займет 60 байт флэша?
Т.е. реально теряем один из трёх байт при упаковке констант?
Alex B._
Цитата(YAM @ Feb 14 2008, 20:21) *
Т.е. реально теряем один из трёх байт при упаковке констант?

все верно. C30 использует PSV для доступа к константам во флеши. PSV - это механизм отображения памяти программ в область памяти данных. Так как программное слово 24-битное, а машинное - 16-битное, в ОЗУ отображается только младшее слово слова программ. В результате все инструкции могут работать с данными во флеши как с данными в ОЗУ (только на чтение). Получается как бы расширение Гарвардской архитектуры.
Если это не устраивает (картинки, фонты, другие большие массивы) - массив в асмовый файл и функцию для доступа с использованием инструкций табличного чтения. Но будьте готовы к уменьшению общей скорости.
Diz
Плюс есть некоторые тонкости с упаковкой структур (аттрибут packed).

Например, если идет байтовый массив, то каждые два байта упаковываются в слово и
занимают 2 байта команды(третий - пустой). При обращении к такому массиву через
указатель иногда получается чтение по нечетному адресу - и выпадение в Address_Error.
YAM
Понятно, спасибо...
Судя по всему IAR вообще не заморачивается с упаковкой...
Alex B._
Цитата(Diz @ Feb 15 2008, 00:34) *
Плюс есть некоторые тонкости с упаковкой структур (аттрибут packed).
Например, если идет байтовый массив, то каждые два байта упаковываются в слово и
занимают 2 байта команды(третий - пустой). При обращении к такому массиву через
указатель иногда получается чтение по нечетному адресу - и выпадение в Address_Error.

На самоме деле packed для байтовых массивов не нужен, элементы массива и без модификатора размещаются по два в слове. packed нужен для размешения элементов структуры размером больше байта по невыровненному адресу. Тем не менее, компилятор все нормально отрабатывает, не знаю, какие у вас проблемы:

Код
1:                
2:                 typedef struct __foo
3:                 {
4:                     char a;
5:                     int  x[2] __attribute__ ((packed));
6:                 } foo;
7:                
8:                 volatile foo doo;
9:                
10:                int main(void)
11:                {
12:                    volatile int *p;
13:                    
14:                    p = &doo.x[0];
15:                    
16:                    *p = 0x1245;
00280  BFC801     mov.b 0x0801,0x0000
00282  B3C450     mov.b #0x45,0x0000
00284  B7E801     mov.b 0x0000,0x0801
00286  BFC802     mov.b 0x0802,0x0000
00288  B3C120     mov.b #0x12,0x0000
0028A  B7E802     mov.b 0x0000,0x0802
0028C  37FFFF     bra 0x00028c

Код
External Symbols in Data Memory (by address):

                    0x0800                  _doo

понятное дело, что оверхеда будет немеряно, потому как байтовые инструкции используются (mov.b, ze.cool.gif, но проблем с кодом не будет

Цитата(YAM @ Feb 15 2008, 11:06) *
Понятно, спасибо...
Судя по всему IAR вообще не заморачивается с упаковкой...

IAR dsPIC последний (1.30) структуры паковать не умеет...
YAM
Не, у вас doo в ОЗУ...
Для IAR:
<PRE>
typedef struct
{
char a;
int b;
char c;
long d;
} _ms;
static const _ms MS =
{
0x01,
0x0203,
0x04,
0x05060708
};
const char *uk;
int b;
uk = (const char *)&MS;
b = sizeof(MS);
while(b--)
{
send(*uk++);
}
</PRE>
Тут будет передано 10 байт в таком порядке:
1,0,3,2,4,0,8,7,6,5
Diz
Да, насчет упаковки просто байтового массива я был неправ - в любом случае располагается
по двум младшим байтам.

Попадание в __AddressError будет, скажем, вот на таком примере (вместо rs232_tx
подставить нужную функцию по вкусу) :

Код
    typedef struct
    {
        uint a  __attribute__ ((packed));
        uchar b[3] __attribute__ ((packed));
        uint c[4] __attribute__ ((packed));
    } example_struct_t;

    const example_struct_t exStruct = { 1, {2, 3, 4}, {6, 7, 8, 9} };

    const uint * cPtr;

    cPtr = exStruct.c;

    for ( uint i= 0; i< 4; i++)
    {
        rs232_tx_hex_uint( *cPtr++);
    }

//

14579                      .section    .const,psv
14580                         .align    2
14581                     _exStruct.3984:
14582 0000 01 00               .word    1
14583 0002 02                  .byte 2
14584 0003 03                  .byte 3
14585 0004 04                  .byte 4
14586 0005 06 00               .word    6
14587 0007 07 00               .word    7
14588 0009 08 00               .word    8
14589 000b 09 00               .word    9

//

14638 000008  58 00 20         mov    #_exStruct.3984+5,w8
14639 00000a  D9 00 20         mov    #_exStruct.3984+13,w9
14640                  .L2:
14660 00000c  38 00 78         mov    [w8++],w0
14661 00000e  00 00 07         rcall    ___rs232_tx_hex_uint
14663 000010  89 0F 54         sub    w8,w9,[w15]
14664                      .set ___BP___,75
14665 000012  00 00 3A         bra    nz,.L2
Alex B._
Цитата(Diz @ Feb 15 2008, 13:40) *
Попадание в __AddressError будет, скажем, вот на таком примере

да, все правильно. Но это будет верно для всех архитектур с разрядностью слова больше 8 бит, вне зависимости от компилятора. Погорячился я - конечно же компилятор упаковку не учитывает
Diz
Попутно обнаружился забавный глюк:

Код
typedef struct
{
    uint a;
    uint b[];
} test_struct_t;

const test_struct_t testSt1 = {1, {0,0,0,0,0,0,0,0}};
const test_struct_t testSt2 = {0, {1,0,0,0,0,0,0,0}};
const test_struct_t testSt3 = {0, {0,0,0,0,0,0,0,0}};

//


14565                      .global    _testSt3; export
14566                      .section    .const,psv
14567                         .align    2
14568                     _testSt3:
14569 0000 00 00               .skip    2
14570                         .global    _testSt2; export
14571                         .align    2
14572                     _testSt2:
14573 0002 00 00               .word    0
14574 0004 01 00               .word    1
14575 0006 00 00               .word    0
14576 0008 00 00               .word    0
14577 000a 00 00               .word    0
14578 000c 00 00               .word    0
14579 000e 00 00               .word    0
14580 0010 00 00               .word    0
14581 0012 00 00               .word    0
14582                         .global    _testSt1; export
14583                         .align    2
14584                     _testSt1:
14585 0014 01 00               .word    1
14586 0016 00 00               .word    0
14587 0018 00 00               .word    0
14588 001a 00 00               .word    0
14589 001c 00 00               .word    0
14590 001e 00 00               .word    0
14591 0020 00 00               .word    0
14592 0022 00 00               .word    0
14593 0024 00 00               .word    0


Размер testSt3 вычисляется неверно - нули в массиве игнорируются.
Alex B._
Цитата(Diz @ Feb 15 2008, 15:15) *
Попутно обнаружился забавный глюк:

версия компилера какая?
Diz
Должна быть 3.02 - точно смогу сказать в понедельник.
Diz
Да, 3.02:

pic30-coff-gcc.exe (GCC) 4.0.3 (dsPIC30, Microchip v3_02) (A) Build date: Nov 9 2007
__C30_VERSION__ == 302
Alex B._
Цитата(Diz @ Feb 18 2008, 13:38) *
Да, 3.02:
pic30-coff-gcc.exe (GCC) 4.0.3 (dsPIC30, Microchip v3_02) (A) Build date: Nov 9 2007
__C30_VERSION__ == 302

псб, завтра проверю на 3.01. последнюю версию невозможно использовать хотя бы из-за этого:
http://forum.microchip.com/tm.aspx?m=299297
Diz
Спасибо за инфу.

Недавно в 3.02 попался еще один баг, довольно серьезный - возврат значения функции
в неверном регистре. В довольно специфичном случае - switch и три case, два из них
пустые, оптимизация -O2. Если получится воссоздать ситуацию, напишу подробнее.
Alex B._
Цитата(Diz @ Feb 19 2008, 10:31) *
Если получится воссоздать ситуацию, напишу подробнее.

хм...
Diz
Воссоздать - убрать весь лишний мусор и оставить баг в чистом виде :-)

Вот:

Код

typedef void *(*fptr_t)( uint);

fptr_t func2( uint Event)
{
    return (fptr_t) 0;
}

fptr_t func1( uint Event)
{
    switch ( Event)
    {
    case 1:                
        nop();
        return (fptr_t) 0;

    case 5:
        return (fptr_t) 0;

    case 6:        
        return (fptr_t) 0;
    }
    return (fptr_t) func2;
}

//
14312                      .global    _func2; export
14313                  _func2:
14336 000000  00 00 05         retlw    #0,w0
//
14359                      .global    _func1; export
14360                  _func1:
14383 000002  E1 0F 50         sub    w0,#1,[w15]
14385 000004  00 00 32         bra    z,.L7
14387 000006  00 00 31         bra    geu,.L13
14388                  .L6:
14390 000008  01 00 20         mov    #handle(_func2),w1
14392 00000a  00 00 06         return    
14393                  .L14:
14395                  .L13:
14397 00000c  65 00 50         sub    w0,#5,w0
14398 00000e  80 00 EB         clr    w1
14399 000010  E1 0F 50         sub    w0,#1,[w15]
14401 000012  00 00 3E         bra    gtu,.L6
14403 000014  01 00 78         mov    w1,w0
14404 000016  00 00 06         return    
14405 000018  00 00 37         bra    .L14
14406                  .L7:
14408 00001a  00 00 00         nop    
14409 00001c  00 00 20         mov.w    #0,w0
14411 00001e  00 00 06         return    
14412 000020  00 00 37         bra    .L14



//


Указатель на func2 возвращается в регистре w1 вместо w0 (а в w0 может быть все, что угодно).
Если, скажем, в case 5: добавить nop(), то все корректно (хотя и не оптимально, мягко скажем):

Код
14360                  _func1:
14383 000002  E5 0F 50         sub    w0,#5,[w15]
14385 000004  00 00 32         bra    z,.L8
14386 000006  80 00 EB         clr    w1
14387 000008  E6 0F 50         sub    w0,#6,[w15]
14389 00000a  00 00 32         bra    z,.L10
14391 00000c  01 00 20         mov    #handle(_func2),w1
14393 00000e  E1 0F 50         sub    w0,#1,[w15]
14395 000010  00 00 32         bra    z,.L14
14396                  .L10:
14398 000012  01 00 78         mov    w1,w0
14399 000014  00 00 06         return    
14400                  .L15:
14402                  .L8:
14404 000016  00 00 00         nop    
14405 000018  00 00 20         mov.w    #0,w0
14407 00001a  00 00 06         return    
14408 00001c  00 00 37         bra    .L15
14409                  .L14:
14411 00001e  00 00 00         nop    
14412 000020  00 00 20         mov.w    #0,w0
14414 000022  00 00 06         return    
14415 000024  00 00 37         bra    .L15
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.