Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 7 sty 2025, o 05:59


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 13 ] 
Autor Wiadomość
PostNapisane: 12 kwi 2016, o 22:04 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

Witam,
w programie używam bufor pierścieniowy do wysyłania znaków przez uart. Zastanawiam się czy da się wstrzymać wykonywanie przerwań podczas dodawania ramki danych do bufora, aby procedura przerwania nie próbowała dodać innych danych w trakcie. Oczywiście zaległe przerwania po dodaniu danych do bufora powinny się wykonać. Dodam że używam mikrokontrolera sam4s z rdzeniem cortex m4.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 kwi 2016, o 22:13 
Offline
Użytkownik

Dołączył(a): 04 paź 2011
Posty: 8597
Pomógł: 337

W bibliotekach jest taka funkcja
void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority){..}


przyjmuje ona wartość priorytetu oraz nr przerwania,ale zarówno systemowe jak i zewnętrze działają.
możesz wiec sobie tak ustawić przerwania żęby np SysTick miał najniższy priorytet, niższy niż np USART
dzieje się tak dlatego że uC obsługuje np 12 priorytetów wystarczy wiec SYSTick'owi przypisać 11 i SYSTick już żadnego przerwania nie wywłaszczy bo niby jak :).

To się zwie Grupowanie i stanowi maskowanie linii zgłoszenia przerwania tylko w NVICu, ale pamiętaj wagi priorytetów nadal oznaczają to samo.

_________________
Zbuduj swój system [url=https://helion.pl/ksiazki/w-labiryncie-iot-budowanie-urzadzen-z-wykorzystaniem-ukladow-esp8266-i-esp32-andrzej-gromczynski,wlablo.htm#format/d]IOT[/url]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 kwi 2016, o 22:35 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

to rozumiem, ale przykładowo dodaję ramkę danych A która ma 20 bajtów. Robię to w pętli głównej, po dodaniu 10tego bajtu wykona się przerwanie zewnętrzne, które doda w tym momencie ramkę B która też ma 20 bajtów. W efekcie bufor będzie zawierał dane w następującej kolejności: 10 bajtów ramki A, całą ramkę B i 10 bajtów ramki A.

------------------------ [ Dodano po: 1 minucie ]

A mi zależy aby dane się nie wymieszały



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 kwi 2016, o 22:50 
Offline
Użytkownik

Dołączył(a): 26 lip 2012
Posty: 291
Lokalizacja: okolice Opola
Pomógł: 20

To wyłącz tylko przerwanie usartu na ten czas. Po co blokować niepotrzebnie inne w którym nie dotykasz bufora.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 11:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

Troszeczkę w nocy czytałem, więc mogłem coś źle zrozumieć :D

Ale doczytałem się o takich makrach asemblerowych jak:

__disable_irq()
__enable_irq()

i jeśli dobrze zrozumiałem to one ustawiają piorytet na wartość 0 aktualnie wykonywaną czynność.

W takim razie jeśli będę miał taki kod:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


I jeśli w trakcie dodawania ramki A do bufora (czyli w trakcie wykonywania instrukcji z pomiędzy makr __disable_irq() __enable_irq() ) zostanie zgłoszone przerwanie zewnętrzne, to w dużym uproszczeniu w czasie będzie to wyglądać tak:
Obrazek

Czy dobrze myślę, czy jestem w błędzie?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 12:25 
Offline
Użytkownik

Dołączył(a): 26 lip 2012
Posty: 291
Lokalizacja: okolice Opola
Pomógł: 20

Dokładnie tak działa. Tylko napisz po co wyłączać WSZYSTKIE przerwania, skoro możesz wyłączyć tylko to jedno konkretne od usartu. Reszta w której nie dotykasz twojego bufora może nadal chodzić.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 14:38 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

Wydaje mi się że wyłączenie przerwań tylko od usartu nie obroni mnie w takim przypadku przed wymieszaniem danych z ramek A i B. Dane się wymieszają w buforze, a usart wyśle wszystko w takiej kolejności w jakiej jest zapisane.

Zapewne w momencie gdy w pętli głównej chce wykonywać operacje na buforze, pomogłoby zablokowanie przerwań które też modyfikują ten bufor.

Tylko np. wyłączając przerwanie zewnętrzne w rejestrach peryferia PIO mogę zagubić część przerwań zewnętrznych.

Obrazek

Oczywiście z tym mogę się mylić, więc jeśli jest inaczej to nich ktoś mnie naprowadzi na dobry tok myślenia :) Na razie dopiero wchodzę w świat 32bitowych mikrokontrolerów.

Więc tak jak pisałem w poprzednim poście makra __disable_irq() __enable_irq() zmieniają priorytet wykonywania się instrukcji pomiędzy tymi makrami na 0. Instrukcje stają się bardzo ważne a żadne przerwanie nie przerwie ich wykonywania. Ale też te przerwania nie zostaną zagubione, tylko zostaną odłożone na wykonanie się po makrze __enable_irq().

Ze względu na to że USART nie tylko wysyła dane, ale również odbiera je. Muszę uważać z tymi makrami aby instrukcje pomiędzy nimi nie wykonywały się dłużej niż czas przyjścia jednego bajtu danych, ponieważ w przypadku przyjścia kilku bajtów z rzędu mogę nie nadążyć z ich odbiorem co spowoduje ich nadpisywanie.

