LPC1752 Keil - Stuck at _idle_thread

ChibiOS public support forum for topics related to the NXP LPC family of Cortex-M micro-controllers.
kunilkuda
Posts: 4
Joined: Thu Jun 12, 2014 11:02 am

LPC1752 Keil - Stuck at _idle_thread

Postby kunilkuda » Thu Jun 12, 2014 11:16 am

Hello,

I'm beginner in ChibiOS, and I want to use it for my project. Currently my problem is that the ChibiOS stuck at _idle_thread(). It's not hang or hardfault, it just that it won't switch back to main() thread.

I've configured the ChibiOS as cooperative scheduling RTOS. The SysTickVector is working (I can see it jump into it but it doesn't switch the task), SVCallVector is also running (no HardFault).

So I just wonder why it keep running at _idle_thread() ? Do I need to use chThdYield() in _idle_thread() to make it switch to the main() task ? Which variable that I need to watch for list of task, and whether the task is ready / waiting for event ?

My 'chconf.h' is as below

Code: Select all

#ifndef _CHCONF_H_
#define _CHCONF_H_

/*===========================================================================*/
/**
 * @name Kernel parameters and options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   System tick frequency.
 * @details Frequency of the system timer that drives the system ticks. This
 *          setting also defines the system tick time unit.
 */
#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY                    1000
#endif

/**
 * @brief   Round robin interval.
 * @details This constant is the number of system ticks allowed for the
 *          threads before preemption occurs. Setting this value to zero
 *          disables the preemption for threads with equal priority and the
 *          round robin becomes cooperative. Note that higher priority
 *          threads can still preempt, the kernel is always preemptive.
 *
 * @note    Disabling the round robin preemption makes the kernel more compact
 *          and generally faster.
 */
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM                 0
#endif

/**
 * @brief   Managed RAM size.
 * @details Size of the RAM area to be managed by the OS. If set to zero
 *          then the whole available RAM is used. The core memory is made
 *          available to the heap allocator and/or can be used directly through
 *          the simplified core memory allocator.
 *
 * @note    In order to let the OS manage the whole RAM the linker script must
 *          provide the @p __heap_base__ and @p __heap_end__ symbols.
 * @note    Requires @p CH_USE_MEMCORE.
 */
#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_MEMCORE_SIZE                 0
#endif

/**
 * @brief   Idle thread automatic spawn suppression.
 * @details When this option is activated the function @p chSysInit()
 *          does not spawn the idle thread automatically. The application has
 *          then the responsibility to do one of the following:
 *          - Spawn a custom idle thread at priority @p IDLEPRIO.
 *          - Change the main() thread priority to @p IDLEPRIO then enter
 *            an endless loop. In this scenario the @p main() thread acts as
 *            the idle thread.
 *          .
 * @note    Unless an idle thread is spawned the @p main() thread must not
 *          enter a sleep state.
 */
#if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__)
#define CH_NO_IDLE_THREAD               FALSE
#endif

/** @} */

/*===========================================================================*/
/**
 * @name Performance options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   OS optimization.
 * @details If enabled then time efficient rather than space efficient code
 *          is used when two possible implementations exist.
 *
 * @note    This is not related to the compiler optimization options.
 * @note    The default is @p TRUE.
 */
#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__)
#define CH_OPTIMIZE_SPEED               TRUE
#endif

/** @} */

/*===========================================================================*/
/**
 * @name Subsystem options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Threads registry APIs.
 * @details If enabled then the registry APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__)
#define CH_USE_REGISTRY                 TRUE
#endif

/**
 * @brief   Threads synchronization APIs.
 * @details If enabled then the @p chThdWait() function is included in
 *          the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
#define CH_USE_WAITEXIT                 TRUE
#endif

/**
 * @brief   Semaphores APIs.
 * @details If enabled then the Semaphores APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
#define CH_USE_SEMAPHORES               TRUE
#endif

/**
 * @brief   Semaphores queuing mode.
 * @details If enabled then the threads are enqueued on semaphores by
 *          priority rather than in FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special requirements.
 * @note    Requires @p CH_USE_SEMAPHORES.
 */
