{"id":171,"date":"2021-08-14T17:42:52","date_gmt":"2021-08-14T17:42:52","guid":{"rendered":"https:\/\/www.jeskevic.info\/?p=171"},"modified":"2021-08-14T17:42:52","modified_gmt":"2021-08-14T17:42:52","slug":"hal_spi_receive-rxonly-bug-stm32","status":"publish","type":"post","link":"https:\/\/www.jeskevic.info\/?p=171","title":{"rendered":"HAL_SPI_Receive &#038; RXONLY bug (STM32)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I need to get data from MAX6675 Cold-Junction-Compensated K-Thermocouple to-Digital Converter (0\u00b0C to +1024\u00b0C). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I need only to read 16 bit and I good. Sounds easy? Not so fast!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Almost every MAX6675 library used full-duplex SPI mode with sending dummy bytes to \/null.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I don&#8217;t need that, I thought. Let&#8217;s configure Cube:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Mode: Receive Only Master<\/li><li>Data Size: 16 bits<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"463\" height=\"503\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-12.png\" alt=\"\" class=\"wp-image-177 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-12.png 463w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-12-276x300.png 276w\" data-sizes=\"(max-width: 463px) 100vw, 463px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 463px; --smush-placeholder-aspect-ratio: 463\/503;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Great, now a bit code:<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s add read function, HAL_SPI_Receive(pointer_to_spi, pointer to buffer, how_many_packets, timeout)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We need to receive only one 16 bit packet, so <strong>1<\/strong>. Very good!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"397\" height=\"124\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-14.png\" alt=\"\" class=\"wp-image-179 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-14.png 397w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-14-300x94.png 300w\" data-sizes=\"(max-width: 397px) 100vw, 397px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 397px; --smush-placeholder-aspect-ratio: 397\/124;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s call this in interrupt (I need defined and time-controlled read time)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"500\" height=\"223\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-13.png\" alt=\"\" class=\"wp-image-178 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-13.png 500w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-13-300x134.png 300w\" data-sizes=\"(max-width: 500px) 100vw, 500px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 500px; --smush-placeholder-aspect-ratio: 500\/223;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Wonderful! Let&#8217;s add output to debug_pin a&amp;b to measure how long it takes to receive &amp; process(PID) data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But then I noticed something really strange.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First HAL_SPI_Receive call (after MCU reset), Receiving Data (pin debug_a) needs, as expected, ~ 16 bits, but, but&#8230; Why it samples 16 extra bits???<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"707\" height=\"312\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-7.png\" alt=\"\" class=\"wp-image-172 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-7.png 707w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-7-300x132.png 300w\" data-sizes=\"(max-width: 707px) 100vw, 707px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 707px; --smush-placeholder-aspect-ratio: 707\/312;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Each next HAL_SPI_Receive call returns data almost immidiately, and also samples 16 bits. WHY? WHAT? I need to receive only <strong>1<\/strong> package! I requested only <strong>1<\/strong> package!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"695\" height=\"302\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-8.png\" alt=\"\" class=\"wp-image-173 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-8.png 695w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-8-300x130.png 300w\" data-sizes=\"(max-width: 695px) 100vw, 695px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 695px; --smush-placeholder-aspect-ratio: 695\/302;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Ok, time for RTFM.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-9-1024x855.png\" alt=\"\" class=\"wp-image-174 lazyload\" width=\"722\" height=\"602\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-9-1024x855.png 1024w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-9-300x251.png 300w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-9-768x641.png 768w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-9.png 1080w\" data-sizes=\"(max-width: 722px) 100vw, 722px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 722px; --smush-placeholder-aspect-ratio: 722\/602;\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-10-1024x385.png\" alt=\"\" class=\"wp-image-175 lazyload\" width=\"710\" height=\"266\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-10-1024x385.png 1024w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-10-300x113.png 300w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-10-768x289.png 768w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-10.png 1080w\" data-sizes=\"(max-width: 710px) 100vw, 710px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 710px; --smush-placeholder-aspect-ratio: 710\/266;\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-11-1024x382.png\" alt=\"\" class=\"wp-image-176 lazyload\" width=\"722\" height=\"269\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-11-1024x382.png 1024w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-11-300x112.png 300w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-11-768x286.png 768w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-11.png 1070w\" data-sizes=\"(max-width: 722px) 100vw, 722px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 722px; --smush-placeholder-aspect-ratio: 722\/269;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Uh, okay, yes, it makes sense! SPI is pretty easy protocol, you send bytes, you receive bytes. If you push out 1 bit, it clocks in 1 bit. So, if you send 2 dummy bytes, it&#8217;ll receive 2 real bytes. But if you want only receive, it virtually doesn&#8217;t know how many bytes you want to receive. So, it generates clock, and fills spi_data_receive regiter. And then waits place for the next packet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With first packet comes first fresh data. And immidiately samples once again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Each next packet &#8211; it takes from spi register data received last time, and immidiately uses it in software. SPI in backend at this moment finishes 16 bit sampling, and stores data for next time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick fix &#8211; and now it looks as expected! (Note SPI SW Enabled debug output &#8211; as in manual, enable, receive one bit, and disable it)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-15.png\" alt=\"\" class=\"wp-image-180 lazyload\" width=\"935\" height=\"244\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-15.png 1002w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-15-300x78.png 300w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-15-768x201.png 768w\" data-sizes=\"(max-width: 935px) 100vw, 935px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 935px; --smush-placeholder-aspect-ratio: 935\/244;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And so it looks in code only (added<em> if RXONLY<\/em>)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"546\" height=\"404\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-18.png\" alt=\"\" class=\"wp-image-183 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-18.png 546w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2021\/08\/image-18-300x222.png 300w\" data-sizes=\"(max-width: 546px) 100vw, 546px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 546px; --smush-placeholder-aspect-ratio: 546\/404;\" \/><figcaption> HAL_SPI_Receive <\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Unfortunatelly, this delay is dependent from SPI clock, and should be tuned for each frequency. Each <em>for <\/em>takes about 12 cycles, so for 128 cycles delay (for Fsck\/128 SPI speed) I need about 12 iterations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For Fsck\/2 SPI speed only 2x _nop; should be inserted&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I have no generic solution for this problem. Use full-duplex with dummy bytes, or disable SPI after one received bit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And RTFM!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I need to get data from MAX6675 Cold-Junction-Compensated K-Thermocouple to-Digital Converter (0\u00b0C to +1024\u00b0C). I need only to read 16 bit and I good. Sounds easy? Not so fast! Almost every MAX6675 library used full-duplex SPI mode with sending dummy bytes to \/null. I don&#8217;t need that, I thought. Let&#8217;s configure Cube: Mode: Receive Only &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.jeskevic.info\/?p=171\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;HAL_SPI_Receive &#038; RXONLY bug (STM32)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[44,43,42,40,41],"class_list":["post-171","post","type-post","status-publish","format-standard","hentry","category-electro","tag-bug","tag-rxonly","tag-spi","tag-stm32","tag-stm32f103c8t6","entry"],"_links":{"self":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=171"}],"version-history":[{"count":1,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/171\/revisions"}],"predecessor-version":[{"id":184,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/171\/revisions\/184"}],"wp:attachment":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}