/*************************************************************************** * Copyright (c) 2003-2010, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: bkni.h $ * $brcm_Revision: Hydra_Software_Devel/40 $ * $brcm_Date: 3/16/10 4:17p $ * * Module Description: * * Revision History: * * $brcm_Log: /magnum/basemodules/kni/generic/bkni.h $ * * Hydra_Software_Devel/40 3/16/10 4:17p erickson * SW3548-2837: add BKNI_DEBUG_CS_TIMING feature, default off * * Hydra_Software_Devel/39 4/14/09 11:51a erickson * PR53778: default BKNI_TRACK_MALLOCS for linux user mode only * * Hydra_Software_Devel/38 4/14/09 9:11a erickson * PR53778: default BKNI_TRACK_MALLOCS on for linux in debug mode * * Hydra_Software_Devel/37 4/9/09 1:35p vsilyaev * PR 53778: Keep a history of free'ed objects for better debug facilities * * Hydra_Software_Devel/36 4/2/09 11:28a erickson * PR53778: extend BKNI_TRACK_MALLOCS to events and mutexes * * Hydra_Software_Devel/35 1/29/09 8:12p vsilyaev * PR 42495: Improved tracking of memory allocation * * Hydra_Software_Devel/34 12/29/08 1:01p erickson * PR50742: fix spelling of BKNI_AssertIsrContext * * Hydra_Software_Devel/33 9/18/08 3:23p erickson * PR46838: merge * * Hydra_Software_Devel/PR46838/1 9/17/08 4:55p dyzhang * PR46838: fix compiling warning with BKNI_TRACK_MALLOCS on. * * Hydra_Software_Devel/32 8/21/08 4:43p vsilyaev * PR 32280: Added BKNI_ASSERT_ISR_CONTEXT * * Hydra_Software_Devel/31 5/7/08 10:54a erickson * PR42495: add BKNI_TRACK_MALLOCS feature, defaulted off * * Hydra_Software_Devel/30 9/11/06 4:13p erickson * PR21941: 23976 * * Hydra_Software_Devel/29 4/28/04 12:14p vsilyaev * PR 9698: Created _isr aliases for ISR safe functions. * * Hydra_Software_Devel/28 4/8/03 4:47p erickson * BKNI_ResetEvent now returns void * Split BKNI_AcquireMutex into Acquire and TryAcquire * * Hydra_Software_Devel/27 4/4/03 12:22p erickson * updated docs * * Hydra_Software_Devel/26 4/4/03 11:53a erickson * updated docs * * Hydra_Software_Devel/25 4/4/03 11:34a erickson * updated docs * * Hydra_Software_Devel/24 4/4/03 11:27a erickson * updated documentation * * Hydra_Software_Devel/23 4/3/03 6:13p erickson * some pre 0.9 api rework * * Hydra_Software_Devel/22 4/3/03 3:57p erickson * documentation updates * * Hydra_Software_Devel/21 4/1/03 7:02p erickson * updated comments * * Hydra_Software_Devel/20 4/1/03 5:21p vsilyaev * Change timeout type in Sleep and Delay from [signed[ int to unsigned. * * Hydra_Software_Devel/19 3/31/03 3:40p erickson * added BKNI_ResetEvent * * Hydra_Software_Devel/18 3/28/03 6:53p erickson * updated comments * * Hydra_Software_Devel/17 3/28/03 12:36p erickson * updated WaitForEvent documentation * * Hydra_Software_Devel/16 3/25/03 11:45a erickson * Removed implementation notes * * Hydra_Software_Devel/15 3/24/03 2:10p erickson * updated comments * * Hydra_Software_Devel/14 3/24/03 11:38a erickson * reworked docs * * Hydra_Software_Devel/13 3/17/03 4:09p erickson * kernel interface doc changes * * Hydra_Software_Devel/12 3/12/03 3:49p erickson * updated tests and got linuxkernel working with them * * Hydra_Software_Devel/11 3/12/03 12:04p erickson * updated return codes, comments * * Hydra_Software_Devel/10 3/11/03 6:59p erickson * changed kernelinterface from using object ptrs to handles * * Hydra_Software_Devel/9 3/10/03 8:28p vsilyaev * Added support for the tagged kernet interface API. * * Hydra_Software_Devel/8 3/10/03 6:36p vsilyaev * Uses extern "C" { } brackets. * * Hydra_Software_Devel/7 3/10/03 4:55p erickson * using standard bkni.h * no longer includes STD_INC include path * * Hydra_Software_Devel/6 3/10/03 2:44p vsilyaev * Function without parameters should have prototype (void). * Include bkni_imp.h at the end. * * Hydra_Software_Devel/4 3/10/03 2:29p erickson * updated docs * * Hydra_Software_Devel/3 3/6/03 6:27p erickson * rework KNI api * * Hydra_Software_Devel/2 3/6/03 10:07a erickson * updated documentation * * Hydra_Software_Devel/1 3/5/03 5:16p erickson * Initial kernelinterface work * ***************************************************************************/ #ifndef BKNI_H__ #define BKNI_H__ #ifdef __cplusplus extern "C" { #endif /*====================== Module Overview =========================== ---++++ *Summary:* The Kernel Interface is the set of operating system and standard C library functions required by the Magnum architecture which is portable across all software and hardware platforms which Broadcom uses. ---++++ *Requirements:* *Portable* - every function must work on every platform in the same well-defined way. Some error conditions cannot or should not be standardized, therefore we also include usage rules (see BKNI_EnterCriticalSection for an example.) Every platform implementationmust be regularly checked with compliance tests. *Safe* - Because of the inherent dangers of multitasking, each kernel interface implementation must ensure there are no race conditions within the implementation. The API must also be simple and explicit in order to help developers avoid race conditions in their code. *Minimal* - The number of functions should be just enough to allow us to implement the Magnum architecture. Platform-dependent code should make use of platform-specific functions. ---++++ *Files:* The kernel interface is divided into three sections: *bkni.h* is the single-task kernel interface. It is used by code which follows the single-task model of execution specified in ThreadSafe. *bkni_multi.h* is the multi-tasking kernel interface. It is used by code which follows the multi-task model of execution specified in ThreadSafe. bkni_multi.h also includes bkni.h. *bkni_metrics.h* is the metrics interface. It must not be called by Magnum code, but provides system monitoring and debugging to platform-specific code. ---++++ *Summary of Changes:* New naming convention. Replaced structures with opaque handles. Init and Uninit functions. Replaced semaphores with mutexes.While a semaphore can be configured as a mutex, it can easily be misconfigured and introduce race conditions. The combination of a mutex and an event is simple and sufficient. Removed sprintf and vsprintf because they introduce possible buffer overruns. snprintf and vsnprintf are sufficient. Memory map functionality (MmuMap and UnmmuMap) was moved to the MemoryManager. Removed debug macros (DBGMSG) and data types (WORD, HANDLE, etc.). ---++++ *Interrupt Safety:* The following functions can be called from an ISR or a critical section: * BKNI_Memset, BKNI_Memcpy, BKNI_Memcmp, BKNI_Memchr, BKNI_Memmove * BKNI_Printf, BKNI_Vprintf * BKNI_Delay * BKNI_SetEvent * BKNI_WaitForEvent, but only with a timeout of zero. All other functions are not callable from either an ISR or critical section. *****************************************************************************/ /*************************************************************************** Summary: Event handle created by BKNI_CreateEvent. ****************************************************************************/ typedef struct BKNI_EventObj *BKNI_EventHandle; /*************************************************************************** Summary: Initialize the kernel interface before use. Description: The system must call BKNI_Init() before making any other kernel interface call. Magnum code cannot call BKNI_Init(). The BKNI_Init call should reset the metrics interface. See BKNI_Metrics_Reset. Returns: BERR_SUCCESS - The kernel interface successfully initialized. BERR_OS_ERROR - Initialization failed. ****************************************************************************/ BERR_Code BKNI_Init(void); /*************************************************************************** Summary: Uninitialize the kernel interface after use. Description: Cleans up the kernel interface. No kernel interface calls can be made after this, except BKNI_Init(). Magnum code cannot call BKNI_Uninit(). Returns: ****************************************************************************/ void BKNI_Uninit(void); /*************************************************************************** Summary: Set byte array to a value. Description: Copies the value of ch (converted to an unsigned char) into each of the first n characters of the memory pointed to by mem. Can be called from an interrupt-context. Input: mem - memory to be set ch - 8 bit value to be copied into memory n - number of bytes to be copied into memory Returns: The value of mem ****************************************************************************/ void *BKNI_Memset(void *mem, int ch, size_t n); /*************************************************************************** Summary: Copy non-overlapping memory. Description: Copies n characters from the object pointed to by src into the object pointed to by dest. If copying takes place between objects that overlap, the behavior is undefined. Use BKNI_Memmove instead. Can be called from an interrupt-context. Input: dest - the destination byte array src - the source byte array n - number of bytes to copy Returns: The value of dest ****************************************************************************/ void *BKNI_Memcpy(void *dest, const void *src, size_t n); /*************************************************************************** Summary: Compare two blocks of memory. Description: Compares the first n characters of the object pointed to by s1 to the first n characters of the object pointed to by s2. Can be called from an interrupt-context. Returns: An integer greater than, equal to, or less than zero, accordingly as the object pointed to by s1 is greater than, equal to, or less than the object pointed to by s2. ****************************************************************************/ int BKNI_Memcmp( const void *s1, /* byte array to be compared */ const void *s2, /* byte array to be compared */ size_t n /* maximum number of bytes to be compared */ ); /*************************************************************************** Summary: Find a byte in a block of memory. Description: Locates the first occurrence of ch (converted to an unsigned char) in the initial n characters (each interpreted as unsigned char) of the object pointed to by mem. Can be called from an interrupt-context. Input: mem - byte array to be searched ch - 8 bit value to be searched for n - maximum number of bytes to be searched Returns: A pointer to the located character, or a null pointer if the character does not occur in the object. ****************************************************************************/ void *BKNI_Memchr(const void *mem, int ch, size_t n); /*************************************************************************** Summary: Copy potentially overlapping memory. Description: Copies n characters from the object pointed to by src into the object pointed to by dest. Copying takes place as if the n characters from the object pointed to by src are first copied into a temporary array of n characters that does not overlap the objects pointed to by dest and src, and then the n characters from the temporary array are copied into the object pointed to by dest. If the memory does not overlap, BKNI_Memcpy is preferred. Can be called from an interrupt-context. Returns: The value of dest ****************************************************************************/ void *BKNI_Memmove( void *dest, /* destination byte array */ const void *src, /* source byte array */ size_t n /* number of bytes to copy */ ); /*************************************************************************** Summary: Print characters to the console. Description: Although printing to the console is very important for development, it cannot and should not be guaranteed to actually print in all contexts. It is valid for the system developer to eliminate all BKNI_Printf output in release builds or if the context demands it (e.g. interrupt context). You should use BKNI_Printf instead of DebugInterface when you explicity want to print information to a console regardless of debug state (e.g. BXPT_PrintStatus, BPSI_PrintPsiInformation). BKNI_Printf is also used by the generic DebugInterface implementation. We only guarantee a subset of ANSI C format specifiers. These include: * %d - int in decimal form * %u - unsigned int in decimal form * %ld - long in decimal form * %lu - unsigned long in decimal form * %x - unsigned int in lowercase hex form * %lx - unsigned long in lowercase hex form * %X - unsigned int in uppercase hex form * %lX - unsigned long in uppercase hex form * %c - an int argument converted to unsigned char * %s - string * \n - newline * \t - tab * %% - % character * %03d - Zero padding of integers, where '3' and 'd' are only examples. This can be applied to any of the preceding numeric format specifiers (not %c or %s). * Pass-through of non-control characters. Beyond these, we do not guarantee the output format. For BKNI_Printf and BKNI_Vprintf, other ANSI C format specifiers may be used, and platforms should try to make sure that any combination of formats and parameters will not cause a system crash. When calling BKNI_Snprint and BKNI_Vsnprintf, Magnum code must only use the guaranteed format specifiers if the results must always be the same on all platforms. BKNI_Printf can be called from an interrupt-context. Returns: >=0 is success. It is the number of characters transmitted. <0 is failure, either in encoding or in outputing. ****************************************************************************/ int BKNI_Printf( const char *fmt, /* format string */ ... /* variable arguments */ ); /*************************************************************************** Summary: Print characters to a null-terminated string. Description: See BKNI_Printf for a description of the format specifiers supported. Can be called from an interrupt-context. Returns: If the output is not truncated, it returns the number of characters printed, not including the trailing null byte. If the output is truncated, it should try to return the number of characters that would have been printed had the size of memory been large enough. However, this result is not required and no Magnum code should depend on this result. ****************************************************************************/ int BKNI_Snprintf( char *s, /* destination string */ size_t n, /* size of memory that can be used. It should include space for the trailing null byte. */ const char *fmt, /* format string */ ... /* variable arguments */ ); /*************************************************************************** Summary: Print characters to the console using a variable argument list. Description: Equivalent to BKNI_Printf, with the variable argument list replaced by the va_list parameter. va_list must initialized by the va_start macro (and possibly subsequent va_arg calls). The BKNI_Vprintf function does not invoke the va_end macro. The value of the va_list parameter may be modified and so it is indeterminate upon return. See BKNI_Printf for a description of the format specifiers supported. Can be called from an interrupt-context. Input: fmt - See BKNI_Printf va_list - See StandardTypes and stdarg.h Returns: >=0 is success. It is the number of characters transmitted. <0 is failure, either in encoding or in outputing. ****************************************************************************/ int BKNI_Vprintf(const char *fmt, va_list ap); /*************************************************************************** Summary: Print characters to a null-terminated string using a variable argument list. Description: See BKNI_Printf for a description of the format specifiers supported. See BKNI_Vprintf for a description of the va_list parameter. Can be called from an interrupt-context. Input: s - memory to print into n - size of memory that can be used. It should include space for the trailing null byte. fmt - See BKNI_Printf va_list - See StandardTypes and stdarg.h Returns: If the output is not truncated, it returns the number of characters printed, not including the trailing null byte. If the output is truncated, it should try to return the number of characters that would have been printed had the size of memory been large enough. However, this result is not required and no Magnum code should depend on this result. ****************************************************************************/ int BKNI_Vsnprintf(char *s, size_t n, const char *fmt, va_list ap); /*************************************************************************** Summary: Busy sleep. Description: BKNI_Delay is a busy sleep which guarantees you will delay for at least the specified number of microseconds. It does not call the scheduler, therefore the Delay is able to be less than the system clock time. This consumes CPU time, so it should be used for only short sleeps and only when BKNI_Sleep cannot be used. Be aware that on a preemptive system, any task can be interrupted and the scheduler can run, and so there is no guarantee of maximum delay time. If you have maximum time constraints, you should be using an interrupt. Can be called from an interrupt-context. Input: microsec - minimum number of microseconds to delay Returns: ****************************************************************************/ void BKNI_Delay(unsigned int microsec); /** BKNI_TRACK_MALLOCS is a simple way to track BKNI_Malloc memory leaks and bad BKNI_Frees. It can also help find the location of bad BKNI_EventHandle and BKNI_MutexHandle instances. **/ #ifndef BKNI_TRACK_MALLOCS #if defined(LINUX) && !defined(__KERNEL__) && BDBG_DEBUG_BUILD #define BKNI_TRACK_MALLOCS 1 #else #define BKNI_TRACK_MALLOCS 0 #endif #endif /** BKNI_DEBUG_CS_TIMING can find critical sections which execute too long. This might happen because of poorly written code or context switching on an overly busy system or a system with misconfigured real-time threads. **/ #ifndef BKNI_DEBUG_CS_TIMING #define BKNI_DEBUG_CS_TIMING 0 #endif /*************************************************************************** Summary: Allocate system memory. Description: Allocates space for an object whose size is specified by size and whose value is indeterminate. System memory is usually managed by an operating system. It differs from memory managed by a MemoryManager in that it is not guaranteed to be physically continuous and you cannot request alignment. Passing a size of 0 is not allowed and leads to undefined behavior. The caller is responsible to also call BKNI_Free to free the memory when done. Memory that is not explicitly freed may or may not remain allocated beyond the life-cycle of a particular application. Returns: NULL - Memory could not be allocated Non-NULL - Memory was allocated ****************************************************************************/ #if BKNI_TRACK_MALLOCS #define BKNI_Malloc(size) BKNI_Malloc_tagged(size, __FILE__, __LINE__) void *BKNI_Malloc_tagged( size_t size, const char *file, unsigned line ); #else void *BKNI_Malloc( size_t size /* Number of bytes to allocate */ ); #endif /*************************************************************************** Summary: Dellocate system memory. Description: Causes the memory pointed to by mem to be deallocated, that is, made available for further allocation. The following scenarios are not allowed and lead to undefined behavior: * Passing a pointer which was not returned by an earlier BKNI_Malloc call * Passing a pointer which was already freed * Passing NULL Returns: ****************************************************************************/ #if BKNI_TRACK_MALLOCS #define BKNI_Free(mem) BKNI_Free_tagged(mem, __FILE__, __LINE__) void BKNI_Free_tagged( void *mem, /* Pointer to memory allocated by BKNI_Malloc */ const char *file, unsigned line ); #else void BKNI_Free( void *mem /* Pointer to memory allocated by BKNI_Malloc */ ); #endif #if BKNI_TRACK_MALLOCS /*************************************************************************** Summary: Print all current mallocs ****************************************************************************/ void BKNI_DumpMallocs(void); #endif /*************************************************************************** Summary: Yield the current task to the scheduler. Description: BKNI_Sleep is a sheduler sleep which guarantees you will delay for at least the specified number of milliseconds. It puts the process to sleep and allows the scheduler to run. The minimum sleep time is dependent on the system clock time. If you need a minimum time which is less that the system clock time, you'll need to use BKNI_Delay. Actual sleep time is dependent on the scheduler but will be at least as long as the value specified by the millisec parameter. A sleep value of 0 should cause the scheduler to execute. This may or may not result in any delay. BKNI_Sleep cannot be called from an interrupt context. Use BKNI_Delay instead. Returns: BERR_SUCCESS - The system slept for at least the specified number of milliseconds. BERR_OS_ERROR - The sleep was interrupted before the specified time. ****************************************************************************/ BERR_Code BKNI_Sleep( unsigned int millisec /* minimum number of milliseconds to sleep */ ); /*************************************************************************** Summary: Create an event used by one task to signal another task. Description: Note that there is no 'name' parameter in BKNI_CreateEvent. We do not support named events because they are essentially global variables that can lead to unwanted behavior. Passing in a name for debugging purposes might lead to someone to think we support named events. The event is created in an unsignalled state. Input: event - point to an event handle which will be initialized. Returns: BERR_SUCCESS - The event is allocated and initialized. BERR_OS_ERROR - The event could not be allocated or initialized. ****************************************************************************/ #if BKNI_TRACK_MALLOCS #define BKNI_CreateEvent(event) BKNI_CreateEvent_tagged(event, __FILE__, __LINE__) BERR_Code BKNI_CreateEvent_tagged( BKNI_EventHandle *event, const char *file, int line ); #else BERR_Code BKNI_CreateEvent(BKNI_EventHandle *event); #endif /*************************************************************************** Summary: Destroy an event. Description: If any signal is pending, it is lost. Input: event - event initialized by BKNI_CreateEvent ****************************************************************************/ #if BKNI_TRACK_MALLOCS #define BKNI_DestroyEvent(event) BKNI_DestroyEvent_tagged(event, __FILE__, __LINE__) void BKNI_DestroyEvent_tagged( BKNI_EventHandle event, const char *file, int line ); #else void BKNI_DestroyEvent(BKNI_EventHandle event); #endif /*************************************************************************** Summary: Wait until an event is signalled by BKNI_SetEvent. Description: Suspends execution of the current task until the event specified by the event parameter becomes signalled. The task should be blocked by the scheduler, resulting in no wasted CPU time. This function fails if the event does not become signalled within the period specified by the timeoutMsec parameter. A timeout of zero instructs this function to fail immediately if the event is not signalled. A timeout value of BKNI_INFINTE (defined in bkni_multi.h) causes this function not to return until successful. BKNI_WaitForEvent can be called from a single-task module only if that module follows the rules specified under PortingInterface interrupt handling. For this reason, BKNI_INFINITE is defined in bkni_multi.h. An event that blocks for a less-than-infinite time can be considered as an interruptible sleep. See PortingInterface for a description of interrupt handling in a single-threaded module. A single BKNI_WaitForEvent call will consume all pending signals. However, if multiple tasks call BKNI_WaitForEvent for the same event, it is only guaranteed that at least one will be woken up with the next BKNI_SetEvent call. Some platforms may wake up one, others may wake up all. To avoid problems, Magnum code should only wait on a particular event from a single task. BKNI_WaitForEvent can be called from an interrupt context, but only if timeoutMsec is 0. In this case, it checks if the event has been set, and does not block if it has not. Calling BKNI_WaitForEvent from an interrupt context with a non-zero timeout leads to undefined behavior. Returns: BERR_SUCCESS - An event happened and was consumed. BERR_TIMEOUT - Either the timeout was 0 and no event was already pending, or the timeout expired before an event happened. BERR_OS_ERROR - The system interruped the wait and an event did not happen. ****************************************************************************/ BERR_Code BKNI_WaitForEvent(BKNI_EventHandle event, int timeoutMsec); /*************************************************************************** Summary: Signal an event which causes BKNI_WaitForEvent to return. Description: Causes the event specified by the event parameter to become signalled. At least one task waiting on the event becomes unblocked. If no task is waiting on this event, the signal is remembered and the next call to BKNI_WaitForEvent will succeed immediately. BKNI_SetEvent may be called from an interrupt context. See Also: See BKNI_WaitForEvent for more details and usage rules. ****************************************************************************/ void BKNI_SetEvent(BKNI_EventHandle event); /*************************************************************************** Summary: Reset an event so that there are no signals pending. Description: In certain cases it is necessary to reset an event in order to avoid a race condition. Consider the following code: foo() { SetHardware(); err = BKNI_WaitForEvent(event, timeout); if (err) return err; return AcquireData(); } interrupt() { BKNI_SetEvent(event); } And now consider the following execution sequence: foo() called setHardware() called BKNI_WaitForEvent() called BKNI_WaitForEvent times out and foo returns an error. Interrupt happens and BKNI_SetEvent called foo() called again setHardware() called BKNI_WaitForEvent() called --> BKNI_WaitForEvent returns BERR_SUCCESS from the old interrupt AcquireData() is called before it should be. In order to avoid this problem, BKNI_ResetEvent must be called before setting or resetting hardware. Be careful that there is not a race condition between BKNI_ResetEvent and the actual resetting of hardware. If you cannot disable the particular interrupt, you need to use a critical section. foo() { BKNI_EnterCriticalSection(); BKNI_ResetEvent(event); SetHardware(); BKNI_LeaveCriticalSection(); err = BKNI_WaitForEvent(event, timeout); if (err) return err; return AcquireData(); } A simple implementation of BKNI_ResetEvent is to call BKNI_WaitForEvent with a timeout of 0. For some platforms, there may be a more optimal implementation. Returns: ****************************************************************************/ void BKNI_ResetEvent(BKNI_EventHandle event); /*************************************************************************** Summary: Cause the application or system to abort immediately if possible. On platforms that support it, the system state should be captured. Description: This is called from a failed BDBG_ASSERT() (see DebugInterface). Can be called from an interrupt-context. There is no required behavior for this function. It can be completely empty. There is no need to print an error message from inside BKNI_Fail because the DebugInterface will have printed something before calling it. See Also: DebugInterface, BDBG_ASSERT ****************************************************************************/ void BKNI_Fail(void); /*************************************************************************** Summary: Create a Magnum critical section which protects against concurrent execution by another Magnum critical section or Magnum ISR (interrupt service routine). Description: A Magnum critical section is defined as a block of code between a BKNI_EnterCriticalSection call and a BKNI_LeaveCriticalSection call or any code inside a Magnum ISR (distinguished with an _isr suffix). Be aware that a Magnum critical section may not mean the same thing as an operating system's critical section. Typically, operating system critical sections mean that interrupts are disabled and no context switch is possible. A Magnum critical section may or may not mean this, depending on the implementation of KNI. Magnum critical sections cannot be preempted by other Magnum critical sections. This includes both interrupts and context switching. But it only applies to Magnum code, not to code outside of Magnum. While there are many ways these rules can be implemented in a system, the recommended approach is as following: * If your system executes Magnum-isr code in interrupt context, Magnum critical sections must be implemented by disabling interrupts. * If your system executes Magnum-isr code in task context, Magnum critical sections must be implemented with a global mutex. Be aware that on task-context only systems, critical sections may not prevent the scheduler from time-slicing and executing non-critical section code concurrently with the critical section. Critical sections are also used to protect concurrent access to a register shared with another module. Ideally, there are no registers shared between disconnected software modules, but sometimes this is unavoidable. Magnum code cannot nest critical sections. Calling BKNI_EnterCriticalSection from inside a critical section is not allowed and leads to undefined behavior. Possible results include deadlock or undetected race conditions. A platform implementation might chose to allow BKNI_EnterCriticalSection to nest because of platform-specific considerations. See Also: BKNI_LeaveCriticalSection, Magnum InterruptSafe rules ****************************************************************************/ #if BKNI_DEBUG_CS_TIMING #define BKNI_EnterCriticalSection() BKNI_EnterCriticalSection_tagged(__FILE__, __LINE__) void BKNI_EnterCriticalSection_tagged( const char *file, unsigned line ); #else void BKNI_EnterCriticalSection(void); #endif /*************************************************************************** Summary: Leave a critical section. Description: Calling BKNI_LeaveCriticalSection when you are not in a critical section is not allowed and leads to undefined behavior. See Also: BKNI_EnterCriticalSection, Magnum InterruptSafe rules ****************************************************************************/ #if BKNI_DEBUG_CS_TIMING #define BKNI_LeaveCriticalSection() BKNI_LeaveCriticalSection_tagged(__FILE__, __LINE__) void BKNI_LeaveCriticalSection_tagged( const char *file, unsigned line ); #else void BKNI_LeaveCriticalSection(void); #endif /*************************************************************************** Summary: Verifies a critical section. Description: Assert that code is running in interrupt context, either from an ISR or inside critical section See Also: BKNI_EnterCriticalSection, Magnum InterruptSafe rules ****************************************************************************/ #ifdef BDBG_DEBUG_BUILD #define BKNI_ASSERT_ISR_CONTEXT() BKNI_AssertIsrContext(__FILE__, __LINE__) #else #define BKNI_ASSERT_ISR_CONTEXT() (void)0 #endif void BKNI_AssertIsrContext(const char *filename, unsigned lineno); /* lines below provides aliases for functions safe to call from the interrupt handler */ #define BKNI_Memset_isr BKNI_Memset #define BKNI_Memcpy_isr BKNI_Memcpy #define BKNI_Memcmp_isr BKNI_Memcmp #define BKNI_Memchr_isr BKNI_Memchr #define BKNI_Memmove_isr BKNI_Memmove #define BKNI_Delay_isr BKNI_Delay #define BKNI_SetEvent_isr BKNI_SetEvent typedef struct BKNI_MallocEntryInfo { const void *mem; size_t size; const char *malloc_file; unsigned malloc_line; bool alive; /* sets to true if block is still allocated */ const char *free_file; unsigned free_line; } BKNI_MallocEntryInfo; /* Called from DBG, and should only be used for the debug purposes */ BERR_Code BKNI_GetMallocEntryInfo( const void *memory, /* pointer memory allocated by BKNI_Malloc */ BKNI_MallocEntryInfo *info ); #define BKNI_GetTrackMallocEntry_isr BKNI_GetTrackMallocEntry #ifdef __cplusplus } #endif #endif /* BKNI_H__ */