#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__)
#define CH_USE_SEMAPHORES_PRIORITY      FALSE
#endif

/**
 * @brief   Atomic semaphore API.
 * @details If enabled then the semaphores the @p chSemSignalWait() API
 *          is included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_SEMAPHORES.
 */
#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__)
#define CH_USE_SEMSW                    TRUE
#endif

/**
 * @brief   Mutexes APIs.
 * @details If enabled then the mutexes APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
#define CH_USE_MUTEXES                  TRUE
#endif

/**
 * @brief   Conditional Variables APIs.
 * @details If enabled then the conditional variables APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_MUTEXES.
 */
#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__)
#define CH_USE_CONDVARS                 TRUE
#endif

/**
 * @brief   Conditional Variables APIs with timeout.
 * @details If enabled then the conditional variables APIs with timeout
 *          specification are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_CONDVARS.
 */
#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__)
#define CH_USE_CONDVARS_TIMEOUT         TRUE
#endif

/**
 * @brief   Events Flags APIs.
 * @details If enabled then the event flags APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
#define CH_USE_EVENTS                   TRUE
#endif

/**
 * @brief   Events Flags APIs with timeout.
 * @details If enabled then the events APIs with timeout specification
 *          are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_EVENTS.
 */
#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__)
#define CH_USE_EVENTS_TIMEOUT           TRUE
#endif

/**
 * @brief   Synchronous Messages APIs.
 * @details If enabled then the synchronous messages APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
#define CH_USE_MESSAGES                 TRUE
#endif

/**
 * @brief   Synchronous Messages queuing mode.
 * @details If enabled then messages are served by priority rather than in
 *          FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special requirements.
 * @note    Requires @p CH_USE_MESSAGES.
 */
#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__)
#define CH_USE_MESSAGES_PRIORITY        FALSE
#endif

/**
 * @brief   Mailboxes APIs.
 * @details If enabled then the asynchronous messages (mailboxes) APIs are
 *          included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_SEMAPHORES.
 */
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
#define CH_USE_MAILBOXES                TRUE
#endif

/**
 * @brief   I/O Queues APIs.
 * @details If enabled then the I/O queues APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__)
#define CH_USE_QUEUES                   TRUE
#endif

/**
 * @brief   Core Memory Manager APIs.
 * @details If enabled then the core memory manager APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__)
#define CH_USE_MEMCORE                  TRUE
#endif

/**
 * @brief   Heap Allocator APIs.
 * @details If enabled then the memory heap allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or
 *          @p CH_USE_SEMAPHORES.
 * @note    Mutexes are recommended.
 */
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
#define CH_USE_HEAP                     TRUE
#endif

/**
 * @brief   C-runtime allocator.
 * @details If enabled the the heap allocator APIs just wrap the C-runtime
 *          @p malloc() and @p free() functions.
 *
 * @note    The default is @p FALSE.
 * @note    Requires @p CH_USE_HEAP.
 * @note    The C-runtime may or may not require @p CH_USE_MEMCORE, see the
 *          appropriate documentation.
 */
#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP              FALSE
#endif

/**
 * @brief   Memory Pools Allocator APIs.
 * @details If enabled then the memory pools allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
#define CH_USE_MEMPOOLS                 TRUE
#endif

/**
 * @brief   Dynamic Threads APIs.
 * @details If enabled then the dynamic threads creation APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_USE_WAITEXIT.
 * @note    Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS.
 */
#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__)
#define CH_USE_DYNAMIC                  TRUE
#endif

/** @} */

/*===========================================================================*/
/**
 * @name Debug options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Debug option, system state check.
 * @details If enabled the correct call protocol for system APIs is checked
 *          at runtime.
 *
 * @note    The default is @p FALSE.
 */
#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_SYSTEM_STATE_CHECK       FALSE
#endif

