logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR][C] Optymalizacja wykorzystania zasobów, Ethernet

damiano713 26 Sie 2009 15:40 3194 18
REKLAMA
  • #1 6945746
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Witam!

    Od kilku dni produkuje tony kodu w C na AVR'ka.
    Programuje urządzenie sieciowe oparte na Atmega32. Na pokładzie mam ENC28J60, 32kb SRAM i 128kB EEPROM.

    Dylemat jest następujący: jak zorganizować dane w pamięciach RAM aby wszystko optymalnie chodziło.
    Teraz używam 500B wewnętrznego RAM na bufor gdzie wczytuje cały pakiet sieciowy z ENC. Nie pozwala mi to na operowanie pełnymi pakietami sieciowymi tj. 1514B. W RAM AVR jest też miejsce na tablice portów gdzie przechowuje wskaźniki do funkcji aplikacji sieciowych i stan klient/serwer. Zewnętrzny RAM przechowuje tablice TCP, ARP i UDP. Są to wpisy na temat aktualnego stanu połączenia dla TCP i UDP a adresów IP i MAC dla ARP.

    Bufor sieciowy musi być trzymany w RAM wewnętrznym, gdyż bardzo łatwo mi rzutować dane pakietu na wskaźnik struktury języka C (bardzo łatwo się wtedy operuje na danych). Myślałem natomiast o innym triku który wymaga ingerencji w sterownik enc28j60. Konkretnie, zamiast funkcji enc28j60ReceivePacket, która wczytuje cały pakiet z RAM karty sieciowej do wewnętrznego RAM, zastąpiłbym ją funkcją która wczytuje do bufora tylko 14B (tyle ile zajmuje nagłówek Ethernet). Dzięki temu mogę rozpoznać jakiego pakietu się spodziewam.
    Kolejną funkcją byłaby taka która na podstawie danych z nagłówka Ethernet wczytuje dane IP/ARP. Tutaj znowu rozpoznanie kolejnych danych i wczytanie nagłówka ICMP/TCP/UDP.
    Dane, natomiast byłyby wczytywane do zewnętrznego SRAM, pozwoliłoby to na operowanie na pakietach maksymalnej wielkości.

    Kolejny pomysł ma się wysyłaniu pakietów. Nagłówki składane w RAM wewnętrznym, bez wyliczania sumy CRC, dlaczego, o tym później. Wysłane do ENC, wraz z danymi składowanymi w SRAM zewnętrznym.
    I znów możliwość generowania pełnych pakietów 1514B.

    Najważniejsza myśl z dziedziny szybkości działania to sumy CRC. Moja atmega z zegarem 12,5MHz (pobieranym z karty sieciowej) spędza mnóstwo czasu na generowaniu sumy kontrolnej. Trzeba odciążyć procesor.
    Nie znalazłem w sieci projektu który korzystałby do generowania wbudowanego w ENC28J60 kontrolera DMA. Piekielnie szybkiego i niezawodnego.
    Żeby tego dokonać trzeba znowu ingerować w funkcje wysyłania pakietów, enc28j60SendPacket, i po zapisaniu wszystkich danych w karcie sieciowej obliczyć sumy CRC i zapisać w odpowiednich komórkach pakietu.

    To co tu opisałem oczywiście nie musi być poprawne, to tylko rozmyślania. Przed sprawdzeniem w praktyce chciałbym się poradzić czy to się opłaca i jak Wam się to widzi.
    Nie lubię znacznie modyfikować działania programów które mają ponad 2000 linijek kodu i działają dosyć dobrze, dlatego chce mieć wszystko rozplanowane.
    Oczywiście wszelkie inne propozycje mile widziane!

    Peace for all!
  • REKLAMA
  • Pomocny post
    #2 6945812
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Pamięć wewnętrzna 2KB - 1514B na ramkę, reszta na stos. Sekcję data, bss oraz opcjonalną stertę wyrzucić do zewnętrznego ramu, chociaż nie wiem na czym niby polega trudność w rzutowaniu wskaźnika - pamięć i wewnętrzna i zewnętrzna są dostępne w dokładnie ten sam sposób.
    Co do odczytywania przy odbiorze i składania przy nadawaniu można wykorzystać dwie proste metody: przy odbieraniu ładujesz cały pakiet, do funkcji przetwarzającej nagłówek ethernet przekazujesz wskaźnik na całość, długość całości, przekazując dalej odpowiednio przesuwasz wskaźnik - tak mam w dwóch moich implementacjach. Przy składaniu pakietu łatwo jest zrobić tablicę wskaźników uzupełnianą od końca - pierwsza funkcja od np udp umieszcza w pamięci dane, wrzuca wskaźnik i długość, potem umieszcza gdzieś nagłówek, wrzuca wskaźnik i długość, potem ip wrzuca swoje dane etc.. po dotarciu do końca można wysyłać bajty idąc po wskaźnikach (pierwsza z implementacji, gdzie korzystam z rtl8019) lub najpierw przenieść wszystkie bajty do jednego ciągłego bloku i dopiero wysłać (druga z moich implementacji wynikacjąca z zastosowania DMA).
    Funkcje liczące crc można zoptymalizować w asm, da się sprowadzić do 4 cykli na bajt wliczając rozgałęzienia.
  • REKLAMA
  • #3 6945848
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Nie dodałem, że mogę maksymalnie wykorzystać 1kB pamięci RAM AVR.

    Cytat:
    chociaż nie wiem na czym niby polega trudność w rzutowaniu wskaźnika - pamięć i wewnętrzna i zewnętrzna są dostępne w dokładnie ten sam sposób.

    RAM mam podłączony poprzez zatrzask do zwykłych portów uC. Jak na razie to kopiowałem sobie kawałek pamięci zewnętrznej do bufora w RAM i tutaj operowałem.
    Czy da się zrobić żeby kompilator robił to za mnie:?:

    Cytat:
    Funkcje liczące crc można zoptymalizować w asm, da się sprowadzić do 4 cykli na bajt wliczając rozgałęzienia.

    Tak jak u mnie w tym momencie. Lecz ENC z zegarem 25MHz będzie to robił znacznie szybciej. Pytanie tylko czy to się opłaca.
  • #4 6945991
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Liczenie sum hm.. w nagłówku ip jest tak mało do liczenia, że szybciej jest zrobić to programowo niż wysłać polecenie układowi żeby policzył - zresztą i tak trzeba policzyć pseudonagłówek, a to jest jeden z wyników częściowych sumy kontrolnej z ip. Przy udp można zrezygnować z sum kontrolnych (wpisać 0). Jedyne gdzie pojawia się korzyść, to przy icmp oraz tcp, sumę z pseudonagłówka wpisać do pola checksum, puścić liczenie na nagłówku i danych i wpisać nową wartość do pola checksum. To czy jest to opłacalne musisz ocenić sam - ja powiem, że komplikuje to trochę kod, gdyż trzeba rozpatrywać przypadek transmisji z wyliczaniem sumy oraz bez, tutaj transmisja jest szeregowa (o ile pamiętam), to można by wyliczanie takich rzeczy uzyskać programowo podczas gdy sprzętowe SPI wysyła dane. Jeśli jednak układ sam sprawdza takie przypadki, to czemu nie.
  • #5 6946397
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Tak też myślałem zrobić.
    Na pewno przy TCP było by sporo szybciej gdybym nie liczył tego CRC sam.
    Co do samych obliczeń to działa to tak ze podaje układowi pointer do początku danych i pointer do końca. Suma zapisuje się w rejestrze. Wtedy mógłbym go dopisać do danych do wysłania bezpośrednio w buforze karty sieciowej.

    Myślałem jeszcze nad samym mechanizmem obsługi stosu TCP. Czy aplikacja ma dostawać cały złożony do kupy pakiet danych TCP, czy sama ma zajmować się defragmentacją. Komplikowałoby to aplikacje korzystające ze stosu ale za to można by zaoszczędzić RAM.

    Jeszcze jedną ważną sprawą jest to jak dużą porcje danych można wysłać. Jeśli aplikacja sama musiałaby się o to troszczyć to pewnie byłoby to bardzo dużo. Tzn odczytuje sobie dane z EEPROM i wysyłam czekając na ACK. retransmisją i wysyłaniem kolejnych partów zajęła by się procedura aplikacji.
    Natomiast, w przypadku automatyzacji najlepszym wyjściem byłby bufor w SRAM. Na przykład 10 elementów 3000B każdy. Aplikacja kopiowałaby tam dane i wysyłała żądanie o wysłanie tych danych. Ograniczenie to te nieszczęsne 3000B (pamięć to tylko 32kB :D ).

    Czy da się to jeszcze jakoś inaczej rozwiązać? Mi aktualnie nic więcej nie przychodzi do głowy.
  • #6 6946424
    mirekk36
    Poziom 42  
    Posty: 9195
    Pomógł: 964
    Ocena: 2289
    oo hoho - tutaj to się dopiero dzieje - żonglujecie stosami, że hej - najbardziej chyba BoskiDialer ;)

    ale do rzeczy - pytanko do damiano713 -> dlaczego taktujesz procka zegarkiem 12,5MHz pobieranym z CLKOUT ENC ? skoro można taktować procek zewnętrznym kwarcem nawet 20MHz ? wtedy wszystkie obliczenia sum kontrolnych itp działałyby szybciej. Z czego to wynika u ciebie że akurat tak to rozwiązujesz?
  • #7 6946436
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Cytat:
    oo hoho - tutaj to się dopiero dzieje - żąglujecie stosami, że hej - najbardziej chyba BoskiDialer Wink

    Kiedyś naprowadził człowieka na dobry trop to i są efekty :)

    mirekk36
    Taktuje 25MHz :D
    Tylko proszę nie pisać że to za dużo. Działać, działa. Koniec i kropka. (z wewnętrznego EEPROM nie korzystam)
  • #8 6946450
    mirekk36
    Poziom 42  
    Posty: 9195
    Pomógł: 964
    Ocena: 2289
    damiano713 napisał:
    Moja atmega z zegarem 12,5MHz (pobieranym z karty sieciowej) spędza mnóstwo czasu na generowaniu sumy kontrolnej. Trzeba odciążyć procesor.

    tzn tak napisałeś wcześniej - ale rozumiem, że już zapodałeś kwarca 25MHz przetaktowując co nieco procka ;) - ja tam nie mam nic przeciwko przetaktowywaniu - czasem też tak robię - no może nie aż o tyle ale jak działa? to działa i gut

    a odnośnie "tropu" to ja też jestem teraz na takim etapie super początkującego w tym temacie i na razie chcę odpalić chociaż najprostsze formy komunikacji ;) co powoli wychodzi. Przy okazji możesz mi powiedzieć czy właśnie teraz pisząc swój stosik bazujesz na tym który mi poleciłeś w moim temacie ? (czyli niejako też mnie naprowadzasz na trop ;) )
  • REKLAMA
  • #9 6946465
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Napisałem tak, bo wiem że zaraz mnie pół forum skrytykuje.

    ENC28J60 ma wbudowany preskaler i mogę sobie ustawić częstotliwość programowo.
    Zrobiłem to w taki sposób że częstotliwość jest zmieniana z 3,125MHz na 25MHz automatycznie kiedy nadejdzie jakikolwiek pakiet.

    Cytat:
    pisząc swój stosik bazujesz na tym który mi poleciłeś w moim temacie

    Jak najbardziej. Moim zdaniem to najbardziej udana implementacja na AVR. Tyleże chciałem ją rozszerzyć o RAM i dodać nowe funkcjonalności. :D
  • Pomocny post
    #10 6946468
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Przy TCP przeniesienie retransmisji na aplikację jest utrudnione. Każdy bajt o danym numerze sekwencyjnym przy każdym wysłaniu musi być taki sam, zresztą pakiet przy retransmisji musi mieć ten sam numer sekwencyjny (lub jeśli potwierdzono tylko część pakietu - trochę dalszy). Najprostsze rozwiązanie według mnie to bufor FIFO z trzema wskaźnikami - zapisu, odczytu oraz dzielący. Przy transmisji pakietu (można zawsze wysyłać ACK+PSH dla ograniczenia przypadków) wysyłać część od wskaźnika dzielącego do wskaźnika zapisu (chyba, że mss zezwala na mniej). Przy timeout przesunąć wskaźnik dzielący na pozycję odczytu i wysyłać ponownie - wszystkie dane do retransmisji są w jednym buforze fifo. Odbiór jest ułatwiony, ponieważ jeśli strumień danych dzieli się na bloki o stałym rozmiarze lub mają zapisaną długość gdzieś na początku, to można odbierać tylko pakiety z in_seq równym out_ack (gdzy in_seq < out_ack tylko wysłać ack do retransmisji, gdy in_seq > out_act też wysłać ack, ale odrzucić pakiet gdyż jest potokowany po pakiecie z którego zostało odrzucone kilka bajtów lub przed którym zaginął pakiet) - z odebranego pakietu wybrać tyle bajtów ile potrzeba do zebrania komunikatu, resztę porzucić (out_ack zwiększyć tylko o ilość użytych bajtów). W taki sposób można dowolnie zmniejszyć rozmiar buforu nadawczego, a bufor odbiorczy musi być w stanie odebrać jeden pakiet. Można bufor odbiorczy zrobić w podobny sposób w oparciu o FIFO, ale zaczyna to komplikować rozwiązanie. Domyślam się że selektywne potwierdzenia, skalowanie okna i inne opcje nie będą Ciebie interesować przy tak małych zasobach pamięciowych.
  • #11 6946517
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Cytat:
    Domyślam się że selektywne potwierdzenia, skalowanie okna i inne opcje nie będą Ciebie interesować przy tak małych zasobach pamięciowych.

    Rzecz jasna, nie. Przynajmniej na razie...

    BoskiDialer
    To co mówisz jest bardzo dobrym rozwiązaniem.
    Myślałem jeszcze nad buforem FIFO (10 takich buforów, jeden na każdy slot TCP) który oferuje wysyłanie obsługiwane przez stos TCP. Kiedy mamy wysyłać coś co jest większe od bufora, wtedy zapisujemy to co już mamy i wywołujemy zapis ustawiając flagę jakąś tam, która wskazuje że nie wszystko wysłane. Stos po wysłaniu tego co miał wysłać wywoła aplikacje aby ta uzupełniła dane.

    Odnośnie PSH. Nie zamierzam korzystać z aplikacji real-time. Więc chyba nie muszę używać PSH poza ostatnim fragmentem danych. Tzn wysyłam 10 fragmentowy pakiet HTTP: ACK, ACK, ACK... ACK&PSH
  • REKLAMA
  • Pomocny post
    #12 6946567
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    damiano713: Fakt jest taki, że flagi PSH jak i URG są w większości stosów ignorowane, jednak jeśli już PSH jest używane, to wymusza wysłanie potwierdzenia bezpośrednio do danego pakietu - implementacje TCP jakie widziałem wysyłają jednak potwierdzenie po każdych dwóch pakietach lub po pewnym krótkim czasie (zwykle 100ms, chyba że rtt jest duże) od odebrania ostatniego pakietu, co jednak powoduje że jeśli bufor nadawczy jest mniejszy od mss, to niezależnie od szybkości łącza nie będzie się dało uzyskać prędkości większej niż 10*mss B/s (zawsze będzie wysłany jeden pakiet zawierający cały bufor nadawczy, odbiorca będzie zwlekał z wysłaniem ack, do tego czasu nadawca nie może opróżnić nadajnika). Ustawienie PSH nic nie kosztuje, a może przyspieszyć wysłanie potwierdzenia jeśli wysyłasz po jednym pakiecie. Co do stanu połączenia - flag zbytnio nie trzeba stosować - do fifo oraz trzech wskaźników wystarcza jeden licznik na zmiennej. Możesz co np 10ms przetwarzać stan "slotów" - jeśli wskaźnik dzielący i zapisu się różnią to znaczy że są nowe dane do wysłania - wysłanie. Zmniejszasz też licznik do retransmisji i jeśli się wyzeruje to przesuwasz wskaźnik dzielący na pozycję odczytu aby po kolejnych 10ms od nowa zostały wysłane dane. Przy odebraniu potwierdzenia wpisujesz nową wartość do licznika retransmisji - w zasadzie w ten sposób masz rozwiązane wszystkie podstawowe przypadki transmisji.
  • #13 6946595
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Super! Chyba już dosyć obsiąkłem wiedzą na ten temat :)
    Co do PSH to kierowałem się RFC. Nic nie stoi na przeszkodzie żeby wysyłać ją cały czas.
    Rozwiązanie z licznikiem też trafione w dziesiątkę.

    Pozdrawiam serdecznie!
  • Pomocny post
    #14 6946869
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Teraz mi się przypomniał warunek wysyłania PSH - ustawia się go w pakiecie, który zawiera ostatnią porcję danych z buforu nadawczego (nie licząc tych, które potencjalnie mogą przyjść). Czyli w przypadku gdy mss jest większe od rozmiaru buforu flaga ta praktycznie zawsze będzie ustawiona i opisana sytuacja nie miała by miejsca, dla większego buforu nadawczego pojawią się pakiety bez PSH, ale tylko dla tego, że nie wszystko zostało wysłane, pojawi się następny pakiet a więc host może oczekiwać z wysłaniem potwierdzenia do następnego pakietu. W takim przypadku Twoje 10 pakietów z ack,ack,ack i ack+psh może zawierać więcej psh. Stos zajmuje się transmisją danych i nie powinno się wymagać od aplikacji wskazywania które pakiety należy oznaczać flagą psh. Wysyłając długi strumień może się okazać że aplikacja jeszcze nie wpisała wszystkich danych albo bufor się zapełnił, w takim przypadku musi pojawić się PSH. Ustawianie flagi PSH we wszystkich pakietach może zwiększyć ilość potwierdzeń, ale upraszcza kod - nie trzeba rozpatrywać przypadku czy ustawiać czy nie (z wyjątkiem warunku czy są dane w pakiecie czy nie). Wracając jeszcze do komunikacji pomiędzy stosem a aplikacją - tutaj są dwa rozwiązania, pierwsze pasywne, gdzie stos przekazuje w jakiś sposób sygnał aplikacji aby wskazać że jest wolne miejsce w buforze nadawczym lub rozwiązanie aktywne, gdzie aplikacja sukcesywnie wywołuje funkcję write() na bloku danych do wysłania poczynając od miejsca jeszcze nie wpisanego, stos zwraca liczbę bajtów wpisanych do buforu nadawczego. Czyli aplikacja stara się wypełniać bufor, a stos przyjmuje od aplikacji tyle bajtów ile się mieści w buforze. Podobnie można zrobić przy odczycie - do read() przekazywać blok oraz maksymalną liczbę bajtów do odczytu a stos zwraca liczbę bajtów odczytanych lub 0/-1 (zależnie co wygodniej i jak wygląda sygnalizacja końca połączenia).
  • #15 6946915
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Sprawa z PSH jest jasna.

    Przyszło mi na myśl żeby jeszcze bardziej przyspieszyć przetwarzanie danych.
    Po co kopiować header Ethernet lub ICMP a nawet IP do RAMu; można skorzystać z DMA ENC28J60 i przekopiować dane do bufora nadawczego. Zamienić miejscami adresy MAC w ramce Ethernet, przekopiować dane pakietu ICMP, lub przekopiować dane nagłówka IP i wypełnić tylko to co potrzeba.
    Kod jest juz i tak uzależniony od karty sieciowej ENC, a na zmianę na Realteka się nie zanosi.
  • #16 6946956
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Wczytanie całego pakietu do ciągłego bloku ma wiele korzyści - rozdziela się kod pobierający od przetwarzającego, nie trzeba ciąć pakietu już przy odbieraniu. Inaczej ma się sprawa przy nadawaniu, gdzie nagłówki są doklejane z początku, tutaj można zastosować rozwiązane z tablicą wskaźników które opisałem w temacie "[AVR][C] - wysyłanie danych przez UDP (ProyconAVRLib)" - nic nie stoi na przeszkodzie, aby wskaźnik wskazywał wtedy na blok wewnątrz buforu odbiorczego (np na część danych). Można nawet w całości wykorzystać bufor odbiorczy do zebrania pakietu, wysłania i dopiero po tym uznać go za pusty i gotowy do odebrania kolejnego pakietu.
    -- edit:
    Można też od razu formować nagłówki pakietu we właściwym miejscu co prowadzi do dalszych uproszczeń i wciąż wszystkie operacje są na ciągłym bloku. Z buforu odbiorczego na pakiety można w tym momencie skorzystać gdy nie ma tam żadnego pakietu lub gdy jest formowana odpowiedź na dany pakiet - wtedy nie trzeba nawet przenosić niektórych danych wewnątrz pamięci.
  • #17 6947005
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Cytat:
    Wczytanie całego pakietu do ciągłego bloku ma wiele korzyści - rozdziela się kod pobierający od przetwarzającego

    Zgadzam się w 100%, ale prosty header Ethernet można automatycznie skopiować do bloku nadawczego karty sieciowej. Przy jego pomocy można od razu pozmieniać MAC miejscami. Oczywiście header ten zostanie też skopiowany do RAM'u AVR ale przy wysyłaniu nie będzie trzeba już sobie nim głowy zawracać.
    Zwykle gdy odbieramy pakiet danego typu to zwracamy pakiet tego samego typu. Nie widzę tutaj możliwości żeby odebrać pakiet IP i nadać w odpowiedzi ARP lub ICMP. Także pola eth->type nie trzeba ruszać.
  • #18 6947090
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    damiano713: Często są przypadki że odbierasz pakiet kierowany na broadcast a wysyłasz unicast - musisz wtrącić lokalny adres mac (odebranie zapytania ARP, wysłanie odpowiedzi). W niektórych implementacjach (bardziej zaawansowanych) zdarza się, że po odebraniu pakietu ARP jest wysyłany inny pakiet (kiedy nie był znany adres mac, pakiet był kolejkowany i przy odebraniu adresu mac od razu wysyłane są zaległe pakiety uzupełnione o uzyskany adres), możliwe jest wysyłanie pakietu ICMP w odpowiedzi na pakiet UDP (gdy port nieosiągalny). Korzyści z przesłania 6 bajtów mniej nagle znikają w gąszczu szczególnych przypadków oraz w serii dodatkowych do wysłania bajtów, które rozkażą kontrolerowi przenieść te 14 czy 6 bajtów w inne miejsce.
  • #19 6947176
    damiano713
    Poziom 15  
    Posty: 177
    Pomógł: 12
    Ocena: 299
    Widze, że nie potrzebnie komplikuje sobie życie :P
    Zostane przy optymalizacji CRC.

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy optymalizacji wykorzystania pamięci RAM w mikrokontrolerze Atmega32 z interfejsem sieciowym ENC28J60. Autor ma do dyspozycji 2KB wewnętrznej pamięci RAM, 32KB zewnętrznego SRAM oraz 128kB EEPROM. Problemem jest ograniczona pamięć wewnętrzna, która nie pozwala na przechowywanie pełnych pakietów Ethernet o rozmiarze do 1514 bajtów. Proponowane rozwiązania obejmują przeniesienie sekcji data, bss i sterty do pamięci zewnętrznej oraz stosowanie buforów FIFO z trzema wskaźnikami do zarządzania retransmisją TCP. Dyskutowano także o sposobach obliczania sum kontrolnych (CRC) – czy wykonywać je programowo, czy sprzętowo w ENC28J60, z uwzględnieniem wpływu na szybkość transmisji. Poruszono temat taktowania mikrokontrolera zegarem 25 MHz, uzyskiwanym z preskalera ENC28J60, co przyspiesza operacje sieciowe. Wskazano na korzyści i ograniczenia kopiowania całych pakietów do ciągłych bloków pamięci RAM oraz na możliwość wykorzystania DMA ENC28J60 do bezpośredniego kopiowania danych do bufora nadawczego, co może przyspieszyć przetwarzanie. Omówiono także znaczenie flagi PSH w TCP i jej wpływ na potwierdzenia oraz przepływ danych. Wskazano, że stos TCP powinien zarządzać retransmisją i fragmentacją, a aplikacja może korzystać z buforów o określonej wielkości. Dyskusja podkreśla konieczność kompromisu między złożonością kodu, wykorzystaniem pamięci i wydajnością transmisji w systemach embedded z ograniczonymi zasobami.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA