<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=46&amp;t=17576&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2017-02-08T22:29:15+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=46&amp;t=17576&amp;mode</id>
<entry>
<author><name><![CDATA[wojtekr51]]></name></author>
<updated>2017-02-08T22:29:15+01:00</updated>
<published>2017-02-08T22:29:15+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=17576&amp;p=182168#p182168</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=17576&amp;p=182168#p182168"/>
<title type="html"><![CDATA[STM32 Cortex M3 - delay_us() - wstawka assemblerowa]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=17576&amp;p=182168#p182168"><![CDATA[
Witam. Mam pytanie dotyczące użycia wstawki assemblera w kodzie C. Program dla STM32L1 z Cortex M3. Chcę napisać funkcję opóźniającą delay_us(). Nie mam zbytnio doświadczenia z ASM, więc podpatrzyłem sobie takie rozwiązanie:<br /><br />[syntax=c]#define delay_us_ASM(us) do {\<br />asm volatile (\<br />&quot;MOV R0,%&#91;loops&#93;\n\t&quot;\<br />&quot;1:\n\t&quot;\<br />&quot;NOP\n\t&quot;\<br />&quot;NOP\n\t&quot;\<br />&quot;SUB R0, #1\n\t&quot;\<br />&quot;CMP R0, #0\n\t&quot;\<br />&quot;BNE 1b\n\t&quot; : : &#91;loops&#93; &quot;r&quot; (4*us) : &quot;memory&quot;\<br />);\<br />} while(0)[/syntax] <br />Czy użycie takiej makrodefinicji jako funkcji opóźniającej, jest poprawne? Mam wątpliwość związaną z wpisywaniem wartości do rejestru R0. Czy przed wykonaniem się wstawki rejestr R0 będzie zwolniony? (Czy w ten sposób nie nadpiszę jakiejś informacji umieszczonej wcześniej w R0?) A jeżeli jest to niepoprawne to czy zapakowanie wstawki do funkcji jak poniżej, wykluczy ten problem?<br /><br />[syntax=c]void delay_us_ASM(uint32_t us)<br />{<br />asm volatile (<br />&quot;MOV R0,%&#91;loops&#93;\n\t&quot;<br />&quot;1: \n\t&quot;<br />&quot;NOP\n\t&quot;<br />&quot;NOP\n\t&quot;<br />&quot;SUB R0, #1\n\t&quot;<br />&quot;CMP R0, #0\n\t&quot;<br />&quot;BNE 1b \n\t&quot; : : &#91;loops&#93; &quot;r&quot; (4*us) : &quot;memory&quot;<br />);<br />}[/syntax]<br /><br />Następne moje pytanie związane jest mechanizmem odmierzania 1 us. Procesor jest taktowany 32 MHz, to znaczy że dla 1 us trzeba wykonać 32 cykle zegara. Skonfigurowałem procedurę wstawki asm tak aby odmierzała właściwy czas. Poprawność wprowadzanego opóźnienia zweryfikowałem za pomocą timera, w następujący sposób:<br /><br />[syntax=c]//fragment umieszczony w funkcji main() w pętli while(1) <br />uint16_t last_tim_us, tim_us;<br /><br />last_tim_us = TIM_GetCounter(TIM10); //stan licznika przed opóźnieniem<br />delay_us_ASM(1000);<br />tim_us = TIM_GetCounter(TIM10); //stan licznika po opóźnieniu<br /><br />pomiar1 = (uint16_t)(tim_us - last_tim_us);<br />min = pomiar1 &lt; min ? pomiar1 : min;<br />max = pomiar1 &gt; max ? pomiar1 : max;[/syntax]<br />Najmniejsza odmierzona wartość: 1000, największa 1002.<br />Funkcja zdaje się odmierzać czas poprawnie. Instrukcje NOP, NOP, SUB, CMP trwają łącznie 4 cykle. Z przeprowadzonego doświadczenia wynika, że instrukcja BNE trwa aż 4 cykle, ale nie mogę znaleźć dla niej opisu w dokumentacji. W jaki sposób działa ta instrukcja? Nie rozumiem też zapisów związanych z nazwą &quot;loops&quot;.<br /><br /><br />Przepraszam za może zbytnie wchodzenie w szczegóły, ale tak mnie naszło żeby popytać conieco, na tym zacnym forum. <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1760">wojtekr51</a> — 8 lut 2017, o 22:29</p><hr />
]]></content>
</entry>
</feed>