/**
 * @brief   Debug option, parameters checks.
 * @details If enabled then the checks on the API functions input
 *          parameters are activated.
 *
 * @note    The default is @p FALSE.
 */
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_CHECKS            FALSE
#endif

/**
 * @brief   Debug option, consistency checks.
 * @details If enabled then all the assertions in the kernel code are
 *          activated. This includes consistency checks inside the kernel,
 *          runtime anomalies and port-defined checks.
 *
 * @note    The default is @p FALSE.
 */
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_ASSERTS           FALSE
#endif

/**
 * @brief   Debug option, trace buffer.
 * @details If enabled then the context switch circular trace buffer is
 *          activated.
 *
 * @note    The default is @p FALSE.
 */
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_TRACE             FALSE
#endif

/**
 * @brief   Debug option, stack checks.
 * @details If enabled then a runtime stack check is performed.
 *
 * @note    The default is @p FALSE.
 * @note    The stack check is performed in a architecture/port dependent way.
 *          It may not be implemented or some ports.
 * @note    The default failure mode is to halt the system with the global
 *          @p panic_msg variable set to @p NULL.
 */
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK       TRUE
#endif

/**
 * @brief   Debug option, stacks initialization.
 * @details If enabled then the threads working area is filled with a byte
 *          value when a thread is created. This can be useful for the
 *          runtime measurement of the used stack.
 *
 * @note    The default is @p FALSE.
 */
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS             TRUE
#endif

/**
 * @brief   Debug option, threads profiling.
 * @details If enabled then a field is added to the @p Thread structure that
 *          counts the system ticks occurred while executing the thread.
 *
 * @note    The default is @p TRUE.
 * @note    This debug option is defaulted to TRUE because it is required by
 *          some test cases into the test suite.
 */
#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING        TRUE
#endif

/** @} */

/*===========================================================================*/
/**
 * @name Kernel hooks
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Threads descriptor structure extension.
 * @details User fields added to the end of the @p Thread structure.
 */
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS                                                   \
  /* Add threads custom fields here.*/
#endif

/**
 * @brief   Threads initialization hook.
 * @details User initialization code added to the @p chThdInit() API.
 *
 * @note    It is invoked from within @p chThdInit() and implicitly from all
 *          the threads creation APIs.
 */
#if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT_HOOK(tp) {                                          \
  /* Add threads initialization code here.*/                                \
}
#endif

/**
 * @brief   Threads finalization hook.
 * @details User finalization code added to the @p chThdExit() API.
 *
 * @note    It is inserted into lock zone.
 * @note    It is also invoked when the threads simply return in order to
 *          terminate.
 */
#if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT_HOOK(tp) {                                          \
  /* Add threads finalization code here.*/                                  \
}
#endif

/**
 * @brief   Context switch hook.
 * @details This hook is invoked just before switching between threads.
 */
#if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__)
#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) {                              \
  /* System halt code here.*/                                               \
}
#endif

/**
 * @brief   Idle Loop hook.
 * @details This hook is continuously invoked by the idle thread loop.
 */
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() {                                                  \
  /* Idle loop code here.*/                                                 \
}
#endif

/**
 * @brief   System tick event hook.
 * @details This hook is invoked in the system tick handler immediately
 *          after processing the virtual timers queue.
 */
#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__)
#define SYSTEM_TICK_EVENT_HOOK() {                                          \
  /* System tick event code here.*/                                         \
}
#endif

/**
 * @brief   System halt hook.
 * @details This hook is invoked in case to a system halting error before
 *          the system is halted.
 */
#if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
#define SYSTEM_HALT_HOOK() {                                                \
  /* System halt code here.*/                                               \
}
#endif

/** @} */

/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h).    */
/*===========================================================================*/
#define CORTEX_ENABLE_WFI_IDLE    TRUE


Thank you in advance

Best Regards,
- Daniel

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: LPC1752 Keil - Stuck at _idle_thread

Postby Giovanni » Thu Jun 12, 2014 12:56 pm

Hi,

