<?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=55&amp;t=15195&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-04-23T19:20:52+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=55&amp;t=15195&amp;mode</id>
<entry>
<author><name><![CDATA[radek_w]]></name></author>
<updated>2016-04-23T19:20:52+01:00</updated>
<published>2016-04-23T19:20:52+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=15195&amp;p=159068#p159068</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=15195&amp;p=159068#p159068"/>
<title type="html"><![CDATA[ATXMega USB - ASF - STDIO - SD Card]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=15195&amp;p=159068#p159068"><![CDATA[
W poprzednim poście <a href="http://forum.atnel.pl/topic15184.html"  class="postlink">LINK</a> pokazałem jak w bardzo prosty sposób w Atmel Studio 7 przy pomocy bibliotek ASF wykorzystać port USB, zdefiniować go jako port szeregowy i przekierować no niego potoki STDIN/STDOUT.<br />W tym poście chcę dodatkowo podłączyć kartę SD korzystając z bibliotek Atmela, a informacje o karcie SD będą wyświetlane poprzez port szeregowy emulowany przez interfejs USB procesora.<br /><br />Ważną sprawą jest fakt, że ASF (Atmel Software Fundation) to gotowe sterowniki, komponenty, usługi i funkcje realizujące obsługę portów IO, interfejsów komunikacyjnych, usług i procedur do wykorzystania w naszym kodzie.<br />Czasem dzięki kilku liniom kodu i odpowiednim definicjom można uzyskać naprawdę spektakularne efekty.<br /><br />Poniżej obrazek ze strony Atmela pokazujący strukturę ASF, <br /><img src="http://asf.atmel.com/docs/latest/doxygen_mainpage/images/asf_structure.jpg" alt="Obrazek" /><br /><br />W naszym projekcie będziemy korzystali z następujących komponentów ASF:<br />- „GPIO service” do zdefiniowania trybu pracy portów procesora<br />- „SD/MMC stack component” do komunikacji z kartą SD<br />- „SD/MMC memory Access komponent” zawierający funkcję odczytu i zapisu danych na/z karty<br />- „USB Device (service) CDC_STDIO” – do obsługi USB w trybie emulacji portu szeregowego przechwytującego STDIN/STDOUT<br /><br />Użyte w projekcie komponenty ASF w oknie ASF Wizard powinny wyglądać TAK<br /><a href="https://obrazkiforum.atnel.pl/911/dd290d4535025ea49db19d7d982d7c4e.PNG"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/911/dd290d4535025ea49db19d7d982d7c4e.PNG" alt="Obrazek" /></a><br /><br />Po dodaniu komponentów czas na konfigurację plików nagłówkowych.<br />Tak jak poprzednio konfigurujemy pliki <strong>conf_clock.h</strong> oraz <strong>conf_usb.h</strong><br /><br /><strong>Plik /config/conf_clock.h definiuje parametry taktowania procesora.</strong><br />Modyfikujemy w nim trzy sekcjie:<br /><br />1. zmieniamy parametr CONFIG_SYSCLK_SOURCE  z domyślnego 2MHz na 32Mhz<br />[syntax=c]//#define CONFIG_SYSCLK_SOURCE          SYSCLK_SRC_RC2MHZ<br />#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_RC32MHZ[/syntax]<br />2. zmieniamy parametr CONFIG_SYSCLK_PSADIV z domyślnego SYSCLK_PSADIV_1 na SYSCLK_PSADIV_2<br />[syntax=c]/* Fbus = Fsys / (2 ^ BUS_div) */<br />#define CONFIG_SYSCLK_PSADIV          SYSCLK_PSADIV_2<br />#define CONFIG_SYSCLK_PSBCDIV         SYSCLK_PSBCDIV_1_1[/syntax]<br />3. usuwamy komentarz w liniach zawierających CONFIG_OSC_RC32_CAL i CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC<br />[syntax=c]#define CONFIG_USBCLK_SOURCE                USBCLK_SRC_RCOSC<br />#define CONFIG_OSC_RC32_CAL                 48000000UL<br />#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC  OSC_ID_USBSOF[/syntax]<br /><br /><br /><strong>Teraz zajmijmy się plikiem /config/conf_usb.h</strong><br />W nim znajdzmy definicję funkcji wywoływanych po aktywacji portu usb<br />Musimy odnaleźć w nim definicje UDI_CDC_ENABLE_EXT, UDI_CDC_DISABLE_EXT<br />i zamienić na poniższe ...<br />[syntax=c]//! Interface callback definition<br />//#define  UDI_CDC_ENABLE_EXT(port)          true<br />//#define  UDI_CDC_DISABLE_EXT(port)<br />#define UDI_CDC_ENABLE_EXT(port) stdio_usb_enable()<br />extern bool stdio_usb_enable(void);<br />#define UDI_CDC_DISABLE_EXT(port) stdio_usb_disable()<br />extern void stdio_usb_disable(void);[/syntax]<br />Linie te są odpowiedzialne za podłączenie/odłączenie STDIO w momencie gdy jest aktywowany/deaktywowany port USB z obsługą urządzenia typu Communication Device Class.<br />Przyda się jeszcze zakomentować poniższą linie znajdującą się gdzieś na początku pliku....<br />[syntax=c]#warning You must refill the following definitions with a correct values[/syntax]<br /><br />Nowością będzie definicja pliku <strong>conf_board.h</strong>.<br />W pliku tym definiujemy połączenia procesora do komponentów zewnętrznych.<br />W tym przypadku będą te definicje podłączenia karty SD oraz przycisku sprzętowego FLIP podłączonego do portu E5 procesora.<br />Jeśli nie mamy przełącznika WRITE_PROTECT to go nie definiujemy, poniżej jest on zakomentowany ponieważ u mnie nie występuje.<br /><br />Zawartość mojego pliku conf_board.h wygląda tak:<br />[syntax=c]#ifndef CONF_BOARD_H<br />#define CONF_BOARD_H<br /><br />//definicja przycisku FLIP<br />#define FLIP_GPIO_PORT&amp;PORTE<br />#define FLIP_GPIO_PINPIN5_bm<br />#define FLIP_NOT_PRESSED(PORTE.IN &amp; PIN5_bm) != 0<br /><br />//definicja sposobu podłączenia karty SD/MMC<br />#define CONF_BOARD_SD_MMC_SPI<br />#define SD_MMC_SPI_MEM_CNT1<br /><br />#define SD_MMC_SPI                  &amp;SPIC<br />#define SD_MMC_SPI_SCK              IOPORT_CREATE_PIN(PORTC,7)<br />#define SD_MMC_SPI_MISO             IOPORT_CREATE_PIN(PORTC,6)<br />#define SD_MMC_SPI_MOSI             IOPORT_CREATE_PIN(PORTC,5)<br />#define SD_MMC_SPI_0_CS             IOPORT_CREATE_PIN(PORTC,4)<br />#define SD_MMC_0_CD_GPIO            IOPORT_CREATE_PIN(PORTE, 0)<br />#define SD_MMC_0_CD_DETECT_VALUE    0<br />/*<br />#define SD_MMC_0_WP_GPIO            IOPORT_CREATE_PIN(PORTE, 3)<br />#define SD_MMC_0_WP_DETECT_VALUE    0<br />*/<br />#endif // CONF_BOARD_H[/syntax]<br /><br />Ponieważ mój zestaw nie jest żadną z płyt uruchomieniowo/deweloperskich Atmela, wieć muszę jeszsze do pliku <br /><strong>/ASF/common/boards/user_board/init.c</strong> dopisać zawartość procedury board_init, która inicjuje komponenty zewnętrzne i porty procesora do współpracy z nimi.<br />Jak widać ja musiałem tylko konfigurować porty IO do współpracy z kartą SD oraz pin E5 do którego jest podłączony microswitch [FLIP].<br /><br />[syntax=c]void board_init(void)<br />{<br />/* This function is meant to contain board-specific initialization code<br /> * for, e.g., the I/O pins. The initialization can rely on application-<br /> * specific board configuration, found in conf_board.h.<br /> */<br />#if ((defined SD_MMC_0_MEM) &amp;&amp; (SD_MMC_0_MEM == ENABLE)) || ((defined SD_MMC_1_MEM) &amp;&amp; (SD_MMC_1_MEM == ENABLE))<br />ioport_configure_port_pin(&amp;PORTE, PIN0_bm, IOPORT_PULL_UP | IOPORT_DIR_INPUT);//CARD DETECT<br />ioport_configure_port_pin(&amp;PORTC, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);   //CS<br />ioport_configure_port_pin(&amp;PORTC, PIN6_bm, IOPORT_DIR_INPUT);//MISO<br />ioport_configure_port_pin(&amp;PORTC, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);//MOSI<br />ioport_configure_port_pin(&amp;PORTC, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);//SCK<br />sd_mmc_init();<br />#endif<br /><br />//FLIP button<br />ioport_configure_port_pin(FLIP_GPIO_PORT, FLIP_GPIO_PIN, IOPORT_PULL_UP | IOPORT_DIR_INPUT);<br />}[/syntax]<br /><br />Skoro jest już tyle... należy zająć się programem głównym...<br /><br />Po uruchomieniu procesora program czeka za naciśnięcie przycisku podłączonego do portu E5 (zwieramy pin procesora do masy),<br />daje nam to czas na otwarcie okienka terminala portu szeregowego (u mnie COM5).<br />Po naciśnięciu przycisku FLIP program działa w pętli badając status karty i wyświetlając informacje o niej.<br /><br />Zmienna <strong>status</strong> przechowuje informacje o aktualnym statusie karty SD.<br />Zmienna <strong>port</strong> to numer portu ( możliwe jest zdefiniowanie i podłączenie kilku kart SD i wybór pomiędzy nimi za pomocą sygnału CD, użyjemy wtedy SD_MMC_0_CD_GPIO, SD_MMC_1_CD_GPIO itd. w pliku conf_board.h )<br /><br />Cała reszta to użycie funkcji i definicji które są już w ASF.<br /><br />A tak wygląda program<br /><br />[syntax=c]#include &lt;asf.h&gt;<br /><br />static void main_display_info_card(uint8_t slot)<br />{<br />printf(&quot;Card information:\n\r&quot;);<br />printf(&quot;    type: &quot;);<br />switch (sd_mmc_get_type(slot)) {<br />case CARD_TYPE_SD | CARD_TYPE_HC:<br />printf(&quot;SDHC&quot;);<br />break;<br />case CARD_TYPE_SD:<br />printf(&quot;SD&quot;);<br />break;<br />case CARD_TYPE_MMC | CARD_TYPE_HC:<br />printf(&quot;MMC High Density&quot;);<br />break;<br />case CARD_TYPE_MMC:<br />printf(&quot;MMC&quot;);<br />break;<br />case CARD_TYPE_SDIO:<br />printf(&quot;SDIO\n\r&quot;);<br />return;<br />case CARD_TYPE_SD_COMBO:<br />printf(&quot;SD COMBO&quot;);<br />break;<br />case CARD_TYPE_UNKNOWN:<br />default:<br />printf(&quot;Unknown\n\r&quot;);<br />return;<br />}<br />printf(&quot;\n\r&quot;);<br />printf(&quot;    size: %d MB\n\r&quot;, (uint16_t)(sd_mmc_get_capacity(slot)/1024));<br />printf(&quot;    write protect status: &quot;);<br />if (sd_mmc_is_write_protected(slot)) { printf(&quot;ON\n\r&quot;); } else {printf(&quot;OFF\n\r&quot;);}<br />}<br /><br /><br />int main (void)<br />{<br />Ctrl_status status;<br />uint8_t slot = 0;<br /><br />sysclk_init();//konfiguracja zegara<br />irq_initialize_vectors();//inicjacja wektorów przerwań (jeśli używamy)<br />cpu_irq_enable();//włączenie przerwań<br />board_init();//inicjacja płytki - tu powinno się inicjować porty IO<br />sleepmgr_init();//optionalny moduł ospowiedzialny za oszczedzanie energii i uśpienie<br />stdio_usb_init();//inicjacja obsługi portu USB<br /><br />//czekamy na nacisniecie przycisku FLIP (port E5)<br />while (FLIP_NOT_PRESSED) {};<br /><br />//no to dalej <br />printf(&quot;\n\r-- SD/MMC/SDIO Card Example\n\r&quot;);<br />printf(&quot;-- Compiled: %s %s --\n\r&quot;, __DATE__, __TIME__);<br /><br />while(1) {<br />printf(&quot;Please plug an SD, MMC or SDIO card in slot #%i.\n\r&quot;,slot);<br />/* Wait card present and ready */<br />do {<br />status = sd_mmc_test_unit_ready(slot);<br />if (CTRL_FAIL == status) {<br />printf(&quot;Card install FAIL\n\r&quot;);<br />printf(&quot;Please unplug and re-plug the card.\n\r&quot;);<br />while (CTRL_NO_PRESENT != sd_mmc_check(slot)) {<br />}<br />}<br />} while (CTRL_GOOD != status);<br /><br />// Display basic card information<br />main_display_info_card(slot);<br /><br />printf(&quot;Please unplug and re-plug the card.\n\r&quot;);<br />while (CTRL_NO_PRESENT != sd_mmc_check(slot)) {};<br />}<br />}[/syntax]<br /><br /><br />Działający program wygląda tak jak poniżej, jest to przykład dla dwóch różnych kart SD.<br /><a href="https://obrazkiforum.atnel.pl/911/6c8eec619b3bb5e864c27d26aa424280.PNG"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/911/6c8eec619b3bb5e864c27d26aa424280.PNG" alt="Obrazek" /></a><br /><strong><br />I to by było na tyle ... w następnym &quot;odcinku&quot; dodamy do projektu bibliotekę FatFS ( jej Atmelowską wersję )<br />i spróbujemy coś odczytać i zapisać.</strong><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=911">radek_w</a> — 23 kwi 2016, o 19:20</p><hr />
]]></content>
</entry>
</feed>