[FRDM KL25Z] Zepsuta "freedomka"? Niekoniecznie

Pytania dotyczące problemów ze zrozumieniem kart katalogowych, not aplikacyjnych dla mkrokontrolerów ARM firmy Freescale, rozwiązania układowe z zastosowaniem tych mikrokontrolerów.
Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1096
Rejestracja: czwartek 03 wrz 2015, 22:02

[FRDM KL25Z] Zepsuta "freedomka"? Niekoniecznie

Postautor: Antystatyczny » wtorek 12 kwie 2016, 19:52

Witam serdecznie.

Modułu FRDM-KL25Z raczej nie muszę nikomu przedstawiać, bo na pewno wszyscy znają je przynajmniej z widzenia lub reklamy. Wspomnę jednak, że moduł ten jest mechanicznie zgodny z Arduino UNO. Ta zgodność spowodowała, że musiałem się zmierzyć z problemem, który początkowo wydawał się być niezwykle poważny. Ok, ale od początku. Zgodność mechaniczna zachęciła mnie do zamontowania wyświetlacza TFT na "freedomce". Pasuje wspaniale, ale... No właśnie, ale.

Pech chciał, że projektant obwodu drukowanego "freedomki" umieścił jeden z sygnałów (pinów) procesora w zewnętrznym rzędzie pinów, który to właśnie zapewnia mechaniczną zgodność z Arduino. O który pin chodzi? Dokładnie o ten:
kl25z-pta4.JPG


Jest to pin PTA4, którego domyślną funkcją tuż po włączeniu zasilania jest wywoływanie przerwania niemaskowalnego (NMI). Przerwanie to wywoływane jest, gdy na pinie pojawi się stan niski. Pewnie już się domyślacie, że to będzie sprawiało problemy... Przecież niektóre shieldy Arduino mogą mieć w tym miejscu rezystor do GND! ;-)

Tak też było w momencie zaaplikowania wyświetlacza do freedomki. Procek się zamrażał, debugger milczał, bo nie potrafił się połączyć z układem docelowym... i właściwie można było pomyśleć, że coś uległo uszkodzeniu. W tym konkretnym przypadku głównym winowajcą okazały się bufory 74HC245 dopasowujące poziomy napięć do akceptowalnych przez kontroler wyświetlacza, gdy korzystamy z tradycyjnej płytki Arduino UNO. Sposób przeróbki wyświetlacza pokażę nieco później, a teraz skupię się na kompleksowym rozwiązaniu problemu. Najpierw przedstawię krótki programik do migania diodą pozbawiony obsługi pinu PTA4:

Kod: Zaznacz cały

#include <stdbool.h>
#include "mcu.h"

#define RED_LED_PIN 18


int main(void)
{
    volatile uint32_t loop;

    //podłączam zegar do portu B
   SIM->SCGC5 |= (SIM_SCGC5_PORTB_MASK);
   //ustawiam wyjcie na pinie 18  portu B
    PTB->PDDR |=  (1ul << RED_LED_PIN);
    //ustawiam tryb pracy tego pinu. 1 oznacza  tryb GPIO
    PORTB->PCR[RED_LED_PIN] = PORT_PCR_MUX(1);

    while(true)
    {
       //maa ptelka opóźniajca, bym widział miganie diody
       for(loop = 0; loop < 500000; ++loop);
       //zmiana stanu na pinie. Tzw. toggle
       PTB->PTOR = (1ul << RED_LED_PIN);
    }
}


Po załadowaniu tego programu do procka oraz sprowokowaniu NMI w taki sposób:

WP_20160412_004.jpg


Freedomka przestała odpowiadać, a program się nie wykonywał. Po przejrzeniu dokumentacji doszedłem do wniosku, że skoro nie da się zamaskować NMI, bo przecież to jest niemaskowalne przerwanie, należy je najzwyczajniej w świecie obsłużyć. Cały myk polega na tym, że wewnątrz obsługi tego przerwania zmieniam tryb pracy pinu PTA4 na zwykły GPIO o kierunku wejściowym oraz kasuję flagę przerwania poprzez jej odczyt. Ot, cała filozofia... Proste, prawda? :) Nasiedziałem się nad tym... A oto zmodyfikowana wersja migacza diodowego:

Kod: Zaznacz cały

#include <stdbool.h>
#include "mcu.h"

#define RED_LED_PIN 18

void NMI_Handler(void);

int main(void)
{
    volatile uint32_t loop;

    //podłączam zegar do portu B
   SIM->SCGC5 |= (SIM_SCGC5_PORTB_MASK);
   //ustawiam wyjcie na pinie 18  portu B
    PTB->PDDR |=  (1ul << RED_LED_PIN);
    //ustawiam tryb pracy tego pinu. 1 oznacza  tryb GPIO
    PORTB->PCR[RED_LED_PIN] = PORT_PCR_MUX(1);

    while(true)
    {
       //maa ptelka opóźniajca, bym widział miganie diody
       for(loop = 0; loop < 500000; ++loop);
       //zmiana stanu na pinie. Tzw. toggle
       PTB->PTOR = (1ul << RED_LED_PIN);
    }
}

//obsługa  przerwania niemaskowalnego
void NMI_Handler(void)
{
   //podłączam zegar do portu A
   SIM->SCGC5 |= (SIM_SCGC5_PORTA_MASK);
   //odczytując stan flagi przerwania automatycznie ją kasuję
   if(PORTA->PCR[4] &PORT_PCR_ISF_MASK)
   {
      ;//nic nie robię
   }
   //bezwarunkowo przełączam pin PTA4 (NMI) w tryb GPIO
   //domyślnie po resecie ten pin będzie wejściem
   PORTA->PCR[4] = PORT_PCR_MUX(1);
   
   //i tyle...po bólu :-)
}


Od teraz pin PTA4 nie będzie nam już sprawiał problemów!

Ok, a miałem jeszcze pokazać, jak przerobiłem wyświetlacz. Kilka słów wyjaśnienia. Pin wyświetlacza oznaczony jako RD steruje przy okazji kierunkiem pracy buforów 74HC245. Gdy stan na pinie RD jest niski, bufory są w trybie wyjściowym, co powoduje, że na ich wyjściach są stany niskie (tak, tak, właśnie...). Wystarczy pin RD podciągnąć rezystorem do 3V3 i już mamy święty spokój, a freedomka się nie zamraża.

Tak to wygląda przed przeróbką:

WP_20160412_001.jpg


Po zamontowaniu rezystora:

WP_20160412_002.jpg


Oraz zmontowany na nowej taśmie piankowej:

WP_20160412_007.jpg


No i na koniec efekt działania na freedomce:

WP_20160412_009.jpg


Mam nadzieję, że opis jest klarowny i nikt nie będzie miał kłopotu z okiełznaniem NMI, ale w razie czego proszę śmiało pytać.

Pozdrawiam!
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Wróć do „Freescale - problemy układowe”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość