drivery w C

Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:293
1

Witam
Pracuję jako programista systemów embedded.
Chciałbym dowiedzieć się gdzie mogę znaleźć listing drivera z jądra linuksa powiedzmy do RS232 napisanego w języku C ?
Czy w ogóle drivery jądra linuksowego są oparte o język C ?

Azarien
Przed znakiem zapytania nie stawia się spacji.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
1

Źródła Linuksa są tu: https://github.com/torvalds/linux
Napisany jest w C i szczątkowo w asemblerze.

Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:293
1

OK, super, dziękuję Ci.
Programuję AVR'y.
Chciałbym jeszcze prosić o odpowiedź na poniższe:

  • załóżmy że chciałbym stworzyć takie oto makro o nazwie LED_ON które by zapalało diodę (czyt. ustawiało pin portu A , powiedzmy PA5 na jeden).
    Wiem że mogę to po prostu osiągnąć wpisując :
Kopiuj
#define LED_ON PORTA|=(1<<PA5)

z tym że ja wolałbym mieć strukturę z polami bitowymi gdzie każde pole bitowe odnosiłoby się do konkretnego bitu pamięci odpowiadającemu pinowi tego portu.
Wówczas mógłbym np. stworzyć makra tego typu:

Kopiuj
#define LED struktura.bit_1
#define ON 1
#define OFF 0

a wywołanie robiłbym wówczas tak:

Kopiuj
LED=ON;
LED=OFF;

Pytanie brzmi : czy mógłbym osiągnąć takie coś bez modyfikowania skryptu linkera? Jasne że modyfikując skrypt linkera można sprawić że dana zmienna typu strukturalnego będzie umieszczona w pamięci dokładnie w tym miejscu co dane odpowiadające PORT'owi. Jeśli tylko taka zmienna i pola bitowe tego typu strukturalnego byłyby dodatkowo opatrzone volatile'm to na pewno uzyskałbym taką właśnie funkcjonalność że przy odwołaniu się do pól tej struktury odwoływałbym się już do konkretnego bitu w pamięci RAM.

Troszkę skomplikowałem moje zapytanie za co przepraszam, powinno być:
Czy istnieje jakiś prosty sposób aby zadeklarować strukturę i umieścić ją pod konkretnym adresem w pamięci bez modyfikowania i ingerencji w skrypt linkera ?

mwl4
  • Rejestracja:około 12 lat
  • Ostatnio:25 dni
  • Lokalizacja:Wrocław
  • Postów:399
2

Mógłbyś zrobić strukturę, wyciągnąć referencje z PORTA, scastować i się odwoływać:

Kopiuj
typedef struct
{
 unsigned bit_0 : 1;
 unsigned bit_1 : 1;
 unsigned bit_2 : 1;
 unsigned bit_3 : 1;
 // ...
} bitset_t;

#define LED ((bitset_t *)(&PORTA))->bit_0
#define ON 1
#define OFF 0

void foo(void)
{
 LED = ON;
}

http://ideone.com/T6STUa


Asm/C/C++
edytowany 3x, ostatnio: mwl4
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:293
0

Dziękuję za podpowiedź.
Super pomyślane.
Chciałbym tylko jeszcze dopytać teoretycznie jak to jest że takie coś jest w ogóle możliwe...
Trochę łopatologicznie jeśli można prosić:

  1. Każemy kompilatorowi potraktować (cast) referencję PORTu jako wskaźnik na typ strukturalny.
  2. Następnie strzałką wyciągamy spod tego wskazania bit o numerze powiedzmy jeden.

I pytanie: Czy to jest to samo co by powiedzieć kompilatorowi w skrócie : Weź potraktuj PORTA w taki sposób jak traktowana jest struktura takiego a takiego typu?

To naprawdę całkiem logiczne i przejrzyste.
Nawet nie wiedziałem że tak można robić.

Czy ktoś próbował użyć takiego zapisu w programie analizując go narzędziami weryfikacji kodu np. Q-AC ?
Nie czepiają się takiego stylu ?

mwl4
  • Rejestracja:około 12 lat
  • Ostatnio:25 dni
  • Lokalizacja:Wrocław
  • Postów:399
2
Adamos19 napisał(a):

