payload: {"action":"created","comment":{"url":"https://api.github.com/repos/memfault/interrupt/pulls/comments/342879430","pull_request_review_id":312145571,"id":342879430,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDM0Mjg3OTQzMA==","diff_hunk":"@@ -0,0 +1,605 @@\n+---\n+title: \"Using Asserts in Embedded Systems\"\n+description:\n+  \"Asserts are a quick and proven way to prevent bugs in embedded systems. An\n+  optimal assert implementation both maximizes the context around the assert\n+  while minimizing code size and RAM usage.\"\n+author: tyler\n+image: /img/debugging-asserts/assert.png\n+---\n+\n+The use of asserts is one of the best ways to find bugs, unintended behavior,\n+programmatic errors, and to learn when systems are no longer 100% functional and\n+need to be reset. If instrumented correctly, an assert can give a developer\n+context about when and where in the code an issue took place. Despite the\n+numerous benefits, the practice of using asserts in firmware is not common or\n+agreed upon.\n+\n+<!-- excerpt start -->\n+\n+By using asserts proactively in embedded systems on debug and production builds,\n+developers can both prevent bugs before shipping and quickly surface and fix\n+them after shipping. Proper assert handling is also the safest way to handle\n+issues and undefined behavior that occur in production. In this post, we'll go\n+over best practices with asserts, when to use asserts, and then come up with a\n+production ready custom assert implementation for an ARM Cortex-M device, all\n+while keeping the code size usage to a minimum.\n+\n+<!-- excerpt end -->\n+\n+_Like Interrupt? [Subscribe](http://eepurl.com/gpRedv) to get our latest posts\n+straight to your mailbox_\n+\n+{:.no_toc}\n+\n+## Table of Contents\n+\n+<!-- prettier-ignore -->\n+* auto-gen TOC:\n+{:toc}\n+\n+## Asserts in Embedded Systems\n+\n+The use of asserts is controversial in the embedded space, **especially** in\n+released or production builds. On top of adhering to the ANSI C standard of\n+`NDEBUG` disabling `assert()`s, many of the popular embedded platforms allow one\n+to\n+[compile](https://github.com/aws/amazon-freertos/blob/master/vendors/nordic/nRF5_SDK_15.2.0/components/libraries/util/nrf_assert.h#L78-L115)\n+[out](https://github.com/espressif/esp-idf/blob/master/components/esp_common/include/esp_err.h#L104-L124)\n+[error](https://github.com/ARMmbed/mbed-os/blob/master/platform/mbed_error.h#L191-L202)\n+[handling](https://github.com/zephyrproject-rtos/zephyr/blob/master/include/sys/__assert.h#L34-L89).\n+\n+In my opinion, disabling asserts for any reason other than to check how much\n+codesize asserts take up in the system is more than likely a **reckless**\n+endeavor, especially if they are used correctly.\n+\n+### Article Disclaimers\n+\n+- This post is about runtime asserting, not compile time asserting, such as\n+  [`static_assert`](https://en.wikichip.org/wiki/c/assert.h/static_assert).\n+- This post is targeting the ever-growing number of **non-safety critical**\n+  embedded systems, such as consumer electronics, Class 1 medical devices, home\n+  automation devices, etc.\n+- The above types of embedded systems are primarily constrained by memory and\n+  code space limitations, so the information below takes this into account.\n+- The examples below are implemented for the ARM Cortex-M series of MCU's. Many\n+  of the concepts can be generalized to other architectures.\n+\n+## Making the Most of Asserts\n+\n+To get the most value from asserting, it is important to set up some postmortem\n+infrastructure. When an assert takes place (or even a system fault), there is _a\n+lot_ of context and data one can capture to help debug these issues without a\n+debugger attached to the device. These include but are not limited to:\n+\n+- the file and line number the assert took place,\n+- the registers at the time of assert\n+- values or function pointers on the stack, to help reassemble the backtrace\n+- the logs that took place before the assert and possibly after the reboot took\n+  place\n+- for those using MyNewt[^1], ESP-IDF[^2], or have Memfault[^3] integrated, a\n+  coredump can be captured at the time of the assert, which will provide a full\n+  dump of system memory and registers.\n+\n+With all of the above, especially coredumps, it becomes advantageous to add as\n+many asserts to the system as possible, especially for capturing those 1 in\n+10,000 hour bugs. This allows developers to quickly track down and investigate\n+bugs affecting users in the field, all without having to reproduce the issue on\n+a development board.\n+\n+## Common Usages of Asserts\n+\n+Every firmware has places where it is and isn't appropriate to assert. The\n+examples below likely apply to most non-safety-critical systems.\n+\n+### When malloc shouldn't fail\n+\n+Dynamic memory allocation is common in embedded systems, especially in today's\n+Internet connected consumer electronics. These devices need to be able to\n+receive an influx Bluetooth packets, use large HTTP buffers, and possibly load\n+assets or fonts into RAM for a user interface. Keeping around statically\n+allocated buffers for all of these functions would be irresponsible, especially\n+for the devices that measure RAM in kilobytes. In these devices, dynamic memory\n+allocation is a must.\n+\n+There are also places where malloc could fail, and where **it shouldn't**.\n+\n+For example, let's give an example of dynamically allocated mutexes.\n+\n+```c\n+Mutex *mutex_create(void) {\n+  Mutex *mutex = malloc(sizeof(Mutex));\n+  ASSERT(mutex);\n+  mutex_init(mutex);\n+\n+  return mutex;\n+}\n+```\n+\n+This malloc **should never fail**, because it would mean the system is out of\n+RAM and should be rebooted to recover itself.\n+\n+### Invalid arguments passed into function\n+\n+Argument checking is one of the best (and easiest) places to assert.\n+\n+We can check for NULL pointers\n+\n+```c\n+void handle_event(Event *evt) {\n+  ASSERT(evt);\n+  ...\n+}\n+```\n+\n+or check sizes of buffers\n+\n+```c\n+void read_packet(void *buf, size_t buf_len) {\n+  ASSERT(buf_len >= sizeof(Packet));\n+  memcpy(...)\n+}\n+\n+```\n+\n+and much more. The benefits of asserting on function arguments include:\n+\n+- developers connected to a debugger very quickly find programmatic mistakes\n+- removes the need to check for argument validity and error handling code in the\n+  upper layers\n+- reduces chances of system faults by catching out-of-bounds accesses and\n+  invalid pointer dereferences.\n+\n+It's not common to see asserts on arguments in vendor and library code, since","path":"_drafts/assert.md","position":153,"original_position":153,"commit_id":"a2c934101b1287fe661784192b11116a923370d5","original_commit_id":"a2c934101b1287fe661784192b11116a923370d5","user":{"login":"franc0is","id":4192460,"node_id":"MDQ6VXNlcjQxOTI0NjA=","avatar_url":"https://avatars3.githubusercontent.com/u/4192460?v=4","gravatar_id":"","url":"https://api.github.com/users/franc0is","html_url":"https://github.com/franc0is","followers_url":"https://api.github.com/users/franc0is/followers","following_url":"https://api.github.com/users/franc0is/following{/other_user}","gists_url":"https://api.github.com/users/franc0is/gists{/gist_id}","starred_url":"https://api.github.com/users/franc0is/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/franc0is/subscriptions","organizations_url":"https://api.github.com/users/franc0is/orgs","repos_url":"https://api.github.com/users/franc0is/repos","events_url":"https://api.github.com/users/franc0is/events{/privacy}","received_events_url":"https://api.github.com/users/franc0is/received_events","type":"User","site_admin":false},"body":"This would be better as a side note (grey box) rather than main text.","created_at":"2019-11-06T01:27:24Z","updated_at":"2019-11-06T01:32:07Z","html_url":"https://github.com/memfault/interrupt/pull/61#discussion_r342879430","pull_request_url":"https://api.github.com/repos/memfault/interrupt/pulls/61","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/comments/342879430"},"html":{"href":"https://github.com/memfault/interrupt/pull/61#discussion_r342879430"},"pull_request":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/61"}}},"pull_request":{"url":"https://api.github.com/repos/memfault/interrupt/pulls/61","id":336123637,"node_id":"MDExOlB1bGxSZXF1ZXN0MzM2MTIzNjM3","html_url":"https://github.com/memfault/interrupt/pull/61","diff_url":"https://github.com/memfault/interrupt/pull/61.diff","patch_url":"https://github.com/memfault/interrupt/pull/61.patch","issue_url":"https://api.github.com/repos/memfault/interrupt/issues/61","number":61,"state":"open","locked":false,"title":"Asserts","user":{"login":"tyhoff","id":1041679,"node_id":"MDQ6VXNlcjEwNDE2Nzk=","avatar_url":"https://avatars2.githubusercontent.com/u/1041679?v=4","gravatar_id":"","url":"https://api.github.com/users/tyhoff","html_url":"https://github.com/tyhoff","followers_url":"https://api.github.com/users/tyhoff/followers","following_url":"https://api.github.com/users/tyhoff/following{/other_user}","gists_url":"https://api.github.com/users/tyhoff/gists{/gist_id}","starred_url":"https://api.github.com/users/tyhoff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tyhoff/subscriptions","organizations_url":"https://api.github.com/users/tyhoff/orgs","repos_url":"https://api.github.com/users/tyhoff/repos","events_url":"https://api.github.com/users/tyhoff/events{/privacy}","received_events_url":"https://api.github.com/users/tyhoff/received_events","type":"User","site_admin":false},"body":"I have not proofread yet, and will still need to work on the story a bit, but the examples are ready and most of the dos and do not's are here as well.","created_at":"2019-11-04T05:07:15Z","updated_at":"2019-11-06T01:32:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6962ed82d68f43a05cac8d9c4b7acc3422449e59","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/memfault/interrupt/pulls/61/commits","review_comments_url":"https://api.github.com/repos/memfault/interrupt/pulls/61/comments","review_comment_url":"https://api.github.com/repos/memfault/interrupt/pulls/comments{/number}","comments_url":"https://api.github.com/repos/memfault/interrupt/issues/61/comments","statuses_url":"https://api.github.com/repos/memfault/interrupt/statuses/a2c934101b1287fe661784192b11116a923370d5","head":{"label":"memfault:tyler/assert-post","ref":"tyler/assert-post","sha":"a2c934101b1287fe661784192b11116a923370d5","user":{"login":"memfault","id":45582074,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ1NTgyMDc0","avatar_url":"https://avatars0.githubusercontent.com/u/45582074?v=4","gravatar_id":"","url":"https://api.github.com/users/memfault","html_url":"https://github.com/memfault","followers_url":"https://api.github.com/users/memfault/followers","following_url":"https://api.github.com/users/memfault/following{/other_user}","gists_url":"https://api.github.com/users/memfault/gists{/gist_id}","starred_url":"https://api.github.com/users/memfault/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/memfault/subscriptions","organizations_url":"https://api.github.com/users/memfault/orgs","repos_url":"https://api.github.com/users/memfault/repos","events_url":"https://api.github.com/users/memfault/events{/privacy}","received_events_url":"https://api.github.com/users/memfault/received_events","type":"Organization","site_admin":false},"repo":{"id":180670875,"node_id":"MDEwOlJlcG9zaXRvcnkxODA2NzA4NzU=","name":"interrupt","full_name":"memfault/interrupt","private":false,"owner":{"login":"memfault","id":45582074,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ1NTgyMDc0","avatar_url":"https://avatars0.githubusercontent.com/u/45582074?v=4","gravatar_id":"","url":"https://api.github.com/users/memfault","html_url":"https://github.com/memfault","followers_url":"https://api.github.com/users/memfault/followers","following_url":"https://api.github.com/users/memfault/following{/other_user}","gists_url":"https://api.github.com/users/memfault/gists{/gist_id}","starred_url":"https://api.github.com/users/memfault/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/memfault/subscriptions","organizations_url":"https://api.github.com/users/memfault/orgs","repos_url":"https://api.github.com/users/memfault/repos","events_url":"https://api.github.com/users/memfault/events{/privacy}","received_events_url":"https://api.github.com/users/memfault/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/memfault/interrupt","description":"A community for embedded software makers.","fork":false,"url":"https://api.github.com/repos/memfault/interrupt","forks_url":"https://api.github.com/repos/memfault/interrupt/forks","keys_url":"https://api.github.com/repos/memfault/interrupt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/memfault/interrupt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/memfault/interrupt/teams","hooks_url":"https://api.github.com/repos/memfault/interrupt/hooks","issue_events_url":"https://api.github.com/repos/memfault/interrupt/issues/events{/number}","events_url":"https://api.github.com/repos/memfault/interrupt/events","assignees_url":"https://api.github.com/repos/memfault/interrupt/assignees{/user}","branches_url":"https://api.github.com/repos/memfault/interrupt/branches{/branch}","tags_url":"https://api.github.com/repos/memfault/interrupt/tags","blobs_url":"https://api.github.com/repos/memfault/interrupt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/memfault/interrupt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/memfault/interrupt/git/refs{/sha}","trees_url":"https://api.github.com/repos/memfault/interrupt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/memfault/interrupt/statuses/{sha}","languages_url":"https://api.github.com/repos/memfault/interrupt/languages","stargazers_url":"https://api.github.com/repos/memfault/interrupt/stargazers","contributors_url":"https://api.github.com/repos/memfault/interrupt/contributors","subscribers_url":"https://api.github.com/repos/memfault/interrupt/subscribers","subscription_url":"https://api.github.com/repos/memfault/interrupt/subscription","commits_url":"https://api.github.com/repos/memfault/interrupt/commits{/sha}","git_commits_url":"https://api.github.com/repos/memfault/interrupt/git/commits{/sha}","comments_url":"https://api.github.com/repos/memfault/interrupt/comments{/number}","issue_comment_url":"https://api.github.com/repos/memfault/interrupt/issues/comments{/number}","contents_url":"https://api.github.com/repos/memfault/interrupt/contents/{+path}","compare_url":"https://api.github.com/repos/memfault/interrupt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/memfault/interrupt/merges","archive_url":"https://api.github.com/repos/memfault/interrupt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/memfault/interrupt/downloads","issues_url":"https://api.github.com/repos/memfault/interrupt/issues{/number}","pulls_url":"https://api.github.com/repos/memfault/interrupt/pulls{/number}","milestones_url":"https://api.github.com/repos/memfault/interrupt/milestones{/number}","notifications_url":"https://api.github.com/repos/memfault/interrupt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/memfault/interrupt/labels{/name}","releases_url":"https://api.github.com/repos/memfault/interrupt/releases{/id}","deployments_url":"https://api.github.com/repos/memfault/interrupt/deployments","created_at":"2019-04-10T22:07:35Z","updated_at":"2019-11-04T20:54:04Z","pushed_at":"2019-11-05T05:49:53Z","git_url":"git://github.com/memfault/interrupt.git","ssh_url":"git@github.com:memfault/interrupt.git","clone_url":"https://github.com/memfault/interrupt.git","svn_url":"https://github.com/memfault/interrupt","homepage":"https://interrupt.memfault.com","size":42270,"stargazers_count":21,"watchers_count":21,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":6,"open_issues":1,"watchers":21,"default_branch":"master"}},"base":{"label":"memfault:master","ref":"master","sha":"824d1f2644e1e63595d5e14a2bfe78bc3d4a8e84","user":{"login":"memfault","id":45582074,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ1NTgyMDc0","avatar_url":"https://avatars0.githubusercontent.com/u/45582074?v=4","gravatar_id":"","url":"https://api.github.com/users/memfault","html_url":"https://github.com/memfault","followers_url":"https://api.github.com/users/memfault/followers","following_url":"https://api.github.com/users/memfault/following{/other_user}","gists_url":"https://api.github.com/users/memfault/gists{/gist_id}","starred_url":"https://api.github.com/users/memfault/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/memfault/subscriptions","organizations_url":"https://api.github.com/users/memfault/orgs","repos_url":"https://api.github.com/users/memfault/repos","events_url":"https://api.github.com/users/memfault/events{/privacy}","received_events_url":"https://api.github.com/users/memfault/received_events","type":"Organization","site_admin":false},"repo":{"id":180670875,"node_id":"MDEwOlJlcG9zaXRvcnkxODA2NzA4NzU=","name":"interrupt","full_name":"memfault/interrupt","private":false,"owner":{"login":"memfault","id":45582074,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ1NTgyMDc0","avatar_url":"https://avatars0.githubusercontent.com/u/45582074?v=4","gravatar_id":"","url":"https://api.github.com/users/memfault","html_url":"https://github.com/memfault","followers_url":"https://api.github.com/users/memfault/followers","following_url":"https://api.github.com/users/memfault/following{/other_user}","gists_url":"https://api.github.com/users/memfault/gists{/gist_id}","starred_url":"https://api.github.com/users/memfault/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/memfault/subscriptions","organizations_url":"https://api.github.com/users/memfault/orgs","repos_url":"https://api.github.com/users/memfault/repos","events_url":"https://api.github.com/users/memfault/events{/privacy}","received_events_url":"https://api.github.com/users/memfault/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/memfault/interrupt","description":"A community for embedded software makers.","fork":false,"url":"https://api.github.com/repos/memfault/interrupt","forks_url":"https://api.github.com/repos/memfault/interrupt/forks","keys_url":"https://api.github.com/repos/memfault/interrupt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/memfault/interrupt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/memfault/interrupt/teams","hooks_url":"https://api.github.com/repos/memfault/interrupt/hooks","issue_events_url":"https://api.github.com/repos/memfault/interrupt/issues/events{/number}","events_url":"https://api.github.com/repos/memfault/interrupt/events","assignees_url":"https://api.github.com/repos/memfault/interrupt/assignees{/user}","branches_url":"https://api.github.com/repos/memfault/interrupt/branches{/branch}","tags_url":"https://api.github.com/repos/memfault/interrupt/tags","blobs_url":"https://api.github.com/repos/memfault/interrupt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/memfault/interrupt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/memfault/interrupt/git/refs{/sha}","trees_url":"https://api.github.com/repos/memfault/interrupt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/memfault/interrupt/statuses/{sha}","languages_url":"https://api.github.com/repos/memfault/interrupt/languages","stargazers_url":"https://api.github.com/repos/memfault/interrupt/stargazers","contributors_url":"https://api.github.com/repos/memfault/interrupt/contributors","subscribers_url":"https://api.github.com/repos/memfault/interrupt/subscribers","subscription_url":"https://api.github.com/repos/memfault/interrupt/subscription","commits_url":"https://api.github.com/repos/memfault/interrupt/commits{/sha}","git_commits_url":"https://api.github.com/repos/memfault/interrupt/git/commits{/sha}","comments_url":"https://api.github.com/repos/memfault/interrupt/comments{/number}","issue_comment_url":"https://api.github.com/repos/memfault/interrupt/issues/comments{/number}","contents_url":"https://api.github.com/repos/memfault/interrupt/contents/{+path}","compare_url":"https://api.github.com/repos/memfault/interrupt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/memfault/interrupt/merges","archive_url":"https://api.github.com/repos/memfault/interrupt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/memfault/interrupt/downloads","issues_url":"https://api.github.com/repos/memfault/interrupt/issues{/number}","pulls_url":"https://api.github.com/repos/memfault/interrupt/pulls{/number}","milestones_url":"https://api.github.com/repos/memfault/interrupt/milestones{/number}","notifications_url":"https://api.github.com/repos/memfault/interrupt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/memfault/interrupt/labels{/name}","releases_url":"https://api.github.com/repos/memfault/interrupt/releases{/id}","deployments_url":"https://api.github.com/repos/memfault/interrupt/deployments","created_at":"2019-04-10T22:07:35Z","updated_at":"2019-11-04T20:54:04Z","pushed_at":"2019-11-05T05:49:53Z","git_url":"git://github.com/memfault/interrupt.git","ssh_url":"git@github.com:memfault/interrupt.git","clone_url":"https://github.com/memfault/interrupt.git","svn_url":"https://github.com/memfault/interrupt","homepage":"https://interrupt.memfault.com","size":42270,"stargazers_count":21,"watchers_count":21,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":6,"open_issues":1,"watchers":21,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/61"},"html":{"href":"https://github.com/memfault/interrupt/pull/61"},"issue":{"href":"https://api.github.com/repos/memfault/interrupt/issues/61"},"comments":{"href":"https://api.github.com/repos/memfault/interrupt/issues/61/comments"},"review_comments":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/61/comments"},"review_comment":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/memfault/interrupt/pulls/61/commits"},"statuses":{"href":"https://api.github.com/repos/memfault/interrupt/statuses/a2c934101b1287fe661784192b11116a923370d5"}},"author_association":"MEMBER"}}
other: {"actor":{"display_login":"franc0is"}}