Page 1 of 1

[BUG] _dbg_check_lock always triggers

Posted: Fri Jul 31, 2015 3:08 pm
by AndreR
Hi Giovanni,

I just started another fresh project with an STM32F4 and came across a rather subtle bug with the debug check functionality of _dbg_check_lock.
I am using only the RT part of the recently released ChibiOS 3.0.0, no fancy HAL stuff, periodic tick mode (pretty much v2.6 style).

In my main() function I blink some LEDs and therefore call chThdSleepMilliseconds(500);
In another task (used for a simple terminal) I use chIQGetTimeout(terminal.pInQueue, TIME_INFINITE);

With that setup and check lock enabled, I pretty fast end up in a system halt with panic message SV#4. Checking the code, I noticed that _dbg_check_lock queries "ch.dbg.lock_cnt != (cnt_t)0" and that every SysLock sets that to 1, every SysUnlock sets it to 0.
When entering the sleep function in my main thread, that sets the ch.dbg.lock_cnt to 1. Now the terminal task executes and in the call to chIQGetTimeout is another SysLock. As the ch.dbg.lock_cnt is already set to 1, this results in a system halt with panic message SV#4.

For me, this looks like a major design flaw. Am I missing something here? I would really like to use the debug features, but with the way check lock works it is rather annoying.

Best regards,
Andre

Re: [BUG] _dbg_check_lock always triggers

Posted: Fri Jul 31, 2015 3:16 pm
by Giovanni
Hi,

When a task is switched an unlock is always executed by the switched-in task. The context switch sequence is always:

- ...
- lock
- switch
- unlock
- ...

There must be something else, this is so fundamental that cannot be broken unless there is a bug and the above sequence is not respected somewhere.

Are all your ISR priorities within range? (2..15 usually on Cortex M3/M4). An ISR calling OS code at priorities 0 or 1 could cause the problem you are experiencing.

Giovanni

Re: [BUG] _dbg_check_lock always triggers

Posted: Fri Jul 31, 2015 3:37 pm
by AndreR
Oh boy, forget about that thread. I just found the problem.

The DEBUG preprocessor definition was set for the C compiler, but not for ASM compiler. So that _dbg_check_unlock was not called in _port_switch.
Sorry for the hassle, you may close this thread.

Re: [BUG] _dbg_check_lock always triggers

Posted: Mon Oct 26, 2015 9:47 pm
by podhrmic
Hi,
I have a similar problem - although the cause seems to be different (I checked the DEBUG flags).

The following code works perfectly using one of the examples for STM32F4xx board:

Code: Select all

static THD_WORKING_AREA(waThread2, 128);
static THD_FUNCTION(Thread2, arg) {

  (void) arg;
  chRegSetThreadName("sys_tick_handler");
  volatile uint32_t nb_tick;

  while (TRUE) {
    nb_tick = chVTGetSystemTime();
    chThdSleepMilliseconds(1);
  }
}


Thread2 is created from within the main thread, before main threads enters its while loop.

