{"id":5435,"date":"2018-07-24T11:42:38","date_gmt":"2018-07-24T09:42:38","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=5435"},"modified":"2023-09-11T12:33:39","modified_gmt":"2023-09-11T10:33:39","slug":"w-poszukiwaniu-zrodel-wyjatkow-wszelakich-w-arm-cortex-m3-i-m4","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/w-poszukiwaniu-zrodel-wyjatkow-wszelakich-w-arm-cortex-m3-i-m4\/","title":{"rendered":"W poszukiwaniu \u017ar\u00f3de\u0142 wyj\u0105tk\u00f3w wszelakich w ARM Cortex M3 i M4"},"content":{"rendered":"\n<p>W swojej praktyce projektowej wielokrotnie mia\u0142em do czynienia z sytuacj\u0105, gdy w prawie gotowym produkcie, kt\u00f3rego oprogramowanie sk\u0142ada\u0142o si\u0119 z wielu tysi\u0119cy linii kodu, nagle zaczyna\u0142y dzia\u0107 si\u0119 dziwne rzeczy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Opis problemu<\/strong><\/h2>\n\n\n\n<p>Z regu\u0142y podczas wykonywania test\u00f3w d\u0142ugofalowych, gdy urz\u0105dzenie dzia\u0142a\u0142o wiele godzin b\u0105d\u017a dni, nagle ni st\u0105d ni zow\u0105d dochodzi\u0142o do resetu. Na dodatek w 9 przypadkach na 10 \u00f3w reset mia\u0142 miejsce w losowym momencie, gdzie\u015b w nocy z soboty na niedziel\u0119. Ale to ju\u017c sk\u0142adam na karb og\u00f3lnej z\u0142o\u015bliwo\u015bci rzeczy martwych.<\/p>\n\n\n\n<p>Pr\u00f3by analitycznego rozwi\u0105zania problemu z regu\u0142y spe\u0142za\u0142y na niczym. W g\u0105szczu tysi\u0119cy linii kodu zwykle nie mog\u0142em znale\u017a\u0107 podejrzanego miejsca, w ko\u0144cu kod by\u0142 pisany przeze mnie, a swoje zawsze wygl\u0105da dobrze. Na szcz\u0119\u015bcie jest recepta na taki problem. Je\u017celi w naszym urz\u0105dzeniu zastosowali\u015bmy mikrokontroler oparty o rdze\u0144 Cortex-M3\/M4, to mo\u017cemy skorzysta\u0107 z pewnego oryginalnego mechanizmu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>O wyj\u0105tkach s\u0142\u00f3w kilka<\/strong><\/h2>\n\n\n\n<p>W przypadku rdzenia Cortex M3\/M4 jakakolwiek nieprawid\u0142owa operacja:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>pr\u00f3ba dost\u0119pu do nieistniej\u0105cego adresu pami\u0119ci,<\/li>\n\n\n\n<li>odwo\u0142anie do wska\u017anika zerowego,<\/li>\n\n\n\n<li>dost\u0119p do niewyr\u00f3wnanego adresu,<\/li>\n<\/ul>\n\n\n\n<p>powoduje wygenerowanie wyj\u0105tku (exception).<\/p>\n\n\n\n<p>Z punktu widzenia samego rdzenia ka\u017cdy wyj\u0105tek (Hard Fault, Mem Manage, Bus Fault, Usage Fault) obs\u0142ugiwany jest w spos\u00f3b identyczny jak zwyk\u0142e przerwanie \u2013 poprzez wywo\u0142anie odpowiedniej funkcji obs\u0142ugi (handlera).<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-5442 size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/tablicaWektor\u00f3w-1.jpg\"><img decoding=\"async\" width=\"577\" height=\"417\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/tablicaWektor\u00f3w-1.jpg\" alt=\"Tablica wektor\u00f3w i domy\u015blna funkcja obs\u0142ugi wyj\u0105tk\u00f3w\" class=\"wp-image-5442\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/tablicaWektor\u00f3w-1.jpg 577w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/tablicaWektor\u00f3w-1-300x217.jpg 300w\" sizes=\"(max-width: 577px) 100vw, 577px\" \/><\/a><figcaption class=\"wp-element-caption\">Rysunek 1. Tablica wektor\u00f3w i domy\u015blna funkcja obs\u0142ugi wyj\u0105tk\u00f3w.<\/figcaption><\/figure>\n\n\n\n<p>Wska\u017aniki do wspomnianych funkcji s\u0105 elementami tablicy wektor\u00f3w (<strong>g_pfnVectors<\/strong> z rysunku 1.), umieszczonej na pocz\u0105tku pami\u0119ci programu. O samej tablicy wektor\u00f3w opowiem szerzej w innym artykule.<\/p>\n\n\n\n<p>Domy\u015blna implementacja takiej funkcji obs\u0142ugi (<strong>Default_Handler<\/strong>) zawiera zwykle albo p\u0119tl\u0119 niesko\u0144czon\u0105 (przez co wykonywanie programu zostaje wstrzymane a\u017c do chwili reakcji watchdoga) albo procedura sama wymusza reset mikrokontrolera.<\/p>\n\n\n\n<p>W obu przypadkach wszelkie dowody i wskaz\u00f3wki, kt\u00f3re pozwoli\u0142yby na znalezienie \u017ar\u00f3d\u0142a problemu zostaj\u0105 zniszczone wraz z resetem mikrokontrolera. Wykonywanie programu jest wznawiane w p\u0142onnej nadziei, \u017ce b\u0142\u0105d si\u0119 ju\u017c nie powt\u00f3rzy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>A wi\u0119c do sedna<\/strong><\/h2>\n\n\n\n<p>W momencie wygenerowania wyj\u0105tku rdze\u0144 automatycznie wrzuca na stos osiem czterobajtowych warto\u015bci, s\u0105 to kolejno:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>rejestry og\u00f3lnego przeznaczenia R0-R3,<\/li>\n\n\n\n<li>wska\u017anik stosu (R12\/SP),<\/li>\n\n\n\n<li>rejestr powrotu (LR),<\/li>\n\n\n\n<li>licznik programu (PC),<\/li>\n\n\n\n<li>rejestr statusu (xPSR).<\/li>\n<\/ul>\n\n\n\n<p>Warto\u015bci te nale\u017cy kolejno odczyta\u0107 ze stosu, a nast\u0119pnie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>wys\u0142a\u0107 za po\u015brednictwem interfejsu szeregowego,<\/li>\n\n\n\n<li>zapisa\u0107 w pami\u0119ci nieulotnej i nast\u0119pnie odczyta\u0107 po restarcie.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-5443 size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/wyjatekWfunkcji-1.jpg\"><img decoding=\"async\" width=\"606\" height=\"417\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/wyjatekWfunkcji-1.jpg\" alt=\"Przyk\u0142ad wyj\u0105tku w funkcji wo\u0142anej z innej funkcji\" class=\"wp-image-5443\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/wyjatekWfunkcji-1.jpg 606w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/wyjatekWfunkcji-1-300x206.jpg 300w\" sizes=\"(max-width: 606px) 100vw, 606px\" \/><\/a><figcaption class=\"wp-element-caption\">Rysunek 2. Przyk\u0142ad wyj\u0105tku w funkcji wo\u0142anej z innej funkcji.<\/figcaption><\/figure>\n\n\n\n<p>Dysponuj\u0105c wspomnianymi wy\u017cej warto\u015bciami rejestr\u00f3w oraz plikiem .map, b\u0119d\u0105cym jednym z efekt\u00f3w kompilacji, &nbsp;jeste\u015bmy w stanie znale\u017a\u0107 miejsce w kodzie, w kt\u00f3rym odby\u0142a si\u0119 nieprawid\u0142owa operacja. Wskazuje na nie warto\u015b\u0107 licznika programu PC odczytana ze stosu.<\/p>\n\n\n\n<p>Dodatkowo, znaj\u0105c warto\u015b\u0107 rejestru powrotu (LR) mo\u017cemy ustali\u0107 z jakiego miejsca w kodzie zosta\u0142a wywo\u0142ana funkcja, w kt\u00f3rej dosz\u0142o do wygenerowania wyj\u0105tku.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-5444 size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/mapFile.jpg\"><img decoding=\"async\" width=\"557\" height=\"135\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/mapFile.jpg\" alt=\"Fragment pliku .map zawieraj\u0105cego adresy poszczeg\u00f3lnych funkcji\" class=\"wp-image-5444\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/mapFile.jpg 557w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/mapFile-300x73.jpg 300w\" sizes=\"(max-width: 557px) 100vw, 557px\" \/><\/a><figcaption class=\"wp-element-caption\">Rysunek 3. Fragment pliku .map zawieraj\u0105cego adresy poszczeg\u00f3lnych funkcji.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Przyk\u0142adowy projekt<\/strong><\/h2>\n\n\n\n<p>W za\u0142\u0105czniku znajduje si\u0119 przyk\u0142adowy projekt, wygenerowany za pomoc\u0105 AC6 Studio na zestaw ewaluacyjny Nucleo L476RG.<\/p>\n\n\n\n<p>W sk\u0142ad projektu wchodz\u0105 nast\u0119puj\u0105ce elementy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>main.c, zawieraj\u0105cy g\u0142\u00f3wn\u0105 p\u0119tl\u0119 programu oraz implementacj\u0119 HardFault_Handler\u2019a<\/li>\n\n\n\n<li>Pliki test_functions_one\/two\/three implementuj\u0105ce funkcje generuj\u0105ce wyj\u0105tki<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-5445 size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/strukturaProjektu.jpg\"><img decoding=\"async\" width=\"219\" height=\"281\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/strukturaProjektu.jpg\" alt=\"Struktura przyk\u0142adowego projektu\" class=\"wp-image-5445\"\/><\/a><figcaption class=\"wp-element-caption\">Rysunek 4. Struktura przyk\u0142adowego projektu.<\/figcaption><\/figure>\n\n\n\n<p>Sednem przyk\u0142adu jest spos\u00f3b pobierania wspomnianych wcze\u015bniej warto\u015bci rejestr\u00f3w ze stosu. Aby to wykona\u0107 nale\u017cy w pierwszej kolejno\u015bci ustali\u0107, na kt\u00f3ry z dw\u00f3ch stos\u00f3w (Main Stack czy Process Stack) trafi\u0142y. O tych dw\u00f3ch stosach drogi czytelniku, b\u0119dziesz m\u00f3g\u0142 przeczyta\u0107 w innym artykule. Na razie przyjmij prosz\u0119 do wiadomo\u015bci, \u017ce istniej\u0105.<\/p>\n\n\n\n<p>Po ustaleniu na kt\u00f3ry stos trafi\u0142y nasze dane, nale\u017cy za\u0142adowa\u0107 warto\u015b\u0107 odpowiedniego wska\u017anika stosu (MSP b\u0105d\u017a PSP) do rejestru R0 i wywo\u0142a\u0107 funkcj\u0119 zdejmuj\u0105c\u0105 wspomniane dane ze stosu. Warto\u015b\u0107 wska\u017anika stosu zostanie przekazana przez wspomniany rejestr R0.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter wp-image-5446 size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/hardFaultHandler.jpg\"><img decoding=\"async\" width=\"634\" height=\"262\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/hardFaultHandler.jpg\" alt=\"HardFault_Handler i przekazanie adresu stosu do funkcji\" class=\"wp-image-5446\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/hardFaultHandler.jpg 634w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/hardFaultHandler-300x124.jpg 300w\" sizes=\"(max-width: 634px) 100vw, 634px\" \/><\/a><figcaption class=\"wp-element-caption\">Rysunek 5. HardFault_Handler i przekazanie adresu stosu do funkcji.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>Opisany mechanizm umo\u017cliwia szybkie i sprawne debugowanie nawet przypadk\u00f3w uznanych za beznadziejne. Wszystko to dzi\u0119ki zapisaniu stanu systemu na chwil\u0119 wyst\u0105pienia wyj\u0105tku i powi\u0105zania go z konkretnym adresem w pami\u0119ci programu. Pozwala to na szybkie doj\u015bcie po przys\u0142owiowej nitce do k\u0142\u0119bka do \u017ar\u00f3d\u0142a problemu.<\/p>\n\n\n\n<p><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/Exceptions.zip\">Pobierz przyk\u0142adowy projekt<\/a><\/p>\n\n\n\n<p class=\"has-text-align-right\">.223rem<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;5435&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;15&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.7&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.7\\\/5 ( votes: 15)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;W poszukiwaniu \u017ar\u00f3de\u0142 wyj\u0105tk\u00f3w wszelakich w ARM Cortex M3 i M4&quot;,&quot;width&quot;:&quot;130.8&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 130.8px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.7\/5 ( votes: 15)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>W swojej praktyce projektowej wielokrotnie mia\u0142em do czynienia z sytuacj\u0105, gdy w prawie gotowym produkcie, kt\u00f3rego oprogramowanie sk\u0142ada\u0142o si\u0119 z &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/w-poszukiwaniu-zrodel-wyjatkow-wszelakich-w-arm-cortex-m3-i-m4\/\">Continued<\/a><\/p>\n","protected":false},"author":161,"featured_media":5651,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[563,564,565,566,567,568],"class_list":["post-5435","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-embedded","tag-arm","tag-cortex-m3","tag-cortex-m4","tag-exception","tag-wyjatek"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/06\/arm-cortex-m-processor-hero.png-900x506x2.png","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5435"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/161"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=5435"}],"version-history":[{"count":4,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5435\/revisions"}],"predecessor-version":[{"id":24031,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5435\/revisions\/24031"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/5651"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=5435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=5435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=5435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}