{"id":1718,"date":"2025-09-05T09:01:30","date_gmt":"2025-09-05T00:01:30","guid":{"rendered":"https:\/\/twarelab.com\/?p=1718"},"modified":"2025-09-12T09:34:26","modified_gmt":"2025-09-12T00:34:26","slug":"stm32f4-f7-how-to-ensure-system-stability-when-using-uart-rx-interrupts","status":"publish","type":"post","link":"https:\/\/twarelab.com\/en\/blog\/stm32f4-f7-how-to-ensure-system-stability-when-using-uart-rx-interrupts\/","title":{"rendered":"[STM32F4\/F7] UART Rx Interrupt \uc0ac\uc6a9\uc2dc \uc2dc\uc2a4\ud15c \uc548\uc815\uc131 \ud655\ubcf4 \ubc29\uc548"},"content":{"rendered":"<p class=\"translation-block\">When developing embedded systems, one of the most common ways to exchange data with external devices is through UART. In many basic serial communication examples, the typical approach is simply checking the RXNE flag to read incoming data.<\/p>\n\n\n\n<p>In most situations, this works fine. However, in more demanding scenarios, issues may arise.<\/p>\n\n\n\n<p class=\"translation-block\">For instance, imagine an external device that keeps transmitting <strong>large amounts of data at very short intervals<\/strong>, regardless of whether your system is ready to respond. In such cases, just relying on RXNE is not enough to guarantee stable operation.<\/p>\n\n\n\n<p class=\"translation-block\">In this post, we\u2019ll explore how to make sure your system can <strong>boot and run reliably<\/strong>, even under these conditions.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The Problem: Why Does the System Hang During Boot?<\/h2>\n\n\n\n<p class=\"translation-block\">During testing, we observed that when an external device continuously transmitted data during boot, <strong>the system sometimes froze during startup<\/strong>.<\/p>\n\n\n\n<p>Tracing the cause revealed the following sequence:<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"1\">\n<li class=\"translation-block\">The external device transmits data \u2192 <strong>Rx Interrupt occurs<\/strong> on the MCU<\/li>\n\n\n\n<li>The MCU should read from the internal buffer, but initialization isn\u2019t finished yet<\/li>\n\n\n\n<li class=\"translation-block\">The ISR cannot be serviced \u2192 <strong>Overrun Error occurs<\/strong><\/li>\n\n\n\n<li>The error flag is not cleared \u2192 system hangs<\/li>\n<\/ol>\n\n\n\n<p class=\"translation-block\">In other words, just handling RXNE isn\u2019t enough. You also need to take care of errors like <strong>Overrun Error (ORE)<\/strong> and <strong>Frame Error (FE)<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The Solution: Handle Error Flags<\/h2>\n\n\n\n<p class=\"translation-block\">To prevent this issue, you must <strong>clear error flags properly<\/strong>.<\/p>\n\n\n\n<p class=\"translation-block\">Both ORE and FE indicate abnormal reception conditions. The fix is simple: clear the corresponding flag and perform a <strong>Dummy Read<\/strong> to flush the buffer.<\/p>\n\n\n\n<p class=\"translation-block\">With this in place, the system can continue working normally, even if data floods in during boot or runtime.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Example Code: Updating the USART2 ISR<\/h2>\n\n\n\n<p class=\"translation-block\">Here\u2019s an example of how the ISR for <strong>USART2<\/strong> can be modified. The same principle applies to any UART port.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\nvoid USART2_IRQHandler(void)\n{  \n    if (LL_USART_IsActiveFlag_ORE(USART2))\n    {\n        LL_USART_ClearFlag_ORE(USART2);\n        LL_USART_ReceiveData8(USART2); \/\/ Dummy Read\n    }\n  \n    if (LL_USART_IsActiveFlag_FE(USART2))\n    {\n        LL_USART_ClearFlag_FE(USART2);\n        LL_USART_ReceiveData8(USART2); \/\/ Dummy Read\n    }\n  \n    if (LL_USART_IsActiveFlag_RXNE(USART2))\n    {\n        LL_USART_ReceiveData8(USART2);\n    }\n  \n    if (LL_USART_IsActiveFlag_TXE(USART2))\n    {\n        \/\/ TX Empty \ucc98\ub9ac\n    }\n  \n    if (LL_USART_IsActiveFlag_TC(USART2))\n    {\n        LL_USART_ClearFlag_TC(USART2);\n    }\n}<\/pre>\n\n\n\n<p class=\"translation-block\">The critical addition here is <strong>handling ORE and FE<\/strong>. By clearing these flags and flushing the buffer,<\/p>\n\n\n\n<p>you eliminate the risk of \u201csystem hang during boot\u201d and greatly improve overall stability.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"translation-block\">Using UART with just the RXNE check is usually enough for basic applications. But in scenarios where <strong>the external device transmits data at a high rate<\/strong>, you need to take extra steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ORE (Overrun Error)<\/strong>: occurs when data isn\u2019t read in time<\/li>\n\n\n\n<li><strong>FE (Frame Error)<\/strong>: occurs when a data frame is invalid<\/li>\n\n\n\n<li><strong>Solution<\/strong> \u2192 Clear the error flag and perform a Dummy Read<\/li>\n<\/ul>\n\n\n\n<p>With this simple enhancement, your system will run far more reliably under heavy UART traffic.<\/p>","protected":false},"excerpt":{"rendered":"<p>With proper error handling, the system stays responsive, even when large bursts of data arrive via UART during boot or normal operation.<\/p>","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":true,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,13,12],"tags":[78,74,79,50],"class_list":["post-1718","post","type-post","status-publish","format-standard","hentry","category-blog","category-en","category-ko","tag-interrupt","tag-stm32f","tag-system-hang","tag-uart"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1718","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/comments?post=1718"}],"version-history":[{"count":5,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1718\/revisions"}],"predecessor-version":[{"id":1747,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/posts\/1718\/revisions\/1747"}],"wp:attachment":[{"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/media?parent=1718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/categories?post=1718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/twarelab.com\/en\/wp-json\/wp\/v2\/tags?post=1718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}