Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MEMMAP = 2; на LPC2146
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
meister
Здравствуйте,

код ниже работает с MEMMAP = 1 и не работает с MEMMAP = 2 (переключается препроцессором). Может, я какую мелочь упустил?

Спасибо.

Код
#include <iolpc2146.h>
#include <intrinsics.h>

#define BIT_(x) (1 << (x))

namespace
{
    unsigned const DBG_PIN = 24;
}

enum vec_id_t
{
    VEC_RESET = 0,
    VEC_UNDEF = 1,
    VEC_SWI = 2,
    VEC_PREFETCH = 3,
    VEC_DATA_ABORT = 4,
    VEC_RESERVED__ = 5,
    VEC_IRQ = 6,
    VEC_FIQ = 7,
    
    VEC_TOTAL_NUM = 8
};

#define MEMMAP_OPTION (1)

#if 1 == MEMMAP_OPTION
    #define VIC_ISR __irq __arm
#else
    #pragma location=0x40000000
    __no_init unsigned intvec[VEC_TOTAL_NUM * 2];
    
    #define VIC_ISR
#endif

VIC_ISR void irq_timer(void);
VIC_ISR void non_vectored_handler(void);

extern "C" __irq __arm void reset_handler(void) {}
extern "C" __irq __arm void undef_handler(void) {}
extern "C" __irq __arm void swi_handler(void) {}
extern "C" __irq __arm void prefetch_handler(void) {}
extern "C" __irq __arm void data_handler(void) {}    
extern "C" __irq __arm void fiq_handler(void) {}

#if 2 == MEMMAP_OPTION
    __irq __arm void irq_handler(void)
    {
        typedef void (VIC_ISR * handler_t)(void);
        handler_t h = reinterpret_cast<handler_t>(VICVectAddr);
        (*h)();
    }
#endif

void hw_init(void)
{
    PCON = 0;
    PCONP = BIT_(1);

    VPBDIV = 1;
    
    MAMCR = 0;
    MAMTIM = 2;
    MAMCR = 2;
    
    
    MEMMAP = MEMMAP_OPTION;
    
#if 2 == MEMMAP_OPTION
    for (unsigned i = 0; i < VEC_TOTAL_NUM; ++i)
    {
        intvec[i] = 0x18F09FE5; // ldr pc, [pc, #24];
    }
    
    intvec[VEC_TOTAL_NUM + VEC_RESET] = reinterpret_cast<unsigned>(&reset_handler);
    intvec[VEC_TOTAL_NUM + VEC_UNDEF] = reinterpret_cast<unsigned>(&undef_handler);
    intvec[VEC_TOTAL_NUM + VEC_SWI] = reinterpret_cast<unsigned>(&swi_handler);
    intvec[VEC_TOTAL_NUM + VEC_PREFETCH] = reinterpret_cast<unsigned>(&prefetch_handler);
    intvec[VEC_TOTAL_NUM + VEC_DATA_ABORT] = reinterpret_cast<unsigned>(&data_handler);
    intvec[VEC_TOTAL_NUM + VEC_IRQ] = reinterpret_cast<unsigned>(&irq_handler);
    intvec[VEC_TOTAL_NUM + VEC_FIQ] = reinterpret_cast<unsigned>(&fiq_handler);
#endif

    VICSoftIntClear = ~0;
    VICIntEnClear = ~0;
    VICIntSelect = 0;

    VICVectAddr0 = reinterpret_cast<unsigned long>(&irq_timer);
    VICVectCntl0 = 4 + BIT_(5);
    VICIntSelect &= ~BIT_(4);    
    VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler);

    VICIntEnable = BIT_(4);

    VICProtection = 1;
    VICVectAddr = 0;    

    T0IR = 0xFF;
    T0TCR = BIT_(0) + BIT_(1);
    T0CTCR = 0;
    T0PR = 0;
    T0PC = 0;
    T0MCR = 0;
    T0CCR = 0;
    T0EMR = 0;
    T0TCR = BIT_(0);
    
    SCS = BIT_(1);
    PINSEL2 &= ~BIT_(3);
    FIO1DIR |= BIT_(DBG_PIN);
}

