Skocz do zawartości

Nucleo-H7 - odłączone piny SDMMC


radek04

Pomocna odpowiedź

Okazało się, że zworki SB14 i SB15 łączą jedynie piny D0 i D1 interfejsu SDMMC1 od złącza Arduino do swoich odpowiedników na złaczu morpho. I faktycznie po ich odlutowaniu problem zniknął. Niestety tylko na chwilę. Wciąż walczę z niezrozumiałym dla mnie problemem, że ten sam program raz działa, raz nie działa. Już przeszedłem na tryb 1-bit, a czujniki zasilam z zewnętrznego źródła. Ostatni pomysł, jaki mam, to porzucenie płytki stykowej i polutowanie wszystkiego. Jeśli to nie zadziała...

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

(edytowany)

I kolejny głupi błąd. Wg mnie w Cube. Po wybraniu jako źródła zegarowego PLL1Q (niezależnie od częstotliwości), karta nie działa. Działa jedynie z PLL2R. 

PS. Widzę, że piszę głównie ze sobą. Ale może kiedyś komuś się przyda...

Edytowano przez radek04
Link do komentarza
Share on other sites

Pewnie schemat już znalazłeś, ale tam jeszcze piszą znowu "SB5 and SB6 to avoid stub of SDMMC signals". Coś z zasilaniem teraz. Rozumiem, że "goły" czytnik też próbowałeś? A płytki stykowe to też może być dobry trop. Jakieś odbicia sygnałów na rzędach pinów (choć to by trzeba przeliczyć, czy częstotliwości goniące kartę faktycznie coś złego robią przy długościach odnóg na płytce stykowej). Ja bym wszystko połączył - polutowane (niby kilka razy używane duponty, ale byle jaka jakość, niby dogięte a nie łączy i wyświetlacz raz działał, raz nie, nowe kable i działa, z płytek stykowych nigdy nie korzystałem), goły czytnik i wtedy. Ewentualnie do gołego dolutować kondensator ceramiczny/tantalowy z czegoś do zasilania na VCC karty. Datasheet (poprawka) od H7 też warto by przejrzeć choć pobieżnie.

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

(edytowany)

@matsobdev, zdaje się, że ten schemat dotyczy starszej wersji płytki Nucleo. Ja mam wersję H743ZI2. W UM2407 zworki SB4 - SB7 odpowiadają za USART3.

Goły czytnik mi nie działa. Testowałem Pololu-2597, ale nie mam pewności co do poprawności opisu wyprowadzeń. CD miał być pod pinem numer 7, a okazuje się, że jest pod numerem 6. Zbyt wiele kombinacji, by wszystkie sprawdzać, nawet dla trybu 1-bit.

SD na 1 bicie działa dobrze, na 4 bitach potrzebny "dobry dotyk". Czyli coś zakłóca. SDMMC2_D3 jest na pinie PB4, który występuje zarówno na złączu Arduino, jak i morpho. Nie znalazłem w instrukcji sposobu na ich rozłączenie. Próbowałem łączyć oba wyprowadzenia, zwierać do masy lub do zasilania, ale bez efektu. Pin ten domyślnie pełni funkcję NJTRST. Czy to może mieć znaczenie?

SDMMC2_D2 (PB3) domyślnie nazywa się (JTDO/TRACESWO). Czy to może być problem?

SDMMC2_D0 jest podłączony do diody LED3. Nie rozłączałem jej, gdyż zdaje się, że nie wpływa ona negatywnie na działanie programu, a pokazuje, kiedy karta ma problemy.

Już wiem, że z samym odczytem 4 czujników nie ma problemu (poza BDMA, ale o tym za chwilę). Bez zapisu osiądam 500 Hz. Program się zwykle nie wyrabia w czasie podczas zapisu na kartę. Chyba raz mi się zdarzyło, że wszystko zadziałało dobrze. Wtedy diody LED2 (zmieniająca stan po wejściu do przerwania timera 500 Hz) oraz LED3 (podłączona do SDMMC2_D0) świeciły jednostajnie (mrugały tak szybko, że nie szło tego zauważyć. Na załączonym filmie typowy przykład, gdy mruganie jest nierównomierne, a program zamiast 10 sekund działa ok. 12 sekund.

Interfejs I2C4 nie posiada "zwykłego" DMA, obsługiwany jest przez BDMA. Czy ktoś się z tym wcześniej spotkał? Jak odczytać wartość z czujnika z użyciem tego trybu? HAL_I2C_Mem_Read_DMA() nie działa w tym przypadku. Nie ma natomiast funkcji HAL_I2C_Mem_Read_BDMA.

Nucleo_H7_SD2.zip

Edit: Kolejna niezrozumiała dla mnie rzecz. gdy do moduły Pololu (tego "gołego") podłączyłem równolegle inny moduł, zaświeciła się LED3 (podłączona do D0) i karta włożona do Pololu zaczęła działać. Po odłączeniu drugiego modułu, dioda gaśnie i karta nie działa.
Dla mnie to już są czary, a nie programowanie...

A może jakiegoś podciągania linii D0 brakuje w Pololu???

Edytowano przez radek04
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

(edytowany)

Chcąc wykluczyć problem z zasilaniem (nie wiem, ile prądu pobiera moduł karty SD), postanowiłem zarówno czujniki, jak i sam moduł podłączyć do niezależnych źródeł napięcia (inny do IMU, inny do SD). O ile czujniki działają, o tyle karta - jeśli nie jest zasilana bezpośrednio z Nucleo - nie działa. Myślałem, że chodzi o wspólny potencjał masy, ale połączenie mas nic nie zmienia.

Jakieś pomysły dotyczące przyczyny takiego stanu rzeczy?

Edytowano przez radek04
Link do komentarza
Share on other sites

4 godziny temu, radek04 napisał:

Bez zapisu osiądam 500 Hz. Program się zwykle nie wyrabia w czasie podczas zapisu na kartę. Chyba raz mi się zdarzyło, że wszystko zadziałało dobrze. Wtedy diody LED2 (zmieniająca stan po wejściu do przerwania timera 500 Hz) oraz LED3 (podłączona do SDMMC2_D0) świeciły jednostajnie (mrugały tak szybko, że nie szło tego zauważyć. Na załączonym filmie typowy przykład, gdy mruganie jest nierównomierne,

Temat jest ciekawy, ale ja mam problem ze zrozumieniem ogólnych założeń nie wnikając w szczegóły na razie.

Czytasz dane z czujników 4x po i2c.
Zapisujesz dane po SPI na kartę SD.
Nie używasz DMA.

No i teraz program wygląda tak:
Inicjujesz wszystko
Uruchamiasz główną pętlę programu... która robi co?
Jak przychodzi przerwanie z i2c wchodzisz do obsługi przerwania i... co dzieje się dalej?

Link do komentarza
Share on other sites

(edytowany)

Pętla główna to w zasadzie inicjacja wszystkich peryferiów, jakieś tam ustawienia czujników i uruchomienie timera. Przerwanie pochodzi od timera, nie od czujnika. Możliwe, że docelowo tym też się zajmę, bo niektóre pomiary wyglądają, jakby się powtarzały, ale to nie jest bieżący problem (tak mi się wydaje).

Główna część programu odbywa się właśnie w przerwaniu zegarowym wywoływanym 500 razy na sekundę:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM7)	// przerwanie pochodzi od timera 7
	{
		timer_tim7++;
		HAL_I2C_Mem_Read_DMA(&hi2c1, MPU9250_ACC_ADDRESS_A, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_A, 14); //14 pomiarów od razu
		HAL_I2C_Mem_Read_DMA(&hi2c2, MPU9250_ACC_ADDRESS_B, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_B, 14); //14 pomiarów od razu
		HAL_I2C_Mem_Read_DMA(&hi2c3, MPU9250_ACC_ADDRESS_C, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_C, 14); //14 pomiarów od razu
		HAL_I2C_Mem_Read_IT(&hi2c4, MPU9250_ACC_ADDRESS_D, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_D, 14); //14 pomiarów od razu

		if (timer_tim7 <= 5000)
		{
			HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
			//printf("%d\n", timer_tim7);

			sprintf(my_string,
					"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
					"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
					"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
					"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",

					MPU9250_Data_A[0],MPU9250_Data_A[1],MPU9250_Data_A[2],MPU9250_Data_A[3],MPU9250_Data_A[4],MPU9250_Data_A[5],MPU9250_Data_A[8],MPU9250_Data_A[9],MPU9250_Data_A[10],MPU9250_Data_A[11],MPU9250_Data_A[12],MPU9250_Data_A[13],//,
					MPU9250_Data_B[0],MPU9250_Data_B[1],MPU9250_Data_B[2],MPU9250_Data_B[3],MPU9250_Data_B[4],MPU9250_Data_B[5],MPU9250_Data_B[8],MPU9250_Data_B[9],MPU9250_Data_B[10],MPU9250_Data_B[11],MPU9250_Data_B[12],MPU9250_Data_B[13],//);//,
					MPU9250_Data_C[0],MPU9250_Data_C[1],MPU9250_Data_C[2],MPU9250_Data_C[3],MPU9250_Data_C[4],MPU9250_Data_C[5],MPU9250_Data_C[8],MPU9250_Data_C[9],MPU9250_Data_C[10],MPU9250_Data_C[11],MPU9250_Data_C[12],MPU9250_Data_C[13],
					MPU9250_Data_D[0],MPU9250_Data_D[1],MPU9250_Data_D[2],MPU9250_Data_D[3],MPU9250_Data_D[4],MPU9250_Data_D[5],MPU9250_Data_D[8],MPU9250_Data_D[9],MPU9250_Data_D[10],MPU9250_Data_D[11],MPU9250_Data_D[12],MPU9250_Data_D[13]); //po dodaniu timer_tim10 nie inkrementuje jego wartości

			if(f_write(&fil, my_string, sizeof(my_string), &numread) != HAL_OK) printf("f_write ERROR\n");

		}else if (timer_tim7 == 5000+1)
		{
			HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, RESET);
			close_file();
			unmount_sd();
			printf("done\n");
			//HAL_TIM_Base_Stop_IT(&htim); //zatrzymanie timera generującego przerwanie
		}
	}
}

