Files
shipheart-appli/sources/sorties.c
T

373 lines
14 KiB
C

//**********************************************************************************************************************************************************************************
// Fichier SORTIES.C
//
// Contient toutes les fonctions liées à l'écriture sur les sorties, quel que soit leur type
//**********************************************************************************************************************************************************************************/
// Includes :
#include "main.h"
// Prototypes :
void ecriture_sortie(uint8_t type, uint8_t module, uint8_t no, uint8_t valeur);
void ecriture_sortie_gpio(int16_t no, int8_t valeur, int8_t logique);
int8_t init_sorties(void);
int8_t init_sorties_gpio(void);
int16_t sortie_no(uint8_t type, uint8_t module, uint8_t no);
// Variables globales :
struct Struct_sorties sorties;
struct gpiod_chip *gpiod_chip0_sorties; // Nécessaire pour CM5
struct gpiod_line_request *gpiod_sorties_request; // Nécessaire pour CM5
/**********************************************************************************************************************************************************************************
Fonction ECRITURE_SORTIE
Fonction utilisée pour mettre à jour l'état d'une sortie, quel que soit sont type.
Reçoit en paramètre : le Type de sortie, le module comportant la sortie, le n° sur le module et la valeur à appliquer
**********************************************************************************************************************************************************************************/
void ecriture_sortie(uint8_t type, uint8_t module, uint8_t no, uint8_t valeur)
{
int x;
x = sortie_no(type, module, no);
if (x != -1)
{
switch(type)
{
case TYPE_SORTIE_GPIO :
{
sorties.gpio.sorties[x].valeur = valeur;
ecriture_sortie_gpio(sorties.gpio.sorties[x].no, sorties.gpio.sorties[x].valeur, sorties.gpio.sorties[x].logique);
break;
}
}
}
}
/**********************************************************************************************************************************************************************************
Fonction INIT_SORTIES
Intitialisation des entrées, quel que soit leur type.
**********************************************************************************************************************************************************************************/
int8_t init_sorties(void)
{
// Init des sorties GPIO :
if (init_sorties_gpio() == -1) return(-1);
return(0);
}
/**********************************************************************************************************************************************************************************
Fonction INIT_SORTIES_GPIO
Configure les I/O du GPIO
Renvoi -1 en cas d'erreur lors de l'initialisation.
**********************************************************************************************************************************************************************************/
int8_t init_sorties_gpio(void)
{
int flag_erreur = 0;
uint8_t groupe;
uint8_t position_groupe;
uint8_t i;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
i = 0;
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
{
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_MOD_WKUP;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_USB_AVANT_PWR_EN;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_TO_UC;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_Pdown_HDMI_CMD_N;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_WIFI_CHIP_EN;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_PWKEY_MOD;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_AUDIO_SD;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_TEST_TP1140;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_TEST_TP1141;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_TEST_TP1142;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_LCD_EN_VGx;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM3P_DO_LCD_EN_VDD;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
}
else // V2 et V3 :
{
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_TO_UC;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_USB_ARRIERE_PWR_EN;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_GNSS_EXTINT;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_AUDIO_SD;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_GNSS_SAFEBOOT;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_Pdown_HDMI_CMD_N;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_USB_AVANT_PWR_EN;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_EN_LCD_VGx;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
sorties.gpio.sorties[i].flag_validite = TRUE;
sorties.gpio.sorties[i].no = CM4_DO_EN_LCD_VDD;
sorties.gpio.sorties[i].pull = NO_PUP_PDN;
sorties.gpio.sorties[i].logique = 1;
i ++;
}
//====================================================================================================
// V3 (CM5) : réservation groupée des lignes GPIO via libgpiod, en sortie,
// avec valeur initiale LOW (comportement identique à l'ancienne méthode mmap au premier boot).
//====================================================================================================
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3)
{
unsigned int offsets[MAX_NOMBRE_SORTIES_GPIO];
uint8_t nb_lignes = 0;
struct gpiod_line_settings *settings = gpiod_line_settings_new();
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_INACTIVE); // Etat bas par défaut, cf discussion
struct gpiod_line_config *line_cfg = gpiod_line_config_new();
struct gpiod_request_config *req_cfg = gpiod_request_config_new();
gpiod_request_config_set_consumer(req_cfg, "shipheart_sorties");
gpiod_chip0_sorties = gpiod_chip_open("/dev/gpiochip0");
if (gpiod_chip0_sorties == NULL)
{
sprintf(tmp, "Ouverture de /dev/gpiochip0 (sorties) impossible...");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
for (i=0; i<MAX_NOMBRE_SORTIES_GPIO; i++)
{
if (!sorties.gpio.sorties[i].flag_validite) continue;
offsets[nb_lignes] = sorties.gpio.sorties[i].no;
gpiod_line_config_add_line_settings(line_cfg, &offsets[nb_lignes], 1, settings);
nb_lignes++;
sprintf(tmp, "GPIO #%2i configurée en SORTIE (via libgpiod)", sorties.gpio.sorties[i].no);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
gpiod_sorties_request = gpiod_chip_request_lines(gpiod_chip0_sorties, req_cfg, line_cfg);
gpiod_request_config_free(req_cfg);
gpiod_line_config_free(line_cfg);
gpiod_line_settings_free(settings);
if (gpiod_sorties_request == NULL)
{
sprintf(tmp, "Réservation des lignes GPIO de sortie impossible...");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
return(0); // On sort ici : la boucle V1/V2 ci-dessous ne doit pas s'exécuter pour V3
}
//====================================================================================================
// V1 et V2 :
//====================================================================================================
for (i=0; i<MAX_NOMBRE_SORTIES_GPIO; i++)
{
if (!sorties.gpio.sorties[i].flag_validite) continue;
groupe = sorties.gpio.sorties[i].no / 10;
position_groupe = sorties.gpio.sorties[i].no % 10;
// Configuration en Sortie de l'E/S GPIO :
*(hardware.gpio_base + groupe) &= ~(7<<(position_groupe*3)); // Mets d'abord à 0 les 3 bits correspondant à N0
*(hardware.gpio_base + groupe) |= (1<<(position_groupe*3)); // Mets ensuite à 1 le bit correspondant à N0 en sortie (sortie = 001)
sprintf(tmp, "GPIO #%2i configurée en SORTIE", sorties.gpio.sorties[i].no);
// Configuration des résitances de pull-up/down :
// Les fonctions de pull-up/down ne sont pas codées pour les sorties car non utilisées.
// Si besoin, reprendre le code équivalent dans 'entrees.c'
// Affichage du message de débug :
if (flag_erreur == 0) affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
else affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Arrêt de l'intitialisation si erreur :
if (flag_erreur != 0) return(-1);
}
return(0);
}
/**********************************************************************************************************************************************************************************
Fonction SORTIE_NO
Reçoit en paramètre :
- le type de sortie concerné
- le module (adresse_k_bus) sur lequel la sortie se situe
- Le n° de la sortie sur le module
Retourne :
- le numéro de sortie correspondant (ou -1 si aucune sortie valide ne correspond). La numérotation allant de 0 à MAX_SORTIES_xxxx (fonction du type).
**********************************************************************************************************************************************************************************/
int16_t sortie_no(uint8_t type, uint8_t module, uint8_t no)
{
int16_t i;
switch(type)
{
case TYPE_SORTIE_GPIO:
{
for (i=0; i<MAX_NOMBRE_SORTIES_GPIO; i++)
{
if ((sorties.gpio.sorties[i].flag_validite) &&
(sorties.gpio.sorties[i].no == no)) return(i);
}
break;
}
default : return(-1);
}
return (-1); // Si on est arrivé au bout de la boucle, on renvoi le code de 'non trouvé'.
}
/**********************************************************************************************************************************************************************************
Fonction ECRITURE_SORTIE_GPIO
Fonction utilisée pour écrire 'VALEUR' (0 ou 1) dans les registres du BCM283x en fonction du N° de sortie GPIO (0 à 53) et de la logique (-1 = logique inversée)
Le fonctionnemengt a été adapté pour les CM5 pour lesquels les E/S GPIO ne sont plus accessiobles via des registres du SOC
NB : cette fonction ne doit PAS être appelée en direct car elle ne met pas à jour l'état de la variable 'sorties.gpio.sorties[].etat' donc il y aura conflit avec le gestionnaire synchrone...!
**********************************************************************************************************************************************************************************/
void ecriture_sortie_gpio(int16_t no, int8_t valeur, int8_t logique)
{
int8_t on;
// Cas d'une sortie à logique inversée :
if (logique == -1) on = OFF;
else on = ON;
//--------------------------------------------------------
// V3 :
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3)
{
enum gpiod_line_value val = (valeur == on) ? GPIOD_LINE_VALUE_ACTIVE : GPIOD_LINE_VALUE_INACTIVE;
gpiod_line_request_set_value(gpiod_sorties_request, no, val);
return;
}
//--------------------------------------------------------
// V1 & V2 :
// Mise à jour des registres du BCM283x :
if (no < 32) // Sorties 0 à 31 :
{
if (valeur == on) (*(hardware.gpio_base + hardware.offset_gpio_out_set_0)) = (1 << (no)); // Mise à 1 dans le registre de SET.
else (*(hardware.gpio_base + hardware.offset_gpio_out_clear_0)) = (1 << (no)); // Mise à 1 dans le registre de RESET.
}
else // Sorties 32 à 53 :
{
if (valeur == on) (*(hardware.gpio_base + hardware.offset_gpio_out_set_1)) = (1 << (no - 32)); // Mise à 1 dans le registre de SET.
else (*(hardware.gpio_base + hardware.offset_gpio_out_clear_1)) = (1 << (no - 32)); // Mise à 1 dans le registre de RESET.
}
}