ChibiOS cannot be configured to a cooperatively scheduled RTOS, except for threads at the same priority level, it is inherently preemptive.

You should provide details about your setup, are you using the provided startup files and ld files? ChibiOS version? is systick enabled?

Giovanni

kunilkuda
Posts: 4
Joined: Thu Jun 12, 2014 11:02 am

Re: LPC1752 Keil - Stuck at _idle_thread

Postby kunilkuda » Fri Jun 13, 2014 2:54 am

Thanks Giovanni.

I'm using ChibiOS 2.6.4 under uVision 4 (with microlib for memcpy, strlen, sprintf, etc). I'm using the included startup file. Here's the cstartup.s looks like in my implementation:

Code: Select all

/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012,2013 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.
 ....snipped
*/

;/* <<< Use Configuration Wizard in Context Menu >>> */

;// <h> Main Stack Configuration (IRQ Stack)
;//   <o> Main Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
main_stack_size EQU     0x00000400

;// <h> Process Stack Configuration
;//   <o> Process Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
proc_stack_size EQU     0x00000400

;// <h> C-runtime heap size
;//   <o> C-runtime heap size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
heap_size       EQU     0x00000400

                AREA    MSTACK, NOINIT, READWRITE, ALIGN=3
main_stack_mem  SPACE   main_stack_size
                EXPORT  __initial_msp
__initial_msp

                AREA    CSTACK, NOINIT, READWRITE, ALIGN=3
__main_thread_stack_base__
                EXPORT  __main_thread_stack_base__
proc_stack_mem  SPACE   proc_stack_size
                EXPORT  __initial_sp
__initial_sp

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base__   ; ChibiOS chmemcore requirement
                EXPORT __heap_base__
__heap_base
Heap_Mem        SPACE   heap_size
__heap_limit
__heap_end__    ; ChibiOS chmemcore requirement
                EXPORT __heap_end__

CONTROL_MODE_PRIVILEGED     EQU     0
CONTROL_MODE_UNPRIVILEGED   EQU     1
CONTROL_USE_MSP             EQU     0
CONTROL_USE_PSP             EQU     2

                PRESERVE8
                THUMB

                AREA    |.text|, CODE, READONLY

/*
 * Reset handler.
 */
                IMPORT  __main
                EXPORT  Reset_Handler
Reset_Handler   PROC
                cpsid   i
                ldr     r0, =__initial_sp
                msr     PSP, r0
                movs    r0, #CONTROL_MODE_PRIVILEGED :OR: CONTROL_USE_PSP
                msr     CONTROL, r0
                isb
                bl      __early_init

                IF      {CPU} = "Cortex-M4.fp"
                LDR     R0, =0xE000ED88           ; Enable CP10,CP11
                LDR     R1, [R0]
                ORR     R1, R1, #(0xF << 20)
                STR     R1, [R0]
                ENDIF

                ldr     r0, =__main
                bx      r0
                ENDP

__early_init    PROC
                EXPORT  __early_init            [WEAK]
                bx      lr
                ENDP

                ALIGN

/*
 * User Initial Stack & Heap.
 */
                IF      :DEF:__MICROLIB
               
                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit
               
                ELSE

                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap
__user_initial_stackheap
                ldr     r0, =Heap_Mem
                ldr     r1, =(proc_stack_mem + proc_stack_size)
                ldr     r2, =(Heap_Mem + heap_size)
                ldr     r3, =proc_stack_mem
                bx      lr

                ALIGN

                ENDIF

                END


Since the vector table is not provided for LPC17xx, I've created my own, based on Keil bare-board startup.s

Code: Select all

/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012,2013 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.
    ....snipped
*/
                PRESERVE8
                THUMB

                AREA    RESET, DATA, READONLY
                IMPORT  __initial_msp
                IMPORT  Reset_Handler
                EXPORT  __Vectors