W przerwaniu pobieram dane z rejestrów czujników i z użyciem funkcji sprintf() zapisuję dane na kartę.
Jeżeli zakomentuję linię kodu z f_write(), 5000 powtórzeń kodu wykonuje się dokładnie w 10 sekund. Gdy robię zapis na kartę, czasami zapis się zawiesza (dziwne mruganie diody LED2 oraz LED3) i zwykle operacja zajmuje ok. 11-13 sekund.

DMA działa mi na liniach I2C1, I2C2, I2C3. Na I2C4 nie umiem obsłużyć BDMA. Na razie wykorzystuję przerwanie HAL_I2C_Mem_Read_IT() do odczytu stanu tego czujnika.

Edytowano przez radek04
Link do komentarza
Share on other sites

Jak odczyt działa, to może zapisuj jakieś sztywne dane, może nawet odłącz czujniki, wygaś kod od nich i próbuj sam zapis na SD. Rozbić na poszczególne problemy, może tak łatwiej, nie będą na siebie wpływać, jeśli coś gdzieś indziej jest jednak. Ale ten schemat jest na 99% dobry (datashhet od czipu nie). Co jest napisane na czipie, tym głównym? Tak w UM2407 mówią o UART, ale nie że te sygnały łączą lub nie, ale o napięciu pomiędzy układem programatora i docelowym. Zworki do użycia, w zależności, czy na docelowym jest 3,3 czy 1,8 wolta. A tutaj coś ciekawego, nota aplikacyjna do SDMMC od ST.

Tak na szybko i są napięcia przy jakich ma to jak szybko chodzić, jest coś nawet o wspominanym przez Ciebie źródle zegara. Lektura obowiązkowa. Bez dokumentacji ani rusz.

PS. Pewnie "goły" nie działał, bo wg tabeli 1. mogła być ustawiona prędkość, która wymaga innego napięcia, niż te co akceptuje SD (2,7 - 3,6 V). Zagadka (sam nie znam odpowiedzi), czy MCU musi pracować na 1,8, jak jest prędkość wymagająca 1,8? Raczej tak, choć głowy nie dam.

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

