Jump to content

    
Sign in to follow this  
3.14

FreeRTOS + LPC2378

Recommended Posts

Прерывания разрешаются, насколько я проникся, после инита всей системы. Например, имею I2C LCD, обмен которого осуществляется через прерывания, соответсвенно на ините этого LCD (если его вначале main включать) все и встанет.

а, ну это разумеется, да. что, кстати, неудобно - приходится инициализацию делать уже в многозадачном режиме, то есть через задницу

 

Конец инициализации "всей системы" определяете лично Вы вызовом vTaskStartScheduler( ) причем уж точно в main() и после инициализации всякого своего железа. Медленно инициализирующееся железо

подвешивается вместо IdleTask (в оригинальной реализации Hook предусмотрен) и в конце цепочки Hook снимается. Единствено, что для IdleTask задержку свою писать надо, обо системная естественно не работает.

 

Может стоит докуменацию на FreeRTOS почитать а?

Share this post


Link to post
Share on other sites
Прерывания разрешаются, насколько я проникся, после инита всей системы. Например, имею I2C LCD, обмен которого осуществляется через прерывания, соответсвенно на ините этого LCD (если его вначале main включать) все и встанет.
Прерывания не будут вызываться, пока они не разрешены глобально (не сброшен I_Bit в CPSR). Это происходит после старта ОС, в момент восстановления контекста первого процесса. Не пользуюсь я FreeRTOS, но специально для вас слазил в исходники:

    /* The last thing onto the stack is the status register, which is set for
    system mode, with interrupts enabled. */
    *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR;

    #ifdef KEIL_THUMB_INTERWORK
    {        
        /* We want the task to start in thumb mode. */
        *pxTopOfStack |= portTHUMB_MODE_BIT;
    }
    #endif

Вот тут готовится значение CPSR которое разрешит прерывания при старте задачи. До этого прерывания глобально запрещены, если вы их нигде случайно не разрешили.

 

 

Отправил и "въехал" - ну так или делайте инициализацию не прерываниями а поллингом или обкладывайте ваш LCD семафором, который не даст с ним работать пока инициализация не закончилась. А инициализацию в задачу запихайте.

Share this post


Link to post
Share on other sites

Прямо из живого FreeRTOS проекта инициализацию выдрал:

