123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- /* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
- Copyright (c) 2014-2017 Datalight, Inc.
- All Rights Reserved Worldwide.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; use version 2 of the License.
- This program is distributed in the hope that it will be useful,
- but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- /* Businesses and individuals that for commercial or other reasons cannot
- comply with the terms of the GPLv2 license may obtain a commercial license
- before incorporating Reliance Edge into proprietary software for
- distribution in any form. Visit http://www.datalight.com/reliance-edge for
- more information.
- */
- /** @file
- @brief Macros to encapsulate MISRA C:2012 deviations in OS-specific code.
- */
- #ifndef REDOSDEVIATIONS_H
- #define REDOSDEVIATIONS_H
- #if REDCONF_OUTPUT == 1
- /* Needed for PRINT_ASSERT() and OUTPUT_CHARACTER().
- */
- #include <stdio.h>
- #endif
- #if (REDCONF_ASSERTS == 1) && (REDCONF_OUTPUT == 1)
- /** @brief Print a formatted message for an assertion.
- Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). Using
- printf() is the most convenient way to output this information; and the risk
- of "unspecified, undefined and implementation-defined" behavior causing
- problems (as cited in the rationale for the rule) is small. The driver does
- not depend on this string being outputted correctly. Furthermore, use of
- printf() disappears when either asserts or output are disabled.
- As Rule 21.6 is required, a separate deviation record is required.
- */
- #define PRINT_ASSERT(file, line) \
- printf("Assertion failed in \"%s\" at line %u\n\r", ((file) == NULL) ? "" : (file), (unsigned)(line))
- #endif
- /** @brief Cast a value to unsigned long.
- Usages of this macro deviate from MISRA C:2012 Directive 4.6. This macro is
- used in two places to cast a uint64_t value (used by the block device
- abstraction for sector numbers) to unsigned long, since third-party code
- which is not under the control of this project uses unsigned long for sector
- numbers. The cast is guaranteed to not lose any information, since when the
- disk is opened the sector count is verified to be less than or equal to an
- unsigned long value. The text of the directive mentions that "it might be
- desirable not to apply this guideline when interfacing with ... code outside
- the project's control", which describes the situation for this deviation.
- As Directive 4.6 is advisory, a deviation record is not required. This
- notice is the only record of the deviation.
- */
- #define CAST_ULONG(ull) ((unsigned long)(ull))
- /** @brief Cast a const-qualified pointer to a pointer which is *not*
- const-qualified.
- Usages of this macro deviate from MISRA C:2012 Rule 11.8. This macro is
- used in exactly one place in order to cope with a poorly designed
- third-party interface. Reliance Edge, at every level of the stack, uses
- const-qualified pointers for buffers used in write operations, since the
- data is read from the buffer, and the buffer does not need to be modified
- (consistent with Rule 8.13). One of the third-party block device interfaces
- that Reliance Edge interfaces with does not follow this convention: it uses
- an unqualified pointer for the buffer parameter of its sector write
- function. This forces the need for the cast to avoid warnings. The
- implementation of the sector write function is provided by the user, so it
- is to be hoped that the buffer is not actually modified.
- As Rule 11.8 is required, a separate deviation record is required.
- */
- #define CAST_AWAY_CONST(type, ptr) ((type *)(ptr))
- /** @brief Allocate zero-initialized (cleared) memory.
- All usages of this macro deviate from MISRA C:2012 Directive 4.12 (required)
- and Rule 21.3 (required). In the context of the single place it is actually
- used, this macro also deviates from Rule 22.1 (required).
- This macro is used in the FreeRTOS block device code in order to allocate a
- RAM disk, when that implementation of the block device is selected. The
- primary rationale for all these deviations is that a) the RAM disk cannot be
- allocated statically (since the volume information is stored in a
- structure), and b) the RAM disk is primarily intended as a temporary testing
- tool for users who want to try out Reliance Edge before the real storage
- media is available. In most real systems, Reliance Edge is used with
- non-volatile storage like SD/MMC or eMMC, not with RAM disks.
- Rule 22.1 states that all resources which are allocated must also be
- explicitly freed. The RAM disk is allocated and never freed, deviating from
- that rule. This is done because the data in the RAM disk is emulating a
- non-volatile storage medium, and thus needs to persist even after the block
- device is closed, to allow the file system to be ormatted and then mounted,
- or unmounted and remounted in the course of a test. Thus the memory will
- remain allocated until the target device is rebooted. This is assumed to be
- acceptable for the primary purpose of the RAM disk, which is preliminary
- testing.
- As Directive 4.12, Rule 21.3, and Rule 22.1 are all required, separate
- deviation records are required.
- */
- #define ALLOCATE_CLEARED_MEMORY(nelem, elsize) calloc(nelem, elsize)
- #if REDCONF_OUTPUT == 1
- /** @brief Output a character to a serial port or other display device.
- Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required).
- FreeRTOS does not include a standard method of printing characters, so
- putchar() is the most convenient and portable way to accomplish the task.
- The risk of "unspecified, undefined and implementation-defined" behavior
- causing problems (as cited in the rationale for the rule) is small. The
- driver does not depend on the character being outputted correctly.
- Furthermore, use of putchar() disappears when output is disabled.
- As Rule 21.6 is required, a separate deviation record is required.
- */
- #define OUTPUT_CHARACTER(ch) (void)putchar(ch)
- #endif
- #if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
- /** @brief Cast a TaskHandle_t (a pointer type) to uintptr_t.
- Usage of this macro deivate from MISRA-C:2012 Rule 11.4 (advisory). This
- macro is used for the FreeRTOS version of RedOsTaskId(). Some RTOSes
- natively use an integer for task IDs; others use pointers. RedOsTaskId()
- uses integers, FreeRTOS uses pointers; to reconcile this difference, the
- pointer must be cast to integer. This is fairly safe, since the resulting
- integer is never cast back to a pointer; and although the integer
- representation of a pointer is implementation-defined, the representation is
- irrelevant provided that unique pointers are converted to unique integers.
- As Rule 11.4 is advisory, a deviation record is not required. This notice
- is the only record of the deviation.
- */
- #define CAST_TASK_PTR_TO_UINTPTR(taskptr) ((uintptr_t)(taskptr))
- #endif
- /** @brief Ignore the return value of a function (cast to void)
- Usages of this macro deviate from MISRA C:2012 Directive 4.7, which states
- that error information must be checked immediately after a function returns
- potential error information.
- If asserts and output are enabled, then this macro is used to document that
- the return value of printf() is ignored. A failure of printf() does not
- impact the filesystem core, nor is there anything the filesystem can do to
- respond to such an error (especially since it occurs within an assert).
- Thus, the most reasonable action is to ignore the error.
- In the STM32 SDIO block device implementation, errors are also ignored in an
- IRQ interrupt handler. This is the most reasonable action to take for two
- reasons: (a) it would be dangerous to spend processor time responding to the
- error inside the IRQ handler; (b) it has been verified that the same error
- is propegated to the DiskRead/Write method, which does return the error to
- the core.
- In the Atmel SD/MMC block device implementation, error information from
- sd_mmc_read_capacity() is ignored. This is a reasonable action because all
- of the possible error conditions were eliminated by a previous check.
- sd_mmc_read_capacity() fails under the same conditions as
- sd_mmc_test_unit_ready(), which was checked ealier in the same function.
- In the mutex module, error information returned from the mutex release
- function is ignored when asserts are disabled. This is a reasonable action
- because the mutex release function (xSemaphoreGive) is documented only to
- fail if the mutex was not obtained correctly, which can be demonstrably
- avoided.
- As Directive 4.7 is required, a separate deviation record is required.
- */
- #define IGNORE_ERRORS(fn) ((void) (fn))
- /** @brief Determine whether a pointer is aligned on a 32-bit boundary.
- This is used to determine whether a data buffer meets the requirements of
- the underlying block device implementation. When transferring data via
- DMA (Direct Memory Access) on an STM32 device, the data buffer must be cast
- as a uint32 pointer, and unexpected behavior may occur if the buffer is not
- aligned correctly.
- There is no way to perform this check without deviating from MISRA C rules
- against casting pointers to integer types. Usage of this macro deviates
- from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites
- against converting pointers to integers is that the chosen integer type may
- not be able to represent the pointer; this is a non-issue here since we use
- uintptr_t. The text says the rule still applies when using uintptr_t due to
- concern about unaligned pointers, but that is not an issue here since the
- integer value of the pointer is not saved and not converted back into a
- pointer and dereferenced. The result of casting a pointer to a sufficiently
- large integer is implementation-defined, but macros similar to this one have
- been used by Datalight for a long time in a wide variety of environments and
- they have always worked as expected.
- This deviation only occurs when using the STM32 SDIO block device
- implementation.
- As Rule 11.4 is advisory, a deviation record is not required. This notice
- is the only record of deviation.
- */
- #define IS_UINT32_ALIGNED_PTR(ptr) (((uintptr_t)(ptr) & (sizeof(uint32_t) - 1U)) == 0U)
- /** @brief Cast a 32-bit aligned void pointer to a uint32 pointer.
- Usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). A
- cast from a void pointer to an object pointer is discouraged because of
- potential alignment issues. However, this macro is only used to cast
- pointers that have already been tested to be 32-bit aligned, so the
- operation will be safe.
- This deviation only occurs when using the STM32 SDIO block device
- implementation.
- As rule 11.5 is advisory, a deviation record is not required. This notice
- is the only record of the deviation.
- */
- #define CAST_UINT32_PTR(ptr) ((uint32_t *) (ptr))
- #endif
|