No i teraz program wygląda tak:
Inicjujesz wszystko i ustawiasz timer aby mieć przerwanie co określony czas
Uruchamiasz główną pętlę programu... która jest pusta
Jak przychodzi przerwanie z timera wchodzisz do obsługi przerwania i tam pobierasz dane z czujników, potem robisz kopiowanie i formatowanie a następnie zapis na kartę.

Przyznam się, że nie jestem ekspertem od STM32 i nie pomogę w szczegółach, ale ogólnie bym podszedł do zagadnienia troszkę inaczej.

Na razie pytania kontrolne:
Funkcje HAL_I2C_Mem_Read* są blokujące? Czyli cały odczyt z I2C musi się zakończyć zanim funkcja wyjdzie?
To jest zapis na kartę: f_write(&fil, my_string, sizeof(my_string), &numread) - i on też jest blokujący?
 

Jeśli tak to jest, no to pierwsze co się nasuwa:
- nie robimy wszystkiego w przerwaniu timera - architektura programu jest zła
- powinniśmy przejść z funkcji blokujących do nieblokujących. Użyć buforów cyklicznych w ilości równej ilości sprzętowych i2c  (https://pl.wikipedia.org/wiki/Bufor_cykliczny) i zrównoleglić odczyty i zapisy.

EDIT:
Zapis na kartę można zostawić blokujący w pętli głównej - trzeba tylko zobaczyć kiedy można go przerywać przerwaniami od i2c i timera. To jest podpięte pod sprzętowe SPI? To tez jest kluczowe pytanie, ten f_write transluje się na sprzętowe SPI, tam nie ma czasem ręczego machania GPIO pod spodem?

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

(edytowany)

Odczyt robię z wykorzystaniem DMA (w jednym przypadku IT), czyli nie są blokujące.

Jeśli chodzi o f_write(), to też się nad tym zastanawiałem i nie znalazłem odpowiedzi. Wydaje się, że zapis na kartę jest blokujący.

Jak użyć taki bufor cykliczny?

Edytowano przez radek04
Link do komentarza
Share on other sites

Moja konkluzja. Wg dokumentacji ustawić 4 bity bez konwersji napięcia i standardową prędkość, która obsługuje 12,5 lub 25 MB/s (raczej wystarczy) i 3,3 V, ustawić właściwy zegar (maks. 25 MHz dla 12,5 MB/s - można mniej dla pewności np. 20, 50 dla 25) i czytnik Pololu próbować. I próbować, czy będzie działaś ta konfiguracja z przypadku z dotykaniem (płytkę stykową można pominąć dla pewności, przylutować goldpiny i du ponty, czy duponty przylutować do płytki czytnika :P).

A zegar to w sumie na jeszcze mniej, bo karta może się nie wyrobić. Takie okrągłe 8, czy 4 MHz dla 4 albo 2 MB/s styknie.

PS. I tutaj może chodziło z tym SB5 i UART, że z SDMMC może się bić, jak potrzebujesz 1,8 V do danej prędkości i źle mostek ustawisz, to programator z H7 się nie dogada z uwagi na różnicę napięć i pominięcie translatora.

Edytowano przez matsobdev
Link do komentarza
Share on other sites

41 minut temu, radek04 napisał:

Odczyt robię z wykorzystaniem DMA (w jednym przypadku IT), czyli nie są blokujące.

Robisz to:

HAL_I2C_Mem_Read_DMA(&hi2c1, MPU9250_ACC_ADDRESS_A, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_A, 14); //14 pomiarów od razu
HAL_I2C_Mem_Read_DMA(&hi2c2, MPU9250_ACC_ADDRESS_B, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_B, 14); //14 pomiarów od razu
HAL_I2C_Mem_Read_DMA(&hi2c3, MPU9250_ACC_ADDRESS_C, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_C, 14); //14 pomiarów od razu
HAL_I2C_Mem_Read_IT(&hi2c4, MPU9250_ACC_ADDRESS_D, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_D, 14); //14 pomiarów od razu

potem nieistotny if, zapalenie leda i potem dane z MPU9250_Data_* kopiujesz do zmiennej my_string. Ale skąd wiesz, że dane są już odczytane z I2C? Nie trzeba tu poczekać aż I2C skończy odczyt?

47 minut temu, radek04 napisał:

Jeśli chodzi o f_write(), to też się nad tym zastanawiałem i nie znalazłem odpowiedzi. Wydaje się, że zapis na kartę jest blokujący.

To jest dość ważne pytanie...

48 minut temu, radek04 napisał:

Jak użyć taki bufor cykliczny?

Ogólnie powinno być przerwanie i2c jak skończony jest odczyt. W przerwaniu kopiujesz dane do bufora i zwiększasz wskaźnik zapisu. (modulo wielkość bufora)
W pętli głównej lub w przerwaniu na skończony zapis SPI. Odczytujesz dane z bufora i zwiększasz wskaźnik odczytu. (modulo wielkość bufora)
 

 

Link do komentarza
Share on other sites

30 minut temu, matsobdev napisał:

Moja konkluzja. Wg dokumentacji ustawić 4 bity bez konwersji napięcia i standardową prędkość, która obsługuje 12,5 lub 25 MB/s (raczej wystarczy) i 3,3 V, ustawić właściwy zegar (maks. 25 MHz dla 12,5 MB/s - można mniej dla pewności np. 20, 50 dla 25) i czytnik Pololu próbować.

Mówisz, żeby sprawdzać akurat ten moduł, który mi nie działa? Mam kilka innych działający, ale one faktycznie mają wbudowane jakieś układy...

33 minuty temu, matsobdev napisał:

A zegar to w sumie na jeszcze mniej, bo karta może się nie wyrobić. Takie okrągłe 8, czy 4 MHz dla 4 albo 2 MB/s styknie.

Chodzi o SYSCLK? Tak mało ustawić?

 

34 minuty temu, matsobdev napisał:

PS. I tutaj może chodziło z tym SB5 i UART, że z SDMMC może się bić, jak potrzebujesz 1,8 V do danej prędkości i źle mostek ustawisz, to programator z H7 się nie dogada z uwagi na różnicę napięć i pominięcie translatora.

Wszystkie moduły SD, jakie mam, zasilane są 3,3 V.

8 minut temu, pmochocki napisał:

Ale skąd wiesz, że dane są już odczytane z I2C? Nie trzeba tu poczekać aż I2C skończy odczyt?

Nie wiem, do tego jeszcze nie doszedłem. Tak naprawdę, jeśli będzie to wartość z poprzedniego odczytu, to też dla mnie OK. Ważne, by każdy kolejny odczyt był faktycznie kolejnym. Natomiast masz rację, powinienem to sprawdzać. Jest na to prosty sposób?

 

11 minut temu, pmochocki napisał:

W pętli głównej lub w przerwaniu na skończony zapis SPI.

Nie korzystam z SPI, tylko z SDIO 1-bit lub SDIO 4-bit.

Link do komentarza
Share on other sites

9 minut temu, radek04 napisał:

Ważne, by każdy kolejny odczyt był faktycznie kolejnym

Pytanie kontrolne - czy masz włączoną pamięć cache dla danych (D-Cache)? Jak zapewne wiesz układy STM32F7 i H7 mają pamięć cache, więc niekoniecznie dostaniesz jakiekolwiek faktyczne odczyty z DMA o ile nie zadbasz o spójność pamięci podręcznej.

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

12 minut temu, radek04 napisał:

Mówisz, żeby sprawdzać akurat ten moduł, który mi nie działa?

Ale tylko wtedy jak ustawi się odpowiednie prędkości, wg noty aplikacyjnej AN5200, załączonej wcześniej, żeby było sygnałowanie 3,3 V.

12 minut temu, radek04 napisał:

Chodzi o SYSCLK? Tak mało ustawić?

W sumie to nie wiem 😄 Bardziej myślałem, czy da się ustawić osobny dzielnik dla SDMMC z SYSCLK lub innego źródła. Widziałem tylko obrazki z tej noty jak wyżej.

12 minut temu, radek04 napisał:

Mam kilka innych działający, ale one faktycznie mają wbudowane jakieś układy...

Używałeś pinu H7 od kierunku danych? Tak z ciekawości. Czy automatycznie w tę i wewtę działają? W sumie mało istotne pytanie.

Edytowano przez matsobdev
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.