Weź potraktuj PORTA w taki sposób jak traktowana jest struktura takiego a takiego typu?

Załóżmy, że PORTA to unsigned. &PORTA da nam unsigned *, i ten wskaźnik sobie castujemy do bitset_t *. Zobaczmy, że adres PORTA i adres pierwszego pola w strukturze jest taki sam:

Kopiuj
 
#include <stdio.h>

typedef struct
{
	unsigned a;
	unsigned b;
} foo;

int main(void) {
	unsigned local_a = 0;
	foo *f = (foo *)(&local_a);
	printf("address local_a: %X, f->a: %X, f->b: %X\n", &local_a, &f->a, &f->b);
	f->a = 2; // ok
	// f->b = 4; // !!! nadpisanie pamięci, która nie należy do nas
	printf("local_a = %u\n", local_a);
	return 0;
}

http://ideone.com/Jx2tCF

W teorii standard C zakłada ciągłość pamięci, więc powinno wszystko działać.

Problem może nastąpić, kiedy odwołamy się do adresu poza zmienną PORTA. Wtedy nadpiszemy pamięć innej zmiennej lub stosu (na stosie są odłożone np. adresy powrotu z funkcji, więc nadpisanie może się skończyć crashem programu).

Generalnie aby nie stwarzać zagrożenia, radziłbym zrobić coś takiego:

Kopiuj
#include <stdio.h>

unsigned PORTA = 0;

#define OUTPUT PORTA
#define BIT(n) (1 << n)
#define LED(op) (OUTPUT op BIT(4))
#define ON |=
#define OFF &=~

int main(void) {
	printf("PORTA = %u\n", PORTA);
	LED(ON);
	printf("PORTA = %u\n", PORTA);
	LED(OFF);
	printf("PORTA = %u\n", PORTA);
	return 0;
}

http://ideone.com/qytrbg

Ewentualnie, jeśli już bardzo byś chciał to mieć oparte na strukturze, to wtedy radziłbym zastosować jakiegoś compile-time asserta, np.:

Kopiuj
#define STATIC_ASSERT(COND) typedef char static_assertion_##__LINE__[(COND) ? 1 : -1]
#define ENSURE_SIZE(structure, size) STATIC_ASSERT(sizeof(structure) == size)
Kopiuj
 
typedef struct
{
	unsigned a;
} foo;
ENSURE_SIZE(foo, sizeof(unsigned)); // ok

http://ideone.com/Czm68c

Kopiuj
typedef struct
{
	unsigned a : 1;
	unsigned b : 1;
} foo;
ENSURE_SIZE(foo, sizeof(unsigned)); // ok

http://ideone.com/4SxD9F
http://ideone.com/jceZ7h <- 32 bity
http://ideone.com/VsjbQ9 <- 33 bity

Kopiuj
typedef struct
{
	unsigned a;
	unsigned b;
} foo;
ENSURE_SIZE(foo, sizeof(unsigned)); // błąd kompilacji

http://ideone.com/ZyCoB5


Asm/C/C++
edytowany 6x, ostatnio: mwl4
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:293
1

Dziękuję ponownie.
Co do rzutowania wskaźnika to mamy jasność. Wskaźnik możemy castować na wskaźnik danego typu strukturalnego i później odwoływać się do pól takiej struktury tym samym odwołując się de facto do konkretnych bitów w pamięci. Należy przy tym pamiętać aby ten typ strukturalny był tak utworzony aby nie było możliwości nadpisania innych struktur pamięci ponieważ bardzo łatwo tutaj popełnić błąd co zresztą super pokazałeś na przykładzie.

Jednakże problem sprawia mi to co napisałeś od tego momentu :

Ewentualnie, jeśli już bardzo byś chciał to mieć oparte na strukturze, to wtedy radziłbym zastosować jakiegoś compile-time asserta...

Cóż to takiego za cudo ten "compile-assert"?

mwl4
Nieco niżej pokazałem przykład. Są to pewnego rodzaju testy przy kompilowaniu. Jeśli się nie powiodą - będzie błąd kompilacji. Więc można na przykład się upewnić o rozmiarze struktury już przy kompilacji.
Adamos19
Pięknie ładnie. Serdecznie dziękuję za wyjaśnienia. Życzę miłego i przyjemnego wieczoru!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.