namespace
{
    unsigned const TIMER_TICK = 20000000 / 1000;
}

void start(void)
{
    T0MR0 = T0TC + TIMER_TICK;
    T0MCR_bit.MR0INT = 1;
    __enable_interrupt();
}

int main(void)
{
    hw_init();
    start();
    while (true) {}
}

VIC_ISR void irq_timer(void)
{
    T0MR0 += TIMER_TICK;
    FIO1PIN ^= BIT_(DBG_PIN);
    T0IR = T0IR;
    VICVectAddr = 0;
}

VIC_ISR void non_vectored_handler(void)
{
    VICVectAddr = 0;
}
alexander55
Цитата(meister @ Jan 15 2008, 14:38) *

Для отладки в RAM кроме MEMMAP=2, нужно перестроить распределение памяти для линкера.
meister
Цитата(alexander55 @ Jan 15 2008, 14:53) *
Для отладки в RAM кроме MEMMAP=2, нужно перестроить распределение памяти для линкера.


Идей кроме как сдвинуть нижнюю границу RAM - нет.

-DRAMSTART=40000040
-DRAMEND=40007FFF

Не работает. Да и не используются у меня в этом фрагменте нижние адреса RAM.
alexander55
Цитата(meister @ Jan 15 2008, 14:58) *
Идей кроме как сдвинуть нижнюю границу RAM - нет.

-DRAMSTART=40000040
-DRAMEND=40007FFF

Не работает. Да и не используются у меня в этом фрагменте нижние адреса RAM.

А что с ROM ?
meister
Цитата(alexander55 @ Jan 15 2008, 15:48) *
А что с ROM ?


-DROMSTART=00000040
-DROMEND=0003FFFF

-Z(CODE)INTVEC=00-3F
-Z(CODE)ICODE,DIFUNCT=ROMSTART-ROMEND
-Z(CODE)SWITAB=ROMSTART-ROMEND
-Z(CODE)CODE=ROMSTART-ROMEND
-Z(CONST)CODE_ID=ROMSTART-ROMEND
-Z(CONST)INITTAB,DATA_ID,DATA_C=ROMSTART-ROMEND
-Z(CONST)CHECKSUM=ROMSTART-ROMEND

Но это же должно быть абсолютно без разницы, раз уж работает с MEMMAP = 1 - только место, откуда будут браться вектора прерываний изменится. Вот это у меня точно правильно?

Код
intvec[i] = 0x18F09FE5; // ldr pc, [pc, #24];
alexander55
Цитата(meister @ Jan 15 2008, 16:03) *
-DROMSTART=00000040
-DROMEND=0003FFFF

Сделайте так.
-DROMSTART=0
-DROMEND=0
meister
Цитата(alexander55 @ Jan 15 2008, 16:40) *
Сделайте так.
-DROMSTART=0
-DROMEND=0


В общем-то ожидаемо:

Building configuration: memmap2 - Debug
Updating build tree...
entry.cpp
Linking
Error[e16]: Segment ICODE (size: 0xec align: 0x2) is too long for segment definition. At least 0xec more bytes needed. The problem occurred while
processing the segment placement command "-Z(CODE)ICODE,DIFUNCT=ROMSTART-ROMEND", where at the moment of placement the available
memory ranges were "-none-"
Reserved ranges relevant to this placement:
0-1f INTVEC

Total number of errors: 1
Total number of warnings: 0
alexander55
Цитата(meister @ Jan 15 2008, 16:53) *

У Вас жалуется линкер на ICODE. Рекомендую посмотреть примерчик для размещения в RAM и сделать по аналогии.
М.б.
-Z(CODE)INTVEC=40000000-4000003f
meister
Цитата(alexander55 @ Jan 15 2008, 17:16) *
У Вас жалуется линкер на ICODE. Рекомендую посмотреть примерчик для размещения в RAM и сделать по аналогии.
М.б.
-Z(CODE)INTVEC=40000000-4000003f