//---------------------------------------------------------------------------
// Starts all the other tasks, then starts the scheduler.
//---------------------------------------------------------------------------
void main( void )
{
    // Setup the processor.
    init_cpu();
    init_delay_timer();    
    // Start Console and Console Task.
    init_console( COM_TEST_BAUD_RATE, CONSOLE_PRIORITY );
    // Hello World :-)
    boutchar( XON );
    hellomessage();
    
    xIdleTaskCreate( 200 );
extern ulong RAMEND;
extern ulong RAMSTART;
#pragma segment="HEAP_RTOS"
    bprintf( "\tRAM use:%u Heap:%8X Size:%i",
                                 (ulong)(__segment_begin( "HEAP_RTOS" ))-(ulong)&RAMSTART,
                                 __segment_begin( "HEAP_RTOS" ),
                                (ulong)&RAMEND - (ulong)(__segment_begin( "HEAP_RTOS" )) + 1 );
    if( copyprotect() )
        status_word |= STW_PROTECT;    
                    
    if( WDMOD_bit.WDTOF )
        printline( "\tWatchdog Reset Granted!");

    init_SLIC_data();
    
    init_AXE();

    vSetIdleHook( init_system );
    
    // Start the scheduler.
    vTaskStartScheduler( 0 );             // 0 - intertal timer 1 - external timer
}


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
void init_system()
{
    init_delay_timer();
ulong ii;
    bprintf( "\tCheck CPU -LPC%i %s", iap_getid(), (status_word & STW_PROTECT) ? "" : "Evolution" );

    boutchar( XON );
    cf_addhandler( "MAIN", main_cfg );

    bprintf(     "\tInit I2C  -%s", init_i2c() ? "Fail":"Done" );
    // Read 1st - Configuration
    bprintf_str(  "\t  Config  -" );
    ii = cf_parser( FALSE );
    if( ii )
        bprintf( ii == 1 ? "Empty" : "Failed" );
    else
        bprintf(  "Ok" );
    
    if( config_flags & DEVICE_OWIRE )
      {    print_str(  "\tCheck OW  -" );
        init_ow();
    }
    bprintf(     "\tInit SPI0 -%s", init_SPI0() ? "Fail":"Done" );
    bprintf(     "\tInit CPLD -%s", init_cpld()    ? "Fail":"Ok" );
    
    bprintf(     "\tInit SPI1 -%s", init_SPI1() ? "Fail":"Done" );
    
    bprintf_str( "\tLoad FPGA -" ); load_fpga( 0x20000, TRUE );

    bprintf(     "\tInit ACSL -%s", init_armsl() ? "Fail":"Ok" );

    init_dsl_post();

    init_eth_post();

    toggle_red_LED();

    // Check Maintenance Console Request
    for( ii=0; ii< 50; ii++ )
    {   if( IO0PIN_bit.P0_14 == 0 )
        {    status_word |= STW_MAINTENANCE;
            bprintf( "\nMaintenance Console Mode" );
            goto skip_application;
        }
               vDummyDelay_ms( 2 );
    }
    //----- Switch System to external 2ms Ticks -----------------------------
    bprintf_str( "\tExt Sync  -" );
    ENTER_CRITICAL();
    {
    // Set edle-sensetive Mode
    // Bug :-(
    // The steps involved in the configuration of the EXTMODE and/or EXTPOLAR would be as follow:-
    // 1. Write 0x00 to VPBDIV
    // 2. Write the desired value to EXTMODE or EXTPOLAR register
    // 3. Write the same value to VPBDIV
    // 3a. Write 0x00 to VPBDIV (additional step for INT0 )
    // 4. Restore the VPBDIV to the previously saved value or simply write to the register again
    //    with the desired value.
    VPBDIV = 0;                 // 1.
    ii = EXTMODE & ( EXTMODE_EXTMODE0|EXTMODE_EXTMODE1|EXTMODE_EXTMODE2|EXTMODE_EXTMODE3);  // Get Curent Value
    ii |= EXTMODE_EXTMODE1;
    EXTMODE = ii;             // 2.
    VPBDIV  = ii;             // 3.
    VPBDIV  = 0;              // 3a
    VPBDIV  = configBUS_CLK; // 4.

    // Select IRQ Pin 'IRQ_2MS'
    PINSEL0_bit.P_IRQ_2MS = 0x2;            // Pin to EINT1 mode

    // IRQ Handler to Temporary MS2_ISR_handler()
    VICIntSelect &= ~(1 << VIC_EINT1);         // Classifies as IRQ.
      VICVectAddr9 = (ulong)MS2_ISR_handler;     // Connect to Slot9
      VICVectCntl9 = 0x20 | VIC_EINT1;          // Enable vector interrupt for EINT1.
    VICIntEnable =  (1 << VIC_EINT1);       // Enable EINT1 2ms interrupt.

    }

    LEAVE_CRITICAL();

    // Enable 2ms in FPGA
    work_spi_reset_clr( CSPI_WR | CSPI_RES_FPGA );
    ms_check_timer = 0;
    vDummyDelay_ms( (16+1)*2 );
    if( ms_check_timer >= 16 )
    {    // Ok 2ms Present.
        ENTER_CRITICAL();
        {
        // Disable INT Generate timer 0 compare match.
        TxMCR &= (~0x01);
        // Set New Handler
//        VICIntSelect &= ~(1 << VIC_EINT1);         // Classifies as IRQ.
          VICVectAddr0 = (ulong)vPortPreemptiveTickEntry_Ext;;     // Connect to Slot9
          VICVectCntl0 = 0x20 | VIC_EINT1;          // Enable vector interrupt for EINT1.
//        VICIntEnable =  (1 << VIC_EINT1);       // Enable EINT1 2ms interrupt.
        }
        LEAVE_CRITICAL();
        bprintf( "Ok (%i)", ms_check_timer );
        // For future....
//!!        sys_reg |= (SYS_2MS_IRQ | SYS_PKT_ENABLE);
    }
    else
    {    // 2ms Failed
          VICIntEnClear = (1<< VIC_EINT1);          // Disable vector interrupt for EINT1.
        work_spi_reset( CSPI_WR | CSPI_RES_FPGA );
        bprintf( "Failed (%i)", ms_check_timer );
        goto skip_application;
    }


    //-----------------------------------------------------------------------
    
    bprintf(     "\tInit SWH  -%s", init_switch() ? "Fail":"Done" );

    printline( "Ready" );

    sys_pkt( sys_reg );


skip_application:
    xTaskCreate( CheckerProcess, "Checker", configMINIMAL_STACK_SIZE*2, NULL, CHECK_TASK_PRIORITY, NULL );

    vSetIdleHook( idle_system );
    off_red_LED();
}

