1 /* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- 2 * 3 * Copyright (c) 2014-2015 Datalight, Inc. 4 * All Rights Reserved Worldwide. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; use version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 /* Businesses and individuals that for commercial or other reasons cannot 21 * comply with the terms of the GPLv2 license may obtain a commercial license 22 * before incorporating Reliance Edge into proprietary software for 23 * distribution in any form. Visit http://www.datalight.com/reliance-edge for 24 * more information. 25 */ 26 27 /** @file 28 * @brief Macros to encapsulate MISRA C:2012 deviations in OS-specific code. 29 */ 30 #ifndef REDOSDEVIATIONS_H 31 #define REDOSDEVIATIONS_H 32 33 34 #if REDCONF_OUTPUT == 1 35 36 /* Needed for PRINT_ASSERT() and OUTPUT_CHARACTER(). 37 */ 38 #include <stdio.h> 39 #endif 40 41 42 #if ( REDCONF_ASSERTS == 1 ) && ( REDCONF_OUTPUT == 1 ) 43 44 /** Print a formatted message for an assertion. 45 * 46 * Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). Using 47 * printf() is the most convenient way to output this information; and the risk 48 * of "unspecified, undefined and implementation-defined" behavior causing 49 * problems (as cited in the rationale for the rule) is small. The driver does 50 * not depend on this string being outputted correctly. Furthermore, use of 51 * printf() disappears when either asserts or output are disabled. 52 * 53 * As Rule 21.6 is required, a separate deviation record is required. 54 */ 55 #define PRINT_ASSERT( file, line ) \ 56 printf( "Assertion failed in \"%s\" at line %u\n\r", ( ( file ) == NULL ) ? "" : ( file ), ( unsigned ) ( line ) ) 57 #endif 58 59 60 /** Cast a value to unsigned long. 61 * 62 * Usages of this macro deviate from MISRA C:2012 Directive 4.6. This macro is 63 * used in two places to cast a uint64_t value (used by the block device 64 * abstraction for sector numbers) to unsigned long, since third-party code 65 * which is not under the control of this project uses unsigned long for sector 66 * numbers. The cast is guaranteed to not lose any information, since when the 67 * disk is opened the sector count is verified to be less than or equal to an 68 * unsigned long value. The text of the directive mentions that "it might be 69 * desirable not to apply this guideline when interfacing with ... code outside 70 * the project's control", which describes the situation for this deviation. 71 * 72 * As Directive 4.6 is advisory, a deviation record is not required. This 73 * notice is the only record of the deviation. 74 */ 75 #define CAST_ULONG( ull ) ( ( unsigned long ) ( ull ) ) 76 77 78 /** Cast a const-qualified pointer to a pointer which is *not* const-qualified. 79 * 80 * Usages of this macro deviate from MISRA C:2012 Rule 11.8. This macro is 81 * used in exactly one place in order to cope with a poorly designed 82 * third-party interface. Reliance Edge, at every level of the stack, uses 83 * const-qualified pointers for buffers used in write operations, since the 84 * data is read from the buffer, and the buffer does not need to be modified 85 * (consistent with Rule 8.13). One of the third-party block device interfaces 86 * that Reliance Edge interfaces with does not follow this convention: it uses 87 * an unqualified pointer for the buffer parameter of its sector write 88 * function. This forces the need for the cast to avoid warnings. The 89 * implementation of the sector write function is provided by the user, so it 90 * is to be hoped that the buffer is not actually modified. 91 * 92 * As Rule 11.8 is required, a separate deviation record is required. 93 */ 94 #define CAST_AWAY_CONST( type, ptr ) ( ( type * ) ( ptr ) ) 95 96 97 /** Allocate zero-initialized (cleared) memory. 98 * 99 * All usages of this macro deviate from MISRA C:2012 Directive 4.12 (required) 100 * and Rule 21.3 (required). In the context of the single place it is actually 101 * used, this macro also deviates from Rule 22.1 (required). 102 * 103 * This macro is used in the FreeRTOS block device code in order to allocate a 104 * RAM disk, when that implementation of the block device is selected. The 105 * primary rationale for all these deviations is that a) the RAM disk cannot be 106 * allocated statically (since the volume information is stored in a 107 * structure), and b) the RAM disk is primarily intended as a temporary testing 108 * tool for users who want to try out Reliance Edge before the real storage 109 * media is available. In most real systems, Reliance Edge is used with 110 * non-volatile storage like SD/MMC or eMMC, not with RAM disks. 111 * 112 * Rule 22.1 states that all resources which are allocated must also be 113 * explicitly freed. The RAM disk is allocated and never freed, deviating from 114 * that rule. This is done because the data in the RAM disk is emulating a 115 * non-volatile storage medium, and thus needs to persist even after the block 116 * device is closed, to allow the file system to be formatted and then mounted, 117 * or unmounted and remounted in the course of a test. Thus the memory will 118 * remain allocated until the target device is rebooted. This is assumed to be 119 * acceptable for the primary purpose of the RAM disk, which is preliminary 120 * testing. 121 * 122 * As Directive 4.12, Rule 21.3, and Rule 22.1 are all required, separate 123 * deviation records are required. 124 */ 125 #define ALLOCATE_CLEARED_MEMORY( nelem, elsize ) calloc( nelem, elsize ) 126 127 128 #if REDCONF_OUTPUT == 1 129 130 /** Output a character to a serial port or other display device. 131 * 132 * Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). 133 * FreeRTOS does not include a standard method of printing characters, so 134 * putchar() is the most convenient and portable way to accomplish the task. 135 * The risk of "unspecified, undefined and implementation-defined" behavior 136 * causing problems (as cited in the rationale for the rule) is small. The 137 * driver does not depend on the character being outputted correctly. 138 * Furthermore, use of putchar() disappears when output is disabled. 139 * 140 * As Rule 21.6 is required, a separate deviation record is required. 141 */ 142 #define OUTPUT_CHARACTER( ch ) ( void ) putchar( ch ) 143 #endif 144 145 146 #if ( REDCONF_TASK_COUNT > 1U ) && ( REDCONF_API_POSIX == 1 ) 147 148 /** Cast a TaskHandle_t (a pointer type) to uintptr_t. 149 * 150 * Usage of this macro deviate from MISRA-C:2012 Rule 11.4 (advisory). This 151 * macro is used for the FreeRTOS version of RedOsTaskId(). Some RTOSes 152 * natively use an integer for task IDs; others use pointers. RedOsTaskId() 153 * uses integers, FreeRTOS uses pointers; to reconcile this difference, the 154 * pointer must be cast to integer. This is fairly safe, since the resulting 155 * integer is never cast back to a pointer; and although the integer 156 * representation of a pointer is implementation-defined, the representation is 157 * irrelevant provided that unique pointers are converted to unique integers. 158 * 159 * As Rule 11.4 is advisory, a deviation record is not required. This notice 160 * is the only record of the deviation. 161 */ 162 #define CAST_TASK_PTR_TO_UINTPTR( taskptr ) ( ( uintptr_t ) ( taskptr ) ) 163 #endif 164 165 166 /** Ignore the return value of a function (cast to void) 167 * 168 * Usages of this macro deviate from MISRA C:2012 Directive 4.7, which states 169 * that error information must be checked immediately after a function returns 170 * potential error information. 171 * 172 * If asserts and output are enabled, then this macro is used to document that 173 * the return value of printf() is ignored. A failure of printf() does not 174 * impact the filesystem core, nor is there anything the filesystem can do to 175 * respond to such an error (especially since it occurs within an assert). 176 * Thus, the most reasonable action is to ignore the error. 177 * 178 * In the STM32 SDIO block device implementation, errors are also ignored in an 179 * IRQ interrupt handler. This is the most reasonable action to take for two 180 * reasons: (a) it would be dangerous to spend processor time responding to the 181 * error inside the IRQ handler; (b) it has been verified that the same error 182 * is propagated to the DiskRead/Write method, which does return the error to 183 * the core. 184 * 185 * In the Atmel SD/MMC block device implementation, error information from 186 * sd_mmc_read_capacity() is ignored. This is a reasonable action because all 187 * of the possible error conditions were eliminated by a previous check. 188 * sd_mmc_read_capacity() fails under the same conditions as 189 * sd_mmc_test_unit_ready(), which was checked earlier in the same function. 190 * 191 * In the mutex module, error information returned from the mutex release 192 * function is ignored when asserts are disabled. This is a reasonable action 193 * because the mutex release function (xSemaphoreGive) is documented only to 194 * fail if the mutex was not obtained correctly, which can be demonstrably 195 * avoided. 196 * 197 * As Directive 4.7 is required, a separate deviation record is required. 198 */ 199 #define IGNORE_ERRORS( fn ) ( ( void ) ( fn ) ) 200 201 202 /** @brief Determine whether a pointer is aligned on a 32-bit boundary. 203 * 204 * This is used to determine whether a data buffer meets the requirements of 205 * the underlying block device implementation. When transferring data via 206 * DMA (Direct Memory Access) on an STM32 device, the data buffer must be cast 207 * as a uint32 pointer, and unexpected behavior may occur if the buffer is not 208 * aligned correctly. 209 * 210 * There is no way to perform this check without deviating from MISRA C rules 211 * against casting pointers to integer types. Usage of this macro deviates 212 * from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites 213 * against converting pointers to integers is that the chosen integer type may 214 * not be able to represent the pointer; this is a non-issue here since we use 215 * uintptr_t. The text says the rule still applies when using uintptr_t due to 216 * concern about unaligned pointers, but that is not an issue here since the 217 * integer value of the pointer is not saved and not converted back into a 218 * pointer and dereferenced. The result of casting a pointer to a sufficiently 219 * large integer is implementation-defined, but macros similar to this one have 220 * been used by Datalight for a long time in a wide variety of environments and 221 * they have always worked as expected. 222 * 223 * This deviation only occurs when using the STM32 SDIO block device 224 * implementation. 225 * 226 * As Rule 11.4 is advisory, a deviation record is not required. This notice 227 * is the only record of deviation. 228 */ 229 #define IS_UINT32_ALIGNED_PTR( ptr ) ( ( ( uintptr_t ) ( ptr ) & ( sizeof( uint32_t ) - 1U ) ) == 0U ) 230 231 232 /** @brief Cast a 32-bit aligned void pointer to a uint32 pointer. 233 * 234 * Usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). A 235 * cast from a void pointer to an object pointer is discouraged because of 236 * potential alignment issues. However, this macro is only used to cast 237 * pointers that have already been tested to be 32-bit aligned, so the 238 * operation will be safe. 239 * 240 * This deviation only occurs when using the STM32 SDIO block device 241 * implementation. 242 * 243 * As rule 11.5 is advisory, a deviation record is not required. This notice 244 * is the only record of the deviation. 245 */ 246 #define CAST_UINT32_PTR( ptr ) ( ( uint32_t * ) ( ptr ) ) 247 248 249 #endif /* ifndef REDOSDEVIATIONS_H */ 250