373 lines
14 KiB
C
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.
|
|
}
|
|
}
|
|
|