Share this post


Link to post
Share on other sites

Спасибо, хочу теперь прикрутить стек uIP.

Добавил в проект исходники стека (пока кастрировал драйверную часть), откомпилировались нормально, но вот во время линковки получаю:

*** ERROR L102: EXTERNAL ATTRIBUTE MISMATCH

SYMBOL: uip_arp_draddr

MODULE: .\obj\uip_arp.obj (uip_arp)

DEFINED: .\obj\uip.obj (uip)

Чего-то я не врубаюсь в смысл ошибки. В uip_arp объявлен массив uip_arp_draddr, а в uip_arp этот массив объявляется внешним, в чем тут криминал?

Share this post


Link to post
Share on other sites
Чего-то я не врубаюсь в смысл ошибки. В uip_arp объявлен массив uip_arp_draddr, а в uip_arp этот массив объявляется внешним, в чем тут криминал?
Ну так приведите код этих объявлений.

Share this post


Link to post
Share on other sites

uip.c (UIP_FIXEDADDR=1):

#if UIP_FIXEDADDR > 0
const u16_t uip_hostaddr[2] =
  {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
   HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
const u16_t uip_arp_draddr[2] =
  {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
   HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
const u16_t uip_arp_netmask[2] =
  {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
   HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
#else
u16_t uip_hostaddr[2];       
u16_t uip_arp_draddr[2], uip_arp_netmask[2];
#endif /* UIP_FIXEDADDR */

uip_arp.h:

...
/**
* \internal Internal variables that are set using the macros
* uip_setdraddr and uip_setnetmask.
*/
extern u16_t uip_arp_draddr[2], uip_arp_netmask[2];
//u16_t uip_arp_draddr[2], uip_arp_netmask[2];
#endif /* __UIP_ARP_H__ */

если в uip_arp просто объявить этот массив (убрал extern), тогда линковщик ругается на дублирование ...

Share this post


Link to post
Share on other sites

Прерывания разрешаются, насколько я проникся, после инита всей системы. Например, имею I2C LCD, обмен которого осуществляется через прерывания, соответсвенно на ините этого LCD (если его вначале main включать) все и встанет.

а, ну это разумеется, да. что, кстати, неудобно - приходится инициализацию делать уже в многозадачном режиме, то есть через задницу

 

Конец инициализации "всей системы" определяете лично Вы вызовом vTaskStartScheduler( ) причем уж точно в main() и после инициализации всякого своего железа. Медленно инициализирующееся железо

подвешивается вместо IdleTask (в оригинальной реализации Hook предусмотрен) и в конце цепочки Hook снимается. Единствено, что для IdleTask задержку свою писать надо, обо системная естественно не работает.

 

Может стоит докуменацию на FreeRTOS почитать а?

 

Вы меня немного не так поняли. я имел в виду ситуацию, когда мне уже надо пользоваться прерываниями, но не запускать многозадачный режим - скажем, инициализировать внешние объекты, используя рабочие библиотеки. режим поллинга тут в принципе подходит, но для этого надо писать отдельный код

 

 

...А инициализацию в задачу запихайте.

вот это я и имел в виду, когда писал про "задницу". получается не очень красиво. а когда еще желательно это делать не в любой момент, притом стопить другие задачи, притом тоже не как попало...

 

uip.c (UIP_FIXEDADDR=1):
#if UIP_FIXEDADDR > 0
const u16_t uip_hostaddr[2] =
  {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
   HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
const u16_t uip_arp_draddr[2] =
  {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
   HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
const u16_t uip_arp_netmask[2] =
  {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
   HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
#else
u16_t uip_hostaddr[2];       
u16_t uip_arp_draddr[2], uip_arp_netmask[2];
#endif /* UIP_FIXEDADDR */

uip_arp.h:

...
/**
* \internal Internal variables that are set using the macros
* uip_setdraddr and uip_setnetmask.
*/
extern u16_t uip_arp_draddr[2], uip_arp_netmask[2];
//u16_t uip_arp_draddr[2], uip_arp_netmask[2];
#endif /* __UIP_ARP_H__ */

если в uip_arp просто объявить этот массив (убрал extern), тогда линковщик ругается на дублирование ...

 

ну так он у Вас описан как const, а объявление не константное. может, в этом дело? на месте линкера я бы обиделся

Share this post


Link to post
Share on other sites

А это случайно не проблема со сменой контроллера прерываний в 2300 серии? Переносить старые исходники обработчика прерываний непрямую нельзя.

Yes, the LPC23xx and LPC24xx use the PL192 VIC while all the older chips use

the PL190 VIC. Go to www.arm.com and search for PL190 and PL192.

 

Another important difference is the address of the register where you read

the current handler address -- VICAddress instead of VICVectAddr. You now

need a "ldr pc, [pc, #-0x0120]" at address 0x18 instead of a "ldr pc, [pc,

#-0x0FF0]".

 

Karl Olsen

Share this post


Link to post
Share on other sites

Обработчик, в итоге, остался старый, а вто его объявление пришлось заменить. Особой разницы в VIC-ах я не заметил, векторов стало 32 (отсюда и новое смещение) и дефаултовый вектор теперь отсутствует.

Share this post


Link to post
Share on other sites
Вы меня немного не так поняли. я имел в виду ситуацию, когда мне уже надо пользоваться прерываниями, но не запускать многозадачный режим - скажем, инициализировать внешние объекты, используя рабочие библиотеки. режим поллинга тут в принципе подходит, но для этого надо писать отдельный код

Пользуйтесь на здроровье! Система пользуется одним единственным таймерным прерыванием и источник этого прерывания инициализируется при старте шедулера. Глобально прерывания (и естественно конкретные источники) могут быть разрешены и использоваться и до старта шедулера.

Я в приведенном куске так не делаю по одной причине - когда запущена система уже работает консоль и инициализацию наблюдать гороаздо приятнее :). Только с этой целью висит Hook.

Share this post


Link to post
Share on other sites
Пользуйтесь на здроровье! Система пользуется одним единственным таймерным прерыванием и источник этого прерывания инициализируется при старте шедулера. Глобально прерывания (и естественно конкретные источники) могут быть разрешены и использоваться и до старта шедулера.

Я в приведенном куске так не делаю по одной причине - когда запущена система уже работает консоль и инициализацию наблюдать гороаздо приятнее :). Только с этой целью висит Hook.

да, действительно. свое замечание снимаю. у меня зато есть другой вопрос :) почему же все-таки при использовании 71x_init.s проект с FreeRTOS у меня виснет? может это быть связано с установкой пользовательского режима, и если да - то как?

Edited by sergik_vrn

Share this post


Link to post
Share on other sites

Пытаюсь завести FreeRTOS на этом же камне и RealView компиллере, почему-то при старте первой же задачи на строчке:

 

STMDB     R13!,{R4,R14}

 

Проц вылетает в Undef_Handler :05: .

 

Чего-то даже не пойму, а куда копать? :07:

 

И еще, в последнем realview исчез атрибут __task, не совсем понятно, он теперь просто не нужен или как? :)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this