__Vectors       DCD     __initial_msp           ; Top of Stack
                DCD     Reset_Handler           ; Reset Handler
                DCD     NMIVector               ; NMI Handler
                DCD     HardFaultVector         ; Hard Fault Handler
                DCD     MemManageVector         ; MPU Fault Handler
                DCD     BusFaultVector          ; Bus Fault Handler
                DCD     UsageFaultVector        ; Usage Fault Handler
                DCD     0                       ; Reserved
                DCD     0                       ; Reserved
                DCD     0                       ; Reserved
                DCD     0                       ; Reserved
                DCD     SVCallVector            ; SVCall Handler
                DCD     DebugMonitorVector      ; Debug Monitor Handler
                DCD     0                       ; Reserved
                DCD     PendSVVector            ; PendSV Handler
                DCD     SysTickVector           ; SysTick Handler

                ; External Interrupts
                DCD     WDT_IRQHandler            ; 16: Watchdog Timer
                DCD     TIMER0_IRQHandler         ; 17: Timer0
                DCD     TIMER1_IRQHandler         ; 18: Timer1
                DCD     TIMER2_IRQHandler         ; 19: Timer2
                DCD     TIMER3_IRQHandler         ; 20: Timer3
                DCD     UART0_IRQHandler          ; 21: UART0
                DCD     UART1_IRQHandler          ; 22: UART1
                DCD     UART2_IRQHandler          ; 23: UART2
                DCD     UART3_IRQHandler          ; 24: UART3
                DCD     PWM1_IRQHandler           ; 25: PWM1
                DCD     I2C0_IRQHandler           ; 26: I2C0
                DCD     I2C1_IRQHandler           ; 27: I2C1
                DCD     I2C2_IRQHandler           ; 28: I2C2
                DCD     SPI_IRQHandler            ; 29: SPI
                DCD     SSP0_IRQHandler           ; 30: SSP0
                DCD     SSP1_IRQHandler           ; 31: SSP1
                DCD     PLL0_IRQHandler           ; 32: PLL0 Lock (Main PLL)
                DCD     RTC_IRQHandler            ; 33: Real Time Clock
                DCD     EINT0_IRQHandler          ; 34: External Interrupt 0
                DCD     EINT1_IRQHandler          ; 35: External Interrupt 1
                DCD     EINT2_IRQHandler          ; 36: External Interrupt 2
                DCD     EINT3_IRQHandler          ; 37: External Interrupt 3
                DCD     ADC_IRQHandler            ; 38: A/D Converter
                DCD     BOD_IRQHandler            ; 39: Brown-Out Detect
                DCD     USB_IRQHandler            ; 40: USB
                DCD     CAN_IRQHandler            ; 41: CAN
                DCD     DMA_IRQHandler            ; 42: General Purpose DMA
                DCD     I2S_IRQHandler            ; 43: I2S
                DCD     ENET_IRQHandler           ; 44: Ethernet
                DCD     RIT_IRQHandler            ; 45: Repetitive Interrupt Timer
                DCD     MCPWM_IRQHandler          ; 46: Motor Control PWM
                DCD     QEI_IRQHandler            ; 47: Quadrature Encoder Interface
                DCD     PLL1_IRQHandler           ; 48: PLL1 Lock (USB PLL)
                DCD     USBActivity_IRQHandler    ; 49: USB Activity interrupt to wakeup
                DCD     CANActivity_IRQHandler    ; 50: CAN Activity interrupt to wakeup

                IF      :LNOT::DEF:NO_CRP
                AREA    |.ARM.__at_0x02FC|, CODE, READONLY
CRP_Key         DCD     0xFFFFFFFF
                ENDIF

/*
 * Default interrupt handlers.
 */
                AREA    |.text|, CODE, READONLY
                EXPORT  _unhandled_exception