However, when I try to compile and run the same code from my own application build on top of ChibiOS (RT Paparazzi autipilot: https://github.com/podhrmic/paparazzi/tree/rt_chibios) the code ends with SV#4 error (misplaced sys_lock).

What I was able to figure out is that the thread is created and woken up in locked zone (from chthreads.c):

Code: Select all

  chSysLock();
  tp = chThdCreateI(wsp, size, prio, pf, arg);
  chSchWakeupS(tp, MSG_OK);
  chSysUnlock();


The difference is that for some reason in the demo application the thread is woken up (chSchWakeupS(tp, MSG_OK)) but not executed until the system is unlocked (chSysUnlock()), while in my application the thread enters its while loop while the system is still in locked zone. Thus it fails when tries to execute chVTGetSystemTime

What could cause this difference? In both cases I am using ChibiOS 3.0.3, STM32F407 and full DEBUG options.
My makefile is essentially the same as demo makefile, just including the extra files so I haven't been able to spot any differences there.

Without checking the system state the program works (seemingly) fine, indeed we want it to work with full DEBUG options.

Any suggestions?

Re: [BUG] _dbg_check_lock always triggers

Posted: Tue Oct 27, 2015 7:45 am
by Giovanni
Hi,

Critical zones are placed around I and S function, when a switch occurs then the unlock is performed "on the other side". When thread starts the very thing that they do is to perform an unlock (in the ASM part).

Are you using the standard makefiles or some other build system?

Giovanni

Re: [BUG] _dbg_check_lock always triggers

Posted: Thu Nov 19, 2015 11:59 pm
by podhrmic
Hi Giovanni,
I found out where the problem is.

I have a modified makefile - but practically the only difference is that I am changing the build directory, and adding a couple of extra source files and includes, the makefile rules are identical.

In my makefile, I have an additional debug flag, so I can easily switch between debug and release mode.

Code: Select all


ifeq (,$(findstring $(RTOS_DEBUG),0 FALSE))
$(info DEBUGGING ON)
$(TARGET).CFLAGS += \
  -DCH_DBG_STATISTICS=TRUE \
   -DCH_DBG_SYSTEM_STATE_CHECK=TRUE \
   -DCH_DBG_ENABLE_CHECKS=TRUE \
   -DCH_DBG_ENABLE_ASSERTS=TRUE \
   -DCH_DBG_ENABLE_TRACE=TRUE \
   -DCH_DBG_ENABLE_STACK_CHECK=TRUE \
   -DCH_DBG_FILL_THREADS=TRUE \
   -DCH_DBG_THREADS_PROFILING=TRUE
else
$(info DEBUGGING OFF)
endif


Then in chconf.h I added an ifdef macro:

Code: Select all

#pragma message(STRING(CH_DBG_STATISTICS))
#if !defined(CH_DBG_STATISTICS)
#define CH_DBG_STATISTICS       FALSE
#endif


So in theory, when I defined RTOS_DEBUG=1 it is equivalent to setting all debug options to TRUE. When I run the compilation process, I get this output:

Each time I include chconf.h:

Code: Select all

In file included from /home/fwmav/Paparazzi/AggieAir/paparazzi/sw/ext/chibios/os/rt/include/ch.h:71:0,
                 from /home/fwmav/Paparazzi/AggieAir/paparazzi/sw/ext/chibios/os/rt/src/chschd.c:29:
arch/chibios/chconf.h:333:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_STATISTICS))
         ^
arch/chibios/chconf.h:345:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_SYSTEM_STATE_CHECK))
         ^
arch/chibios/chconf.h:357:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_ENABLE_CHECKS))
         ^
arch/chibios/chconf.h:370:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_ENABLE_ASSERTS))
         ^
arch/chibios/chconf.h:382:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_ENABLE_TRACE))
         ^
arch/chibios/chconf.h:397:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_ENABLE_STACK_CHECK))
         ^
arch/chibios/chconf.h:410:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_FILL_THREADS))
         ^
arch/chibios/chconf.h:424:9: note: #pragma message: 1
 #pragma message(STRING(CH_DBG_THREADS_PROFILING))


However - and here is the catch - in three cases I get the following output instead:

Code: Select all

In file included from /home/fwmav/Paparazzi/AggieAir/paparazzi/sw/ext/chibios/os/rt/include/ch.h:71:0,
                 from arch/chibios/mcu_periph/sys_time_arch.h:41,
                 from mcu_periph/sys_time.h:211,
                 from mcu.c:32:
arch/chibios/chconf.h:333:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_STATISTICS))
         ^
arch/chibios/chconf.h:345:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_SYSTEM_STATE_CHECK))
         ^
arch/chibios/chconf.h:357:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_ENABLE_CHECKS))
         ^
arch/chibios/chconf.h:370:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_ENABLE_ASSERTS))
         ^
arch/chibios/chconf.h:382:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_ENABLE_TRACE))
         ^
arch/chibios/chconf.h:397:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_ENABLE_STACK_CHECK))
         ^
arch/chibios/chconf.h:410:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_FILL_THREADS))
         ^
arch/chibios/chconf.h:424:9: note: #pragma message: (!0)
 #pragma message(STRING(CH_DBG_THREADS_PROFILING))



When I remove the ifdef macros and set all debugging options to TRUE in chconf.h the program compiles and runs fine. So my guess is that somehow the debugging options are not properly included for a couple of files, and that makes the compiler confused.

If I do the same thing in the ChibiOS demo project (i.e. define a flag for debugging options in the makefile) it works fine. So I am suspecting it is some settings in my makefile / preprocessor.

The workaround is to not have ifdef macros in chconf.h, but I would be curious in case you had any suggestions why it might be happening,

Regards

Re: [BUG] _dbg_check_lock always triggers

Posted: Fri Nov 20, 2015 8:58 am
by Giovanni
Hi,

Are those defines also passed to the assembler files? those use the configuration switches too.

Giovanni

Re: [BUG] _dbg_check_lock always triggers

Posted: Tue Nov 24, 2015 9:30 pm
by podhrmic
That was the problem - I had to pass

Code: Select all

$(UDEFS)
not only to

Code: Select all

DEFS
, but to

Code: Select all

ADEFS
too (in rules.mk).
Now it runs properly (the unrelated defines doesn't seem to have any effect for assembler).
Thank you Giovanni!