Skocz do zawartości

Kurs STM32L4 – #4 – komunikacja przez UART, debugger


Komentator

Pomocna odpowiedź

Racja jest to w warunku uwzględnione, dopiero po odbiorze znaku końca linii dane z bufora są brane pod uwagę

Myślałem, że jest brany pod uwagę cały bufor w analizie:

if(strcmp(bufor_linii, "Włącz") == 0)

Stąd gdy znajdują się w nim inne rzeczy nie powinno to pasować, ale doczytam o tym jak działa ta instrukcja, dzięki
Na pierwszy rzut oka myślałem że dane do bufora są ładowane do czasu gdy napotkany zostanie znak końca linii.
A odczyt wygląda jakoś mało intuicyjnie 🙂

Edytowano przez dragolice
  • Lubię! 1
Link do komentarza
Share on other sites

@xkonwa witam na forum 🙂 Czy korzystasz z tego samego programu do odbierania danych na PC? Którego dokładnie kodu dotyczy Twój problem? Czy już od pierwszego przykładu pojawia się coś takiego?

Link do komentarza
Share on other sites

Cześć, jestem na etapie, gdzie nadpisałem funkcję "io_putchar", jednakże problem wystąpił już wcześniej. Mianowicie każda wiadomośc jest wysyłana podwójnie, nie mam pojęcia dlaczego. Chciałem to złapać podczas debugowania i zauważyłem, że pierwsza "sztuka" mojej wiadomości wypisywana jest na konsoli, zanim kliknę pierwsze "resume", czyli w momencie gdy po naciśnięciu "Debug" kursor ustawia się na funkcji "HAL_INIT", w tym momencie już wyświetla mi się cała wiadomość, później podczas debugowania działa wszystko w porządku i elegancko wiadomość jest wysyłana znak po znaku i sam program działa w porządku. Jednakże nie mam pojęcia skąd defaultowo ta sama wiadomość pojawia się przed ruszeniem programu. Korzystam z Tera Term.

 

Zauważyłem, że przy zmianie tekstu, pierwsza wiadomość wyświetla się jeszcze stara po naciśnięciu run, podczas gdy przy drugim prawidłowym działaniu jest już nowa wiadomość.

Przy ponownym "runach", już się powielają.

Edytowano przez Tomasz2000PL
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

@Tomasz2000PL witam na forum 🙂 Dla formalności: czyli jak rozumiem, jeśli nie korzystasz z Debuggera, to wszystkie komunikaty wyświetlają się podwójnie, tak? Wygląda na to, że znów pojawiła się jakaś aktualizacja w Cube, która coś tu miesza (lub jest to błąd). Wyeksportuj proszę swój projekt i dodaj go tutaj jako archiwum zip - sprawdzę Twoją wersję projektu i zobaczymy, czy uda się odtworzyć u Ciebie ten błąd.

Link do komentarza
Share on other sites

@Tomasz2000PL przeanalizowałem ten temat, ale nie udało mi się znaleźć nic konkretnego. Mam wrażenie, że tak po prostu działa teraz(?) Cube i szczerze mówią to nie mam 100% pewności czy kiedyś było inaczej. Możliwe, że tak, ale nie pamiętam tego - może ktoś inny potwierdzi?

