-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Memfault Firmware SDK 0.24.0 (Build 283912)
- Loading branch information
Memfault Inc
committed
Jul 29, 2021
1 parent
907c880
commit 3973d90
Showing
32 changed files
with
1,068 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
BUILD ID: 268452 | ||
GIT COMMIT: 9d1b0d8da | ||
BUILD ID: 283912 | ||
GIT COMMIT: 7f6c0b54c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
//! @file | ||
//! | ||
//! Copyright (c) Memfault, Inc. | ||
//! See License.txt for details | ||
|
||
#include <stdarg.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
|
||
#include "memfault/config.h" | ||
|
||
#if MEMFAULT_COMPACT_LOG_ENABLE | ||
|
||
#include "memfault/core/compiler.h" | ||
#include "memfault/core/debug_log.h" | ||
#include "memfault/core/compact_log_helpers.h" | ||
#include "memfault/core/compact_log_serializer.h" | ||
#include "memfault/util/cbor.h" | ||
|
||
//! Compact logs are placed in a linker section named "log_fmt". This is a symbol exposed by the | ||
//! linker which points to the start of the section | ||
extern uint32_t __start_log_fmt; | ||
|
||
//! Note: We don't read this in the firmware but it is used during the decode | ||
//! process to sanity check the section is being laid out as we would expect. | ||
MEMFAULT_PUT_IN_SECTION(".log_fmt_hdr") | ||
const sMemfaultLogFmtElfSectionHeader g_memfault_log_fmt_elf_section_hdr = { | ||
.magic = 0x66474f4c, /* LOGf */ | ||
.version = 1, | ||
}; | ||
|
||
bool memfault_vlog_compact_serialize(sMemfaultCborEncoder *encoder, uint32_t log_id, | ||
uint32_t compressed_fmt, va_list args) { | ||
const uint32_t bits_per_arg = 2; | ||
const uint32_t bits_per_arg_mask = (1 << bits_per_arg) - 1; | ||
|
||
const size_t num_args = (31UL - MEMFAULT_CLZ(compressed_fmt)) / bits_per_arg; | ||
|
||
if (!memfault_cbor_encode_array_begin(encoder, 1 /* log_id */ + num_args)) { | ||
return false; | ||
} | ||
|
||
// We use an offset within the section to reduce the space needed when serializing | ||
// the log. | ||
uint32_t log_fmt_offset = log_id - (uint32_t)(uintptr_t)&__start_log_fmt; | ||
|
||
if (!memfault_cbor_encode_unsigned_integer(encoder, log_fmt_offset)) { | ||
return false; | ||
} | ||
|
||
for (size_t i = 0; i < num_args; i++) { | ||
// See memfault/core/compact_log_helpers.h for more details. In essence, | ||
// the promotion type of a given va_arg is encoded within two bits of the | ||
// compressed_fmt field. | ||
const uint32_t type = | ||
(compressed_fmt >> ((num_args - i - 1) * bits_per_arg)) & bits_per_arg_mask; | ||
|
||
bool success = false; | ||
switch (type) { | ||
|
||
case MEMFAULT_LOG_ARG_PROMOTED_TO_INT32: { | ||
int32_t val = va_arg(args, int32_t); | ||
success = memfault_cbor_encode_signed_integer(encoder, val); | ||
break; | ||
} | ||
|
||
case MEMFAULT_LOG_ARG_PROMOTED_TO_INT64: { | ||
// We differentiate between an 64 bit and 32 bit integer arg | ||
// by packing the cbor encoded int in an array. | ||
uint64_t val = va_arg(args, uint64_t); | ||
success = memfault_cbor_encode_array_begin(encoder, 1) && | ||
memfault_cbor_encode_long_signed_integer(encoder, (int64_t)val); | ||
break; | ||
} | ||
|
||
case MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE: { | ||
// Note: Per the ARM ABI, doubles are just serialized out onto the stack | ||
// and occupy 8 bytes: | ||
// | ||
// Chapter 7: THE STANDARD VARIANTS | ||
// For a variadic function the base standard is always used both for argument passing and | ||
// result return. | ||
// | ||
// 6.5 Parameter Passing | ||
// In the base standard there are no arguments that are candidates for a co-processor | ||
// register class. | ||
// | ||
// So for ARM we could just do the following: | ||
// uint64_t val = va_arg(args, uint64_t) | ||
// | ||
// But parsing as a double is more portable and get's optimized away by compilers | ||
// like GCC anyway: https://godbolt.org/z/mVAS7D | ||
MEMFAULT_STATIC_ASSERT(sizeof(uint64_t) == sizeof(double), "double does not fit in uint64_t"); | ||
|
||
// Note: We use memcpy to properly type-pun / avoid strict-aliasing violation: | ||
// https://mflt.io/strict-aliasing-type-punning | ||
double val = va_arg(args, double); | ||
uint64_t double_as_uint64; | ||
memcpy(&double_as_uint64, &val, sizeof(val)); | ||
success = memfault_cbor_encode_uint64_as_double(encoder, double_as_uint64); | ||
break; | ||
} | ||
|
||
case MEMFAULT_LOG_ARG_PROMOTED_TO_STR: { | ||
const char *str = va_arg(args, const char*); | ||
success = memfault_cbor_encode_string(encoder, str != NULL ? str : "(null)"); | ||
break; | ||
} | ||
|
||
default: | ||
break; | ||
|
||
} | ||
|
||
if (!success) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool memfault_log_compact_serialize(sMemfaultCborEncoder *encoder, uint32_t log_id, | ||
uint32_t compressed_fmt, ...) { | ||
va_list args; | ||
va_start(args, compressed_fmt); | ||
const bool success = memfault_vlog_compact_serialize(encoder, log_id, compressed_fmt, args); | ||
va_end(args); | ||
|
||
return success; | ||
} | ||
|
||
#endif /* MEMFAULT_COMPACT_LOG_ENABLE */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
components/include/memfault/core/compact_log_compile_time_checks.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#pragma once | ||
|
||
//! @file | ||
//! | ||
//! Copyright (c) Memfault, Inc. | ||
//! See License.txt for details | ||
//! | ||
//! @brief | ||
//! | ||
//! Compile time validity checks run on compact logs: | ||
//! 1) Enables printf() style Wformat checking | ||
//! 2) Verifies that number of args passed is <= the maximum number supported (15) | ||
|
||
#include "memfault/config.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#include <stdbool.h> | ||
|
||
#if MEMFAULT_COMPACT_LOG_ENABLE | ||
|
||
#include "memfault/core/compiler.h" | ||
#include "memfault/core/preprocessor.h" | ||
|
||
#define MEMFAULT_LOGGING_MAX_SUPPORTED_ARGS 15 | ||
|
||
|
||
static void _run_printf_like_func_check(const char* format, ...) | ||
MEMFAULT_PRINTF_LIKE_FUNC(1, 2); | ||
|
||
//! Mark the function as used to prevent warnings in situations where this header is included but | ||
//! no logging is actually used | ||
MEMFAULT_USED | ||
static void _run_printf_like_func_check(MEMFAULT_UNUSED const char* format, ...) { } | ||
|
||
//! Compilation time checks on log formatter | ||
//! | ||
//! - static asserts that argument list does not exceed allowed length. | ||
//! - Runs printf() style format checking (behind a "if (false)" so that | ||
//! the actual code gets optimized away) | ||
#define MEMFAULT_LOGGING_RUN_COMPILE_TIME_CHECKS(format, ...) \ | ||
do { \ | ||
MEMFAULT_STATIC_ASSERT( \ | ||
MEMFAULT_ARG_COUNT_UP_TO_32(__VA_ARGS__) <= MEMFAULT_LOGGING_MAX_SUPPORTED_ARGS , \ | ||
MEMFAULT_EXPAND_AND_QUOTE(MEMFAULT_ARG_COUNT_UP_TO_32(__VA_ARGS__)) \ | ||
" args > MEMFAULT_LOGGING_MAX_SUPPORTED_ARGS (" \ | ||
MEMFAULT_EXPAND_AND_QUOTE(MEMFAULT_LOGGING_MAX_SUPPORTED_ARGS) ")!"); \ | ||
if (false) { \ | ||
_run_printf_like_func_check(format, ## __VA_ARGS__); \ | ||
} \ | ||
} while (0) | ||
|
||
#endif /* MEMFAULT_COMPACT_LOG_ENABLE */ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
Oops, something went wrong.