//********************************************************************************************************************************************************************************** // Fichier HARDWARE.C // // Contient toutes les fonctions liées à l'interface avec le matériel. // En particulier, permet de s'affranchir de l'utilisation de la bibiliothèque BCM2835... // // Les documents utilisés sont essentiellement : // - http://elinux.org/RPi_Low-level_peripherals très bon article dédié au Raspberry Pi et décrivant bien les différentes versions de RASPI. // - http://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf est la base de la documentation car la VRAIE doc du processeur... //**********************************************************************************************************************************************************************************/ // Includes : #include "main.h" // Prototypes : int gestion_timer(void); void timer(void); int init_timer(void); int init_memory_map(void); // Variables globales : struct Struct_hardware hardware; /********************************************************************************************************************************************************************************** Fonction TIMER Fonction de gestion du signal de timer Linux (programmé pour se déclencher toutes les 10ms) **********************************************************************************************************************************************************************************/ void timer(void) { uint16_t i; hardware.dizaines_ms ++; //-------------------------------------------------- 10 ms -------------------------------------------------- // Capteurs.c : if (capteurs.sequenceur.compteur > 0) capteurs.sequenceur.compteur --; // Circuits.c : if (circuits.sequenceur.compteur > 0) circuits.sequenceur.compteur --; for (i=0; i 0) circuits.circuits[i].sequenceur.compteur --; } // Ecran.c if (ecran.sequenceur.compteur > 0) ecran.sequenceur.compteur --; // Entrees.c : if (entrees.core.sequenceur.compteur > 0) entrees.core.sequenceur.compteur --; if (entrees.gpio.sequenceur.compteur > 0) entrees.gpio.sequenceur.compteur --; if (entrees.level_sensor.sequenceur.compteur > 0) entrees.level_sensor.sequenceur.compteur --; // Events.c : if (events.sequenceur.compteur > 0) events.sequenceur.compteur --; // Gestion_bdd.c : if (bdd.compteur_synchro > 0) bdd.compteur_synchro --; // Systeme.c : if (systeme.sequenceur.compteur > 0) systeme.sequenceur.compteur --; //-------------------------------------------------- 100 ms -------------------------------------------------- if ((hardware.dizaines_ms % 10) == 0) { // Audio.c if (audio.sequenceur.compteur > 0) audio.sequenceur.compteur --; // Batteries.c : if (batteries.sequenceur.compteur > 0) batteries.sequenceur.compteur --; // C_bus.c : if (c_bus.sequenceur.compteur > 0) c_bus.sequenceur.compteur --; if (c_bus.sequenceur.compteur_time_out > 0) c_bus.sequenceur.compteur_time_out --; if (c_bus.protocole_rx.sequenceur.compteur > 0) c_bus.protocole_rx.sequenceur.compteur --; if (c_bus.protocole_rx.sequenceur.compteur_time_out > 0) c_bus.protocole_rx.sequenceur.compteur_time_out --; if (c_bus.protocole_tx.sequenceur.compteur > 0) c_bus.protocole_tx.sequenceur.compteur --; if (c_bus.protocole_tx.sequenceur.compteur_time_out > 0) c_bus.protocole_tx.sequenceur.compteur_time_out --; // Circuits.c : for (i=0; i 0) circuits.circuits[i].compteur_time_out --; } // Events.c : for (i=0; i 0) events.events[i].sequenceur.compteur --; } // Fonctions.c : if (tempo_delai_dixieme_sec > 0) tempo_delai_dixieme_sec --; // Utilisé par la fonction DELAI_DIXIEME_SECONDE. // G_bus.c : if (g_bus.sequenceur.compteur > 0) g_bus.sequenceur.compteur --; if (g_bus.sequenceur.compteur_time_out > 0) g_bus.sequenceur.compteur_time_out --; if (g_bus.protocole_rx.sequenceur.compteur > 0) g_bus.protocole_rx.sequenceur.compteur --; if (g_bus.protocole_rx.sequenceur.compteur_time_out > 0) g_bus.protocole_rx.sequenceur.compteur_time_out --; if (g_bus.protocole_tx.sequenceur.compteur > 0) g_bus.protocole_tx.sequenceur.compteur --; if (g_bus.protocole_tx.sequenceur.compteur_time_out > 0) g_bus.protocole_tx.sequenceur.compteur_time_out --; // Gnss.c : if (gnss.sequenceur.compteur > 0) gnss.sequenceur.compteur --; if (gnss.sequenceur.compteur_time_out > 0) gnss.sequenceur.compteur_time_out --; // Gestion_bdd.c : if (bdd.compteur > 0) bdd.compteur --; if (bdd.compteur_enregistrement_mesures > 0) bdd.compteur_enregistrement_mesures --; // M_bus.c : if (m_bus.sequenceur.compteur > 0) m_bus.sequenceur.compteur --; if (m_bus.sequenceur.compteur_time_out > 0) m_bus.sequenceur.compteur_time_out --; if (m_bus.protocole_rx.sequenceur.compteur > 0) m_bus.protocole_rx.sequenceur.compteur --; if (m_bus.protocole_rx.sequenceur.compteur_time_out > 0) m_bus.protocole_rx.sequenceur.compteur_time_out --; if (m_bus.protocole_tx.sequenceur.compteur > 0) m_bus.protocole_tx.sequenceur.compteur --; if (m_bus.protocole_tx.sequenceur.compteur_time_out > 0) m_bus.protocole_tx.sequenceur.compteur_time_out --; // Modem.c : if (modem.sequenceur.compteur > 0) modem.sequenceur.compteur --; if (modem.sequenceur.compteur_time_out > 0) modem.sequenceur.compteur_time_out --; // Nmea.c : if (nmea.sequenceur.compteur > 0) nmea.sequenceur.compteur --; // Reseaux.c if (reseaux.sequenceur.compteur > 0) reseaux.sequenceur.compteur --; if (reseaux.compteur_check_adresses_ip > 0) reseaux.compteur_check_adresses_ip --; // Reservoirs.c : if (reservoirs.sequenceur.compteur > 0) reservoirs.sequenceur.compteur --; // Systeme.c : if (chargement_code.sequenceur.compteur > 0) chargement_code.sequenceur.compteur --; if (chargement_code.sequenceur.compteur_time_out > 0) chargement_code.sequenceur.compteur_time_out --; if (systeme.faucheuse.compteur > 0) systeme.faucheuse.compteur --; if (systeme.sequenceur.compteur_time_out > 0) systeme.sequenceur.compteur_time_out --; // Usb.c if (usb.sequenceur.compteur > 0) usb.sequenceur.compteur --; } //-------------------------------------------------- 1000 ms = 1s -------------------------------------------------- if (hardware.dizaines_ms >= 100) { // affichage_debug(__FILE__, __LINE__, "Timer: 1 seconde", TYPE_MESSAGE_DEBUG_WARNING); hardware.dizaines_ms = 0; // RAZ du compteur toutes les 100 boucles (1000 ms) // Batteries.c : for (i=0; i 0) batteries.batteries[i].sequenceur.compteur --; } for (i=0; i 0) systeme.modules_config[i].courant_maxi_compteur --; } // Events.c : if (events.sequenceur.compteur_time_out > 0) events.sequenceur.compteur_time_out --; // Reseaux.c : if (reseaux.compteur_connexion_ship2net > 0) reseaux.compteur_connexion_ship2net --; if (reseaux.compteur_scan_sta > 0) reseaux.compteur_scan_sta --; if (reseaux.compteur_check_webgl > 0) reseaux.compteur_check_webgl --; // Systeme.c : if (systeme.compteur_check_new_download > 0) systeme.compteur_check_new_download --; if (systeme.compteur_sauvegarde_bdd > 0) systeme.compteur_sauvegarde_bdd --; } } /********************************************************************************************************************************************************************************** Fonction INIT_TIMER Initialise le Timer Linux **********************************************************************************************************************************************************************************/ int init_timer(void) { struct itimerval valeur_timer; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; // Init des variables globales : hardware.dizaines_ms = 0; // Mise en place du handler de signal vers la fonction TIMER() : if (signal(SIGALRM, (void (*)(int)) timer) == SIG_ERR) { sprintf(tmp, "Mise en place du handler de timer impossible..."); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); return(-1); } // Calcul des paramètres de chargement du timer : if ((BASE_TEMPS_TIMER/1000) > 0) { valeur_timer.it_value.tv_sec = BASE_TEMPS_TIMER / 1000; valeur_timer.it_value.tv_usec = (BASE_TEMPS_TIMER % 1000) * 1000; } else { valeur_timer.it_value.tv_sec = 0; valeur_timer.it_value.tv_usec = (BASE_TEMPS_TIMER * 1000); } valeur_timer.it_interval = valeur_timer.it_value; // Chargement et lancement du timer : if (setitimer(ITIMER_REAL, &valeur_timer, NULL) == -1) { sprintf(tmp, "\tLancement du timer impossible..."); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); return(-1); } else { sprintf(tmp, "Lancement du timer Linux (période = %i ms)\t\t\t\t\t: OK", BASE_TEMPS_TIMER); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK); } return (0); } /********************************************************************************************************************************************************************************** Fonction INIT_MEMORY_MAP Créée une nouvelle projection dans l'espace d'adressage virtuel. Utilise la fonction MMAP de Linux. **********************************************************************************************************************************************************************************/ int init_memory_map() { int mem_fd; off_t offset; void *ptr_map; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //------------------------------------ // Initialisation dépendant de la génération de ShipBase : if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) { offset = BCM2837_ADRESSE_BASE_PERIPH + CM3P_OFFSET_GPIO_BASE; hardware.offset_gpio_out_set_0 = CM3P_OFFSET_GPIO_OUT_SET_0; hardware.offset_gpio_out_set_1 = CM3P_OFFSET_GPIO_OUT_SET_1; hardware.offset_gpio_out_clear_0 = CM3P_OFFSET_GPIO_OUT_CLEAR_0; hardware.offset_gpio_out_clear_1 = CM3P_OFFSET_GPIO_OUT_CLEAR_1; hardware.offset_gpio_pin_level_0 = CM3P_OFFSET_GPIO_PIN_LEVEL_0; hardware.offset_gpio_pin_level_1 = CM3P_OFFSET_GPIO_PIN_LEVEL_1; } else { offset = BCM2711_ADRESSE_BASE_PERIPH + CM4_OFFSET_GPIO_BASE; hardware.offset_gpio_out_set_0 = CM4_OFFSET_GPIO_OUT_SET_0; hardware.offset_gpio_out_set_1 = CM4_OFFSET_GPIO_OUT_SET_1; hardware.offset_gpio_out_clear_0 = CM4_OFFSET_GPIO_OUT_CLEAR_0; hardware.offset_gpio_out_clear_1 = CM4_OFFSET_GPIO_OUT_CLEAR_1; hardware.offset_gpio_pin_level_0 = CM4_OFFSET_GPIO_PIN_LEVEL_0; hardware.offset_gpio_pin_level_1 = CM4_OFFSET_GPIO_PIN_LEVEL_1; } // Ouverture du fichier /dev/mem : if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { sprintf(tmp, "Ouverture de [/dev/mem] impossible..."); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); return (-1); } else { // sprintf(tmp, "Ouverture de [/dev/mem] \t\t\t\t: OK"); // affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK); } // **************************************************************************************************************** // mmap du GPIO : ptr_map = mmap( NULL, // Any adddress in our space will do (indique l'endroit où est stocké le mapping...) BLOCK_SIZE, // Map length PROT_READ|PROT_WRITE, // Enable reading & writting to mapped memory MAP_SHARED, // Shared with other processes mem_fd, // File to map offset // Offset to GPIO peripheral ); if (ptr_map == MAP_FAILED) { sprintf(tmp, "Erreur 'mmap' pour création de l'espace GPIO. Erreur : %p", ptr_map); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); return(-1); } else { sprintf(tmp, "Initialisation de 'mmap' pour création de l'espace GPIO\t\t\t: OK"); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK); } // Toujours utiliser un pointeur VOLATILE (permet de limiter l'optimisation du compilateur et de forcer TOUS les accès au matériel) hardware.gpio_base = (volatile uint32_t *)ptr_map; // **************************************************************************************************************** // Fermeture du fichier /dev/mem : close(mem_fd); //No need to keep mem_fd open after mmap return 0; }