_unhandled_exception PROC
                EXPORT  NMIVector                 [WEAK]
                EXPORT  HardFaultVector           [WEAK]
                EXPORT  MemManageVector           [WEAK]
                EXPORT  BusFaultVector            [WEAK]
                EXPORT  UsageFaultVector          [WEAK]
                EXPORT  SVCallVector              [WEAK]
                EXPORT  DebugMonitorVector        [WEAK]
                EXPORT  PendSVVector              [WEAK]
                EXPORT  SysTickVector             [WEAK]
                EXPORT  WDT_IRQHandler            [WEAK]
                EXPORT  TIMER0_IRQHandler         [WEAK]
                EXPORT  TIMER1_IRQHandler         [WEAK]
                EXPORT  TIMER2_IRQHandler         [WEAK]
                EXPORT  TIMER3_IRQHandler         [WEAK]
                EXPORT  UART0_IRQHandler          [WEAK]
                EXPORT  UART1_IRQHandler          [WEAK]
                EXPORT  UART2_IRQHandler          [WEAK]
                EXPORT  UART3_IRQHandler          [WEAK]
                EXPORT  PWM1_IRQHandler           [WEAK]
                EXPORT  I2C0_IRQHandler           [WEAK]
                EXPORT  I2C1_IRQHandler           [WEAK]
                EXPORT  I2C2_IRQHandler           [WEAK]
                EXPORT  SPI_IRQHandler            [WEAK]
                EXPORT  SSP0_IRQHandler           [WEAK]
                EXPORT  SSP1_IRQHandler           [WEAK]
                EXPORT  PLL0_IRQHandler           [WEAK]
                EXPORT  RTC_IRQHandler            [WEAK]
                EXPORT  EINT0_IRQHandler          [WEAK]
                EXPORT  EINT1_IRQHandler          [WEAK]
                EXPORT  EINT2_IRQHandler          [WEAK]
                EXPORT  EINT3_IRQHandler          [WEAK]
                EXPORT  ADC_IRQHandler            [WEAK]
                EXPORT  BOD_IRQHandler            [WEAK]
                EXPORT  USB_IRQHandler            [WEAK]
                EXPORT  CAN_IRQHandler            [WEAK]
                EXPORT  DMA_IRQHandler            [WEAK]
                EXPORT  I2S_IRQHandler            [WEAK]
                EXPORT  ENET_IRQHandler           [WEAK]
                EXPORT  RIT_IRQHandler            [WEAK]
                EXPORT  MCPWM_IRQHandler          [WEAK]
                EXPORT  QEI_IRQHandler            [WEAK]
                EXPORT  PLL1_IRQHandler           [WEAK]
                EXPORT  USBActivity_IRQHandler    [WEAK]
                EXPORT  CANActivity_IRQHandler    [WEAK]

NMIVector
HardFaultVector
MemManageVector
BusFaultVector
UsageFaultVector
SVCallVector
DebugMonitorVector
PendSVVector
SysTickVector
WDT_IRQHandler
TIMER0_IRQHandler
TIMER1_IRQHandler
TIMER2_IRQHandler
TIMER3_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
UART3_IRQHandler
PWM1_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
I2C2_IRQHandler
SPI_IRQHandler
SSP0_IRQHandler
SSP1_IRQHandler
PLL0_IRQHandler
RTC_IRQHandler
EINT0_IRQHandler
EINT1_IRQHandler
EINT2_IRQHandler
EINT3_IRQHandler
ADC_IRQHandler
BOD_IRQHandler
USB_IRQHandler
CAN_IRQHandler
DMA_IRQHandler
I2S_IRQHandler
ENET_IRQHandler
RIT_IRQHandler
MCPWM_IRQHandler
QEI_IRQHandler
PLL1_IRQHandler
USBActivity_IRQHandler
CANActivity_IRQHandler

                B       .
                ENDP

                END


Note that I've changed the NMIVector, HardFaultVector, MemManageVector, BusFaultVector, UsageFaultVector, SVCallVector, DebugMonitorVector, PendSVVector and SysTickVector interrupt handler names to ChibiOS standard (instead of Keil's standard: *_IRQHander). I didn't change the linker file because it's not needed in RCVT port, and my linker map file showed that the SysTickVector and SVCallVector from ChibiOS is connected.

I only want to use the ChibiOS kernel, because my old project already have all the necessary BSPs / mcu peripheral drivers. I need to keen the peripheral IRQ handler names according to Keil, otherwise my old drivers won't link into the IRQ table.

Then for the application, what I want is really simple. I'm polling one of the GPIO pin using Timer1 IRQ. The main thread will wait until the GPIO pin is pressed for more than 2 secs. The main thread is waiting for event that's fired during the Timer1 IRQ. Here's my application code (very sorry for the mess. Need to compress everything into single file).

Code: Select all


#include <LPC17xx.h>
#include "ch.h"

#define LPC17XX_CCLK    100000000UL

/*----------------------------------------------------------------------------*/
/*** \brief The MFB event flags */
enum _mfb_event {
    MFB_EVENT_NOT_PRESSED    = 0x0000,
    MFB_EVENT_LONG_PRESSED   = 0x0001,
    MFB_EVENT_SHORT_PRESSED  = 0x0002,
};

/*** \brief The MFB event object */
static EVENTSOURCE_DECL(ge_mfb_event);

/*** \brief The threshold value for LONG_PRESSED */
enum _mfb_long_threshold {
    MFB_THRESHOLD_POWERUP   = 20, /* 2 secs to start up the mat */
    MFB_THRESHOLD_POWERDOWN = 10, /* 1 sec to shutdown the mat */
};

/*** \brief Store the threshold value for LONG PRESSED condition */
static uint8_t gu8_mfb_long_threshold = MFB_THRESHOLD_POWERUP;

/*----------------------------------------------------------------------------*/
/*** \brief The Timer1 interrupt handler. It's firing every 100ms to check the
 *          MFB status
 */
void TIMER1_IRQHandler(void) {
    #define MFB_IS_PRESSED     ((LPC_GPIO0->FIOPIN & 0x00400000) == 0)
    static uint8_t mfb_hold_time;

    if (MFB_IS_PRESSED) {
        mfb_hold_time++;
        if (mfb_hold_time == gu8_mfb_long_threshold) {
            chEvtBroadcastFlagsI(&ge_mfb_event, MFB_EVENT_LONG_PRESSED);
            mfb_hold_time = 0;
        }
    } else {
        if (mfb_hold_time > 0) {
            chEvtBroadcastFlagsI(&ge_mfb_event, MFB_EVENT_SHORT_PRESSED);
        }

        mfb_hold_time = 0;
    }

    /* Clear Timer1 MR0 IRQ */
      LPC_TIM1->IR = 1;
}

/*----------------------------------------------------------------------------*/
/*** \brief Init the board and the MCU for the operation
 *
 * The first stage is needed to init the required MCU peripherals and BSPs to
 * print the informational message for the production tools
 */
static void init_hardware_stage_1(void);

/*** \brief Wait until user powered on the system. This function will wait for
 *          MFB_EVENT_LONG_PRESSED event
 */
static void wait_until_powered_on(void);

/*** \brief Init the board and the MCU for the operation
 *
 * The second stage is needed to init whole board for the operation. This will
 * only happen after the user pressed the MFB for 2 secs.
 */
static void init_hardware_stage_2(void);

/*----------------------------------------------------------------------------*/
int main(void) {
    /* Init the required hardware for MFB detection, and print production info
     */
    init_hardware_stage_1();

    /* Init the ChibiOS */
    chSysInit();

    /* Wait until user pressed MFB for 2 secs */
    wait_until_powered_on();

    /* System is powered. Init the rest of the peripherals */
    init_hardware_stage_2();

    while(1);
}