Po zrobieniu kilku testów wniosek mam taki, że podczas włączania debuggera układ startuje i stary program zaczyna się wykonywać, a dopiero po chwili mikrokontroler jest resetowany i rozpoczyna się właściwie debugowanie nowego kodu, czyli układ jest zatrzymywany i czeka na instrukcję. Jak to sprawdzić najłatwiej? Zmieniając kod np. do takiej postaci:

  /* USER CODE BEGIN 2 */
  printf("Hello world!\r\n");

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  int i = 0;
  while (1)
  {
	  printf("Test %d \r\n", i);
	  HAL_Delay(1000);
	  i++;
    /* USER CODE END WHILE */

Widać wtedy, że po włączeniu debuggera układ "zdąży" wyświetlić napis "Hello world" oraz "Test 0", dalej praca mikrokontrolera jest wstrzymywana. Po ręcznym wystartowaniu kod działa już poprawnie i wartości nie są wyświetlane podwójnie:

d868d-2023-04-02_20-35-04-13981.png

Można też dodać "brzydką" modyfikację w postaci opóźnienia na początku:

  /* USER CODE BEGIN 2 */
  HAL_Delay(200);
  printf("Hello world!\r\n");

Przy 200 ms opóźnienia na starcie nie będzie już tego efektu.

Można również dla testu, po wystartowaniu debuggera, użyć opcji Run > Restart. Program zadziała wtedy poprawnie. Reasumując: to nie jest błąd w programie, dane nie są wysyłane podwójnie. Po prostu podczas startu debuggera na kilkaset milisekund startuje stara wersja programu i widzimy jej efekty zanim nowy kod zostanie wgrany i zatrzymany. Sprawdzę jeszcze coś w tym zakresie, ale na ten moment nie udało mi się zmienić działania debuggera.

Link do komentarza
Share on other sites

Cytat z kursu:
Mamy więc dwie możliwości przekierowania komunikatów z printf na UART:
- możemy napisać własną funkcję __io_putchar i wysyłać za jej pomocą po jednym znaku,
- możemy też zastąpić _write własną wersją tej funkcji i przesyłać od razu cały napis.

Nie udało mi się zrealizować własnej funkcji printf() pierwszą metodą. Sprawdziłem, że postąpiłem dokładnie według opisu w kursie, który jest zresztą tożsamy z przepisami m.in. na forum openSTM32.org. Dość szybko ustaliłem, że moja wersja __io_putchar() w ogóle nie jest wywoływana. Po zagłębieniu się do pliku *lst nie znalazłem żadnego skoku do __io_putchar() wewnątrz funkcji _write(). To tak wstępnie wygląda, jakby kompilator umieścił kod __io_putchar() - oczywiście wersję z biblioteki systemowej, a nie moją wersję z main.c - jako "inline" w trakcie przetwarzania pliku syscalls.c.

Analogiczna robota z podstawieniem własnej wersji funkcji _write() działa zgodnie z oczekiwaniami.

Mam "dziewicze" CubeIDE 1.12.1 Build: 16088_20230420_1057 i nie zmieniałem żadnych domyślnych ustawień kompilacji / linkowania projektu. 
 

Link do komentarza
Share on other sites

Witam ponownie, dopisałem do kodu odbierającego rozkazy informację co odebrano, wydaje mi się, ze tak jest lepiej bo mamy na ekranie terminala potwierdzenie czy rozkaz został zrozumiany:

// przetwarzamy dane
if (strcmp(line_buffer, "on") == 0) {
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
	printf("Odebrano polecenie: %s\n", line_buffer);
} else if (strcmp(line_buffer, "off") == 0) {
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
	printf("Odebrano polecenie: %s\n", line_buffer);
} else {
	printf("Nieznane polecenie: %s\n", line_buffer);
}

A tak to wygląda:

image.png.6c6f0812d0f42ea517fb0734dff4ba28.png

  • Lubię! 2
Link do komentarza
Share on other sites

(edytowany)

Mam 2 pytanka:

1) Jak wyczyścić konsolę tera term? (albo ustawić serial port na com3 i 115200 prędkość jako domyślne, aby można było po prostu tera terma zamykać i otwierać na nowo)

2) Jaki jest sposób ponownego "uruchamiania" programu po wprowadzeniu zmian (np. zmiana w printf). Nie muszę za każdym razem kompilować programu tak?

Należy taki program zatrzymać, i potem zdebugować czy jeszcze jakoś inaczej.
😄

Edytowano przez Dirichleta
Link do komentarza
Share on other sites

@Dirichleta cześć

1) image.thumb.png.ec6cdd0314bc353ca6e63dd37415474a.png

2) Finalny plik elf musi się skompilować, ale masz i tak mechanizm ograniczania kompilacji poszczególnych plików przed wejściem do linkera. Eclipse sprawdza powiązania pomiędzy plikami i kompiluje tylko to do których doszła zmiana. Możesz w jakiś sposób spróbować wymusić kompilację od zera to zobaczysz dużą różnicę w czasie kompilacji.

  • Lubię! 1
Link do komentarza
Share on other sites

@sewerynlukasz to powinno działać, masz do tego panel po prawej stronie IDE gdzie możesz dodać expresion albo live expresion i tam zmienić wartość w locie. Zatrzymaj program na pułapce przed linią która coś robi ze zmienna, ustaw wartość i przejdź dalej.

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.