Jeśli piszę jakieś herezje to mnie poprawcie ;) Piszę po prostu tak jak ja to rozumiem. A dopiero się uczę, więc mogę się mylić.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 16:19 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Cytuj:
Ze względu na to że USART nie tylko wysyła dane, ale również odbiera je. Muszę uważać z tymi makrami aby instrukcje pomiędzy nimi nie wykonywały się dłużej niż czas przyjścia jednego bajtu danych, ponieważ w przypadku przyjścia kilku bajtów z rzędu mogę nie nadążyć z ich odbiorem co spowoduje ich nadpisywanie.
Mając prędkość 9600 bps, to jeden znak przychodzi rzadziej niż co 1 milisekundę (przy większej prędkości odpowiednio częściej, ale pewnie i tak nie używasz większej niż 115200 bps, więc a jest to tylko trochę więcej niż 10 razy szybszej). Więc przy szybkości działania procesora to jest wieczność (oczywiście jak masz poprawnie napisany kod).

Nie do końca rozumiem. Czy masz jeden bufor na dane odbierane i nadawane?
Kto i kiedy pisze do tego bufora oprócz programu głównego (jakie przerwanie)?

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 16:41 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Witam,

Rozumiem, że jakieś przerwanie ( poza programem głównym ) pisze Ci dane do bufora nadawczego, który jest wysyłany w przerwaniu od UARTA, tak? Jeśli tak, to po prostu, na czas przepisywania tego bufora w wątku głównym, wyłącz to przerwanie, które może Ci ten bufor nadpisać. Po co w tym wypadku korzystać z __disable_IRQ(), które w tym wypadku jest metodą typu "Weź większy młotek!" ;-), daj spokój Twój procek to nie M0. Przy okazji, zdarzenia odbiorcze bęą dalej obsługiwane, choćbyś wieki te "parę" bajtów do bufora przepisywał ;-).Nota bene, sprawdź w CMSIS swojego procesora, co tak naprawdę robi to makro, bo podejrzewam, że po prostu: ASM volatile ("cpsid i"), czyli faktycznie wyłącza wszystkie przerwania, a nie "kombinuje" z BASEPRI ( co mógłby sugerować Twój poprzedni post ).

Pozdrawiam, QuadMan.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 16:55 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

rskup napisał(a):
Mając prędkość 9600 bps, to jeden znak przychodzi rzadziej niż co 1 milisekundę (przy większej prędkości odpowiednio częściej, ale pewnie i tak nie używasz większej niż 115200 bps


Masz rację, akurat o tym napisałem trochę na wyrost. Korzystam z prędkości 115200 bps, taktuje mikrokontroler częstotliwością 50 MHz, więc naprawdę musiałbym poszaleć żeby zakłócić odbiór danych.

rskup napisał(a):
Nie do końca rozumiem. Czy masz jeden bufor na dane odbierane i nadawane?
Kto i kiedy pisze do tego bufora oprócz programu głównego (jakie przerwanie)?


mam osobne bufory do odbioru i do wysyłania danych. Dodawać dane do bufora nadawczego będę w pętli głównej i różnych przerwaniach. Jedno dodanie danych to cała ramka np 20 bajtów ( gdzie np pierwszy bajt to bajt staru, a ostatni czyli 20sty to CRC).

Myślę że makra o których wcześniej pisałem powinny się sprawdzić. Po prostu na czas dodawania danych do bufora będę używać makra __disable_irq() __enable_irq()

------------------------ [ Dodano po: 15 minutach ]

QuadMan napisał(a):
.Nota bene, sprawdź w CMSIS swojego procesora, co tak naprawdę robi to makro, bo podejrzewam, że po prostu: ASM volatile ("cpsid i"), czyli faktycznie wyłącza wszystkie przerwania, a nie "kombinuje" z BASEPRI ( co mógłby sugerować Twój poprzedni post ).


Niestety racja. Sprawdziłem i tak jest.
ObrazekObrazek



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 19:30 
Offline
Użytkownik

Dołączył(a): 26 lip 2012
Posty: 291
Lokalizacja: okolice Opola
Pomógł: 20

Instrukcje enable i disavle irq sa częścią cmsis wiec de fakto czescie rdzenia a nie procesora wiec czy stm czy atmel czy nxp beda robily to samo.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 20:25 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Metoda pisania do tego samego bufora przez program główny oraz różne przerwania zawsze będzie powodowała problemy. Czy nie możesz mieć dodatkowych buforów dla przerwań i znaczników, które wykorzystuje procedura w programie głównym ładując odpowiednie dane do bufora nadawania?

Możesz też jak masz stałą długość, to od razu zwiększać wskaźnik na tail-a o 20 bajtów a potem dopiero uzupełniać danymi. Ale wtedy musiałbyś zapewnić, że funkcje wysyłające nie zaczną wysyłać jak jeszcze nie wpisałeś danych (np. mieć dwa wskaźniki na koniec bufora, jeden dla funkcji zapisujących a drugi dla wysyłających - pierwszy zwiększać od razu a drugi po uzupełnieniu danych).

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 13 kwi 2016, o 21:42 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 sie 2013
Posty: 48
Pomógł: 2

O tej drugiej opcji już myślałem, to by była taka rezerwacja miejsca na dane. Można to zrobić z tym drugim wskaźnikiem albo jeśli bufor to przykładowo tablica typu uint16_t ( czasami tak robię, żeby przemycać jakieś dodatkowe dane, jestem świadomy że to marnotrawstwo pamięci) to można na nieużywanej części zmiennej ustawiać jakiś bit informujący funkcję wysyłającą że dane w mniej znaczącym bajcie są prawidłowe. W przypadku gdy funkcja wysyłająca (przerwanie) natrafiłaby na daną, która nie ma ustawionego tego bitu musiałaby włączyć jakiś timer, żeby za jakiś czas znowu została sprawdzona poprawność tej danej.

Trochę ten bufor zrobi się skomplikowany, ale jeśli to zapewni poprawną kolejność wysyłania się danych to warto pokombinować :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 13 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO