L’objectif ici est de compiler et d’exécuter un programme permettant de lire une tension sur des pins analogiques. Deux programmes, en fait, l’un côté PRU (Programmable Real-time Unit) et l’autre côte CPU ARM. Finalement, j’ai opté pour les exemples fournis par Texas Instruments, qui est le constructeur du « cœur » (SoC AM3358/9) de la BBB. Au départ, je ne saisissais pas bien comment lancer les programmes fournis par TI, ni l’intérêt exact du SDK. J’ai en plus installé leur « Code Composer Studio » sur ma bécane (CCS), qui prend moultes Giga et est bien complexe. Je vais probablement le désinstaller.
Grâce au projet BeagleScope, dont je parle dans mon précédant post, en étudiant le fichier deplay.sh, j’ai compris comment lancer un programme (dans le firmware) sur l’un des deux micro-contrôleurs (les fameux PRUs).
Le premier exemple, dans le post précédent, consistait à faire clignoter une LED à partir d’un pin numérique configuré en « output ». Maintenant, nous allons construire et exécuter un projet, nommé « PRU_ADC_onChip » qui a pour objectif de lire des valeurs sur des pins analogiques (ADC = Analog to Digital Converter) et de les convertir en Volts en fonction d’une tension de référence. Les ADC de la BBB ont 12 bits de résolution et prennent donc des valeurs entre 0 et 4096-1 (4096 = 2 puissance 12). La tension de référence pour les convertisseurs est de 1.8 V, au lieu des 3.3 V pour pour les pins numériques. ATTENTION, ne pas mettre une tension supérieure à 1.8 V au risque d’endommager laBeagleBone! La tension de référence est fournie sur le pin P9_32 (VDD_ADC) et une terre analogique sur le pin P9_34 (GROUNDA_ADC). Vraiment, faite attention de ne pas mettre une tension supérieure à 1.8 V dans les entrées analogiques, please!!!
Les pins d’entrée analogique, sur le header P9, sont numérotées de AIN0 à AIN6 (7 entrées), pins 33 et 35 à 40, le pin 34 étant la terre et le pin 32 étant la référence à 1.8 V. Les entrées analogiques sont surlignées en vert dans la figure ci-dessous:
Une vidéo illustrant le « projet », dans ses grandes lignes, est disponible ici : How to Use the PRU to Control a Peripheral: PRU_ADC_onChip on Sitara 335x using Beaglebone Black. C’est une bonne idée de la regarder cette vidéo, elle ne dure que 10 minutes (si l’Anglais ne vous rebute pas).
Les explications dans ce post sont certainement transposables à d’autres BeagleBones (Green, Blue), moyennant quelques adaptations.
Note: la résolution est ici de 12 bits, contre 10 bits pour l’Arduino Uno. La résolution standard d’un fichier audio est de 16 bits (signé).
Du coup, cela signifie que le pas de quantification est de 1.8 V divisé par (2 puissance 12, moins 1), soit 0.440 mV environ!
Résumé avec la vidéo TI (traduction) :
Dans certaines situations, il est plus logique de contrôler un périphérique avec un processeur déterministe dédié plutôt qu’avec un cœur ARM à usage général dans un processeur TI. Les applications vont d’un système de surveillance dédié où la charge de traitement peut être déchargée de l’ARM à un environnement en temps réel où le stimulus nécessite une réponse du processeur dans un laps de temps connu. Cette vidéo fournit un exemple d’utilisation du noyau d’unité programmable en temps réel (PRU) pour contrôler un périphérique sur n’importe quel processeur TI avec un PRU-ICSS ou PRU_ICSSG. Dans ce cas, pour contrôler le convertisseur analogique-numérique (ADC) sur le processeur Sitara AM335x à l’aide du BeagleBone Black.
Sur le projet PRU_ADC_onChip :
Il s’agit d’un projet de référence pour l’utilisation du PRU-ICSS pour contrôler un périphérique ADC sur l’AM335x. Le but de ce projet est de fournir un modèle pour contrôler un périphérique sur puce à l’aide du PRU. Il démontre également une application de RPMsg pour la communication ARM-PRU.
Nous allons passer aux choses sérieuses, à savoir la compilation des deux codes, l’un sur la BBB pour le PRU et l’autre sur votre PC sous Linux pour le processeur ARM de la BBB.
La première étape consiste à modifier le fichier /boot/uEnv.txt, puis rebooter.
Dans ce fichier de configuration, il faut dé-commenter la ligne suivante :
disable_uboot_overlay_adc=1, afin d’empêcher le processeur ARM d’accéder à la conversion analogique numérique ADC, car ce sera la tâche du micro-contrôleur.
Re-booter :
sudo reboot now
La seconde étape: le projet fait partie du pru-software-support-package fourni par Texas Instruments (TI) et téléchargeable ici pru-software-support-package. Il est souhaitable de le télécharger sur votre PC, puis de le copier sur votre BBB :
scp pru-software-support-package-5.6.0.zip debian@beaglebone.home:/home/debian/
Sur les deux ordinateurs (PC et BBB), le décompresser :
unzip pru-software-support-package-5.6.0.zip
Le projet s’appelle PRU_ADC_onChip et se trouve dans le répertoire : pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip.
La troisième étape (1/2) : installation du SDK sur le PC pour la compilation croisée.
On trouve le SDK de TI depuis PROCESSOR-SDK-AM335X, c’est un très gros fichier « ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin » (9.2 Go après installation, sur mon PC) . Une fois téléchargé, il faut l’exécuter pour installer le SDK :
chmod u+x ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin
./ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin


La troisième étape (2/2) : la compilation croisée (cross-compilation)
Il s’agit de compiler le programme depuis le PC (processeur x86) pour le processeur ARM de la BeagleBone, sur lequel il sera exécuté.
Le code source est dans le fichier pru_adc_userspace.c, qui se trouve dans le sous répertoire PRU_ADC_onChip/pru_adc_userspace
Attention, celui-ci doit être compilé sur votre PC.
Ce n’est pas indiqué explicitement dans le README.txt, mais c’est nécessaire.
Faire l’export suivant pour le dossier bin du SDK :
export ARM_CCT=/home/benaroya/ti-processor-sdk-linux-am335x-evm-06.01.00.08/linux-devkit/sysroots/x86_64-arago-linux/usr/bin
en remplaçant « /home/benaroya » par votre répertoire racine contenant le SDK
Dans le répertoire PRU_ADC_onChip/pru_adc_userspace, on compile :
make clean
make
Enfin, il ne reste plus qu’à recopier le dossier généré « gen » vers l’exemple sur la BeagleBone
scp -r gen debian@beaglebone.home:/home/debian/pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip/pru_adc_userspace/
La quatrième étape : compilation pour le PRU 0 sur la BBB.
dans PRU_ADC_onChip, compiler pru_adc_firmware.c dans la beaglebone :
export PRU_CGT=/usr/share/ti/cgt-pru
make clean
make
Vous pouvez insérer l’export dans ~/.bashrc, pour ne plus le faire à chaque connexion à la BBB.
La cinquième étape : démarrer le PRU.
Comme indiqué dans le post précédent, il faut mettre le code pour le PRU 0 dans le firmware et lancer le remoteproc0. Il y a une erreur dans le programme fourni par TI parce que pru_adc_userspace.c essayez de lancer automatiquement PRU 1, alors que le programme « pru_adc_firmware.c » est compilé avec des options pour le PRU 0. ça n’a pas fonctionné en l’état chez moi.
Dans pru_adc_firmware.c :
/*
* The PRU-ICSS system events used for RPMsg are defined in the Linux devicetree
* PRU0 uses system event 16 (To ARM) and 17 (From ARM)
* PRU1 uses system event 18 (To ARM) and 19 (From ARM)
*/
#define TO_ARM_HOST 16
#define FROM_ARM_HOST 17
Dans pru_adc_userspace.c :
char firmware[] = "/sys/class/remoteproc/remoteproc1/firmware";
char pruState[] = "/sys/class/remoteproc/remoteproc1/state";
Remplacer remoteproc1 par remoteproc0 ne suffit pas bizarrement.
On revient à nos moutons: renommer et copier le code compilé dans le firmware,
cp PRU_ADC_onChip.out PRU_ADC_onChip-fw
sudo cp PRU_ADC_onChip-fw /lib/firmware/
et démarrer le programme sur le PRU 0
echo 'stop' > /sys/class/remoteproc/remoteproc0/state 2>/dev/null
echo "PRU_ADC_onChip-fw" > /sys/class/remoteproc/remoteproc0/firmware
echo 'start' > /sys/class/remoteproc/remoteproc0/state
Dernière étape : tester
./gen/pru_adc_userspace -c 5
Reading voltage at ADC Channel: 5
Voltage on ADC Channel 5 is 1.7960V
./gen/pru_adc_userspace -c 6
Reading voltage at ADC Channel: 6
Voltage on ADC Channel 6 is 0.9270V
./gen/pru_adc_userspace -c 7
Reading voltage at ADC Channel: 7
Voltage on ADC Channel 7 is 0.0501V
C’est magnifique, car physiquement, le pin AIN4 (canal 5) est rélié à l’analog VDD (1.8 V), le pin AIN5 (canal 6) est « au milieu » (pont résistif de 2k Ohms) et le pin AIN6 (canal 7) est à la masse. Cependant, c’est un peu fluctuant au cours du temps. Apparemment, il y a moyen de moyenner la mesure:
/*
* set the ADC_TSC STEPCONFIG1 register for channel 5
* Mode = 0; SW enabled, one-shot
* Averaging = 0x3; 8 sample average
* SEL_INP_SWC_3_0 = 0x4 = Channel 5
* SEL_INM_SWC_3_0 = 1xxx = VREFN (reduces noise in single ended mode)
* use FIFO0
*/
ADC_TSC.STEPCONFIG1_bit.MODE = 0;
ADC_TSC.STEPCONFIG1_bit.AVERAGING = 3;
ADC_TSC.STEPCONFIG1_bit.SEL_INP_SWC_3_0 = 4;
ADC_TSC.STEPCONFIG1_bit.SEL_INM_SWC_3_0 = 8;
ADC_TSC.STEPCONFIG1_bit.FIFO_SELECT = 0;
Discussion générale :
Nous avons compilé et testé ce projet pour la lecture d’une entrée analogique. Il est composé de deux codes, l’un pour le PRU 0 qui va lire une valeur sur un pin analogique. Cette partie du code est assez lisible. Ensuite, cette valeur (échantillonnée sur 12 bits) est envoyée au micro-processeur ARM. La communication entre PRU et ARM est assurée par le framework RPMsg (Remote Processor Messaging, voir peut-être ici). Ne connaissant pas ce framework, je vais me rencarder sur ce Graal.
Enfin, le second code, compilé sur mon PC , est exécuté sur la BBB par l’ARM. Celui-ci envoie une requête avec le numéro du canal et reçoit en retour la valeur mesurée. Enfin, celle-ci est convertie en Volts et affichée.
Conclusion :
Nous avons abordé, entre autres, le téléchargement du « pru-software-support-package » de Texas Instruments, l’installation du SDK sur le PC, la compilation des deux codes, l’activation du PRU et enfin nous avons fourni de bons résultats de l’exécution du programme sur ARM.
A noter que le PRU lit une seule valeur sur l’ADC (one-shot). Il serait intéressant de lire des valeurs à intervalles réguliers et de les renvoyer à l’ARM. Aussi comprendre la communication entre PRU et ARM avec le RPMsg.
Et Voilà !!!