В том-то и суть, что мне надо то MEMMAP=1 то MEMMAP=2 (поэтому менять нельзя, да и мне кажется незачем). Непонятно, почему надо копаться в настройках линковщика. Вся разница этих двух режимов - откуда процессор будет вынимать байты. Если из flash - все работает. Если из RAM - память нужно случайно не стереть. Я никуда (кроме стека, который далеко) не пишу.
Сергей Борщ
Цитата(meister @ Jan 15 2008, 18:25) *
Вся разница этих двух режимов - откуда процессор будет вынимать байты.
На самом деле разницы никакой - он во обоих случаях берет байты из нулевых адресов. Отражен туда кусочек ОЗУ или нет - для него не важно. Посмотрите вот этот проект - мне удалось сделать выбор флеш/ОЗУ выбором скрипта линкера и скрипта отладчика (.mac). Исходники идентичны для обоих случаев.
meister
Цитата(Сергей Борщ @ Jan 15 2008, 21:56) *
На самом деле разницы никакой - он во обоих случаях берет байты из нулевых адресов.


Я имел ввиду физические адреса ну или саму память.

Код
        for( i = 0; i < 0x40; i += 4 )
        {
            tmp = __readMemory32(0x40000000 + i, "Memory");
            __writeMemory32(tmp,0x00000000 + i, "Memory");
        }


Ну это понятно, хоть мне так и не подойдет - у меня там branch стоят, да и перемапивание у мена делается не просто так - там нужно другие обработчики подставить (поменять основные на заглушки), пока основные будут стерты.

Перед тем, как я сегодня ушел с работы - я поменял endian у 0x18F09FE5 и процессор стал заходить в прерывание. Один раз. Потом опять ломается. Попробовал собрать инструкцию ldr pc, [pc, #24] руками - так и получается.
Сергей Борщ
Цитата(meister @ Jan 15 2008, 21:16) *
Ну это понятно, хоть мне так и не подойдет - у меня там branch стоят, да и перемапивание у мена делается не просто так - там нужно другие обработчики подставить (поменять основные на заглушки), пока основные будут стерты.
ууууу... А надо ли стирать основные? Потенциальная возможность получить полностью нерабочее устройство после сбоя во время перепрошивки.
Гляньте тут и тут Если я правильно догадался, и вы пишете загрузчик.
meister
Проблема с MEMMAP = 2; была решена написанием "нормального" обработчика сброса

Код
    org    0x00
__program_start:        LDR pc, [pc, #24]
        undefvec:        B           undef_handler
        swivec:            B           swi_handler
        pabtvec:        B           prefetch_handler
        dabtvec:        B           data_handler

    org 0x18
        irqvec:            B            irq_handler
        fiqvec:         B           fiq_handler
        
    org 0x20
        DC32                        ?cstartup


Код
intvec[VEC_TOTAL_NUM + VEC_RESET] = ARM7TDMI_MEM_32(0x00000020);


и только затем smile.gif

Код
MEMMAP = MEMMAP_OPTION;


Цитата(Сергей Борщ @ Jan 15 2008, 22:56) *
Если я правильно догадался, и вы пишете загрузчик.


Правильно smile.gif Спасибо за ссылки, буду смотреть и думать.
meister
Я тут дебажил smile.gif и наткнулся на такой код:

// 287 __enable_interrupt();
_BLF ??EnI_t,??rT??EnI_t

который, я подозреваю, передает управление в стертый сектор и программа ломается. На что переписать __enable_interrupt и __disable_interrupt? Я попробовал на

Код
    MODULE  BOOTLOADER_UTIL;
    PUBLIC  bootloader_enable_interrupt;
    PUBLIC  bootloader_disable_interrupt;
    RSEG    BOOTLOADERCODE
    
    CODE32    

bootloader_enable_interrupt:
    PUSH    {r0}
    MRS     r0, cpsr
    ORR     r0, r0, #192
    MSR     cpsr_c, r0
    POP     {r0}
    BX      lr;

bootloader_disable_interrupt:
    PUSH    {r0}
    MRS     r0, cpsr
    bic     r0, r0, #192
    MSR     cpsr_c, r0
    POP     {r0}
    BX      lr;

    LTORG;
    ENDMOD;


не работает совсем sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.