/*----------------------------------------------------------------------------*/
static void init_hardware_stage_1(void) {
    uint32_t delay;
   
    /* Set all LEDs to off */
    LPC_GPIO2->FIODIR |= 0x30;
    LPC_GPIO2->FIOSET = 0x10; /* Turn off red led */
    LPC_GPIO2->FIOSET = 0x20; /* Turn off green led */
   
    /* Set all PSU to off (until user pressed the MFB for 2secs) */
    LPC_GPIO0->FIODIR |= 0x240;
    LPC_GPIO0->FIOCLR  = 0x200;
    for (delay = 0; delay < 0xFFF; delay++);
    LPC_GPIO0->FIOCLR  = 0x40;
    for (delay = 0; delay < 0xFFF; delay++);

    /* Enable 100ms timer to detect the MFB pressed condition */
    /* TIM1_PCLK = CCLK / 4 = 100Mhz / 4 = 25Mhz */
    LPC_TIM1->PR  = (25000 - 1); /* 1ms prescaler */
    LPC_TIM1->MR0 = (100);       /* 100 * 1ms = 100ms */
    LPC_TIM1->MCR = 3;           /* (RESET_AFTER_INTERVAL |
                                      INTERRUPT_AFTER_INTERVAL)*/

    /* Reset and stop the Timer */
    LPC_TIM1->TCR = 2;

    NVIC_EnableIRQ(TIMER1_IRQn);

    /* Start the timer */
    LPC_TIM1->TCR = 1;

    /* Setup SysTick timer as the ChibiOS timer */
    SysTick_Config(LPC17XX_CCLK / CH_FREQUENCY);
}

/*----------------------------------------------------------------------------*/
static void wait_until_powered_on(void) {
    struct EventListener el;

    chEvtInit(&ge_mfb_event);
    chEvtRegister(&ge_mfb_event, &el, MFB_EVENT_LONG_PRESSED);
   
    /* Wait until the MFB_EVENT_LONG_PRESSED is sent */
    chEvtWaitOne(MFB_EVENT_LONG_PRESSED);

    chEvtUnregister(&ge_mfb_event, &el);
}

/*----------------------------------------------------------------------------*/
static void init_hardware_stage_2(void) {
    /* Enable all PSUs */
    uint32_t delay;

    LPC_GPIO0->FIOSET  = 0x200; /* Pull high P0.9 */
    for (delay = 0; delay < 0xFFF; delay++);
    LPC_GPIO0->FIOSET  = 0x40;  /* Pull high P0.6     */
    for (delay = 0; delay < 0xFFF; delay++);

    /* Turn on all LEDS */
    LPC_GPIO2->FIOCLR = 0x10; /* Turn on red led */
    LPC_GPIO2->FIOCLR = 0x20; /* Turn on green led */
}


If the code works, the LEDs should be on, but the it's not. And the debugger showed that even though the Timer1 IRQ fired -> event broadcasted, SysTick fired, SVC fired, there's no task switch happening. The thread stuck at _idle_thread

I hope I'm giving enough information to solve this problem. Sorry if it's too much.

Thank you for your time and suggestion too =)

Best Regards,
-Daniel

kunilkuda
Posts: 4
Joined: Thu Jun 12, 2014 11:02 am

[closed] Re: LPC1752 Keil - Stuck at _idle_thread

Postby kunilkuda » Fri Jun 13, 2014 4:59 am

Hi Giovanni,

Manage to solve it. The thread stuck at _idle_thread() because the main() thread is never going to READY state, due to chEvtWaitOne() waiting at the wrong signal

Code: Select all

static void wait_until_powered_on(void) {
    struct EventListener el;

    chEvtInit(&ge_mfb_event);
    chEvtRegister(&ge_mfb_event, &el, MFB_EVENT_LONG_PRESSED);
   
    /* Wait until the MFB_EVENT_LONG_PRESSED is sent */
    // chEvtWaitOne(MFB_EVENT_LONG_PRESSED);
    chEvtWaitOne(EVENT_MASK(MFB_EVENT_LONG_PRESSED));

    chEvtUnregister(&ge_mfb_event, &el);
}

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: LPC1752 Keil - Stuck at _idle_thread

Postby Giovanni » Fri Jun 13, 2014 8:38 am

Hi,

Probably the vectors table is the problem, names are different. Please use the one provided with ChibiOS, by just adding/removing vectors as needed.

Giovanni


Return to “LPC Support”

Who is online

Users browsing this forum: No registered users and 7 guests