View
126
Download
4
Category
Preview:
Citation preview
jc/md/lp-01/05 Driver UART en polling : présentation 1
DRIVER UART EN POLLING
Présentation
jc/md/lp-01/05 Driver UART en polling : présentation 2
Objectif du chapitre
• Écrire un driver rudimentaire et l’intégrer dans Windows CE pour prendre connaissance des mécanismes
• Le driver choisi est le gestionnaire d’une liaison série classique dans le monde PC à base de l’UART 16550
• Ce composant présent dans la cible même s’il est utilisé de la façon la plus simple, en polling, nous permettra d’essayer notre driver
jc/md/lp-01/05 Driver UART en polling : présentation 3
Driver en polling
• À écrire avec la plate-forme z_cible_CEPC• Le driver assure l’interface entre le système et le
contrôleur de la liaison série• Côté système il dialogue par des IOCTL, ici
réduits à trois pour– Envoyer un caractère– Tester le status en réception puisque nous
prévoyons une gestion par polling– Recevoir un caractère
• Côté périphérie, le dialogue consiste à lire et à écrire dans les registres du contrôleur
jc/md/lp-01/05 Driver UART en polling : présentation 4
Contrôleur 16550
• Contrôlé par douze registres internes• Registres sélectionnés par une combinaison
– Des adresses A2, A1 et A0– D’un complément fourni par le signal Read/Write– D’un second complément fourni par le bit « DLAB »
poids fort du registre Line Control Register
• Nota : – Nous n’utiliserons pas la FIFO intégrée– Les registres Interrupt Register et Interrupt Status
Register seront présentés dans le prochain chapitre
jc/md/lp-01/05 Driver UART en polling : présentation 5
Adressage des registres du 16550
DLAB A2 A1 A0 R/W Register
0 0 0 0 R Receive Buffer Register
0 0 0 0 W Transmit Buffer Register
0 0 0 1 R/W Interrupt Register
x 0 1 0 R Interrupt Status Register
x 0 1 0 W FIFO Control Register
x 0 1 1 R/W Line Control Register
x 1 0 0 R/W Modem Control Register
x 1 0 1 R/W Line Status Register
x 1 1 0 R/W Modem Status Register
x 1 1 1 R/W Scratch Register
1 0 0 0 R/W Divisor Latch (LSB)
1 0 0 1 R/W Divisor Latch (MSB)
jc/md/lp-01/05 Driver UART en polling : présentation 6
Receive Buffer Register
• Registre de 8 bits qui contient la donnée reçue de la périphérie et à destination du CPU
• Accessible en lecture seule à l’adresse 000, en fonctionnement normal (DLAB = 0)
• Dans le cas d’utilisation des FIFOs, ce registre fournit successivement les données disponibles dans la FIFO de réception
jc/md/lp-01/05 Driver UART en polling : présentation 7
Transmitter Holding Register
• Registre de 8 bits qui contient la donnée reçue du CPU et à destination de la périphérie
• Accessible en écriture seule à l’adresse 000, en fonctionnement normal (DLAB = 0), après l’initialisation du Baud Rate Generator
• Dans le cas d’utilisation des FIFOs, ce registre introduit successivement les données fournies par le CPU dans la FIFO d’émission
jc/md/lp-01/05 Driver UART en polling : présentation 8
FIFO Control Register
• Bit 0 : 1 autorise FIFOs Receiver et Transmitter• Bit 1 : 1 réinitialisation de la FIFO du Receiver• Bit 2 : 1 réinitialisation de la FIFO du Transmitter• Bit 3 : 1 DMA Mode• Bit 4 : réservé• Bit 5 : réservé• Bit 6 : seuil de déclenchement IT FIFO (LSB)• Bit 7 : seuil de déclenchement IT FIFO (MSB
jc/md/lp-01/05 Driver UART en polling : présentation 9
Line Control Register
• Bit 0 : codage nombre de bits de data (LSB)• Bit 1 : codage nombre de bits de data (MSB)• Bit 2 : 0 un bit de stop, 1 deux bits de stop• Bit 3 : 0 pas de parité, 1 parité• Bit 4 : codage et contrôle de la parité• Bit 5 : codage et contrôle de la parité,• Bit 6 : 1 génération d’un break• Bit 7 : DLAB, 1 sélection Divisor Latch Ex : codage nombre de bits 11 → 8 bits de data
jc/md/lp-01/05 Driver UART en polling : présentation 10
MODEM Control Register
• Bit 0 : gère le signal DTR• Bit 1 : gère le signal RTS• Bit 2 : signal OUT1• Bit 3 : signal OUT2 (EI/DI)• Bit 4 : mode Loopback• Bit 5 : 0• Bit 6 : 0• Bit 7 : 0
jc/md/lp-01/05 Driver UART en polling : présentation 11
Registres d’état ou de « status »
• Dans ces registres, la présence d’un bit à 1 indique la présence d’un événement
• Line Status Register– Consacré aux données– Par exemple le bit 0 positionné à 1 indique qu’une
donnée à été reçue, etc.
• MODEM Status Register– Consacré à la gestion d’un MODEM– Par exemple le bit 7 positionné à 1 indique qu’une
fréquence porteuse est détectée, etc.
• Nous n’utiliserons que le Line Status Register
jc/md/lp-01/05 Driver UART en polling : présentation 12
Line Status Register
• Bit 0 : 1 → Receiver Data Ready• Bit 1 : 1 → Overrun• Bit 2 : 1 → Parity Error• Bit 3 : 1 → Framing Error• Bit 4 : 1 → Break Interrupt• Bit 5 : 1 → Transmit Holder Register vide• Bit 6 : 1 → Transmitter vide• Bit 7 : 1 → erreur dans la FIFO de réception
jc/md/lp-01/05 Driver UART en polling : présentation 13
Autres registres
• D’autres registres sont utilisés pour gérer les interruptions. Comme nous utilisons une gestion par interrogation (polling), nous ne les détaillons pas.
• Un Scratch Register sans aucune influence sur le fonctionnement du 16550 est à la disposition des programmeurs
jc/md/lp-01/05 Driver UART en polling : présentation 14
Baud Rate Generator
• La vitesse de transmission est fixée à partir de l’horloge utilisée divisée systématiquement par 16 puis par la valeur des Divisor Latch LS et MS
• Avec un oscillateur à 1,8432 MHz le nombre à placer dans les Divisor Latch LS et MS est :
– 110 bauds 1047– 1200 bauds 96– 9600 bauds 12– 38400 bauds 3
jc/md/lp-01/05 Driver UART en polling : présentation 15
Lecture et écriture des registres
• Windows CE nous propose deux fonctions pour écrire ou lire les registres du 16550
• Dans l’architecture x86, ces registres sont supposés placés dans un espace réservé aux entrées-sorties : le « I/O Space »
• L’ I/O Space est indépendant de l’espace mémoire habituel. Dans cet espace, on parle plutôt d’un port que d’une adresse mémoire.
• La distinction entre les deux espaces est réalisée par le hardware
jc/md/lp-01/05 Driver UART en polling : présentation 16
Lecture d’un port
UCHAR READ_PORT_UCHAR( PUCHAR Port );
Parameters
Port [in] Pointer to the port that must be a mapped memory
range in I/O space.
Return ValuesThis function returns the byte read from the specified port
address.
jc/md/lp-01/05 Driver UART en polling : présentation 17
Écriture dans un port
VOID WRITE_PORT_UCHAR( PUCHAR Port,
UCHAR Value );Parameters
Port
[in] Pointer to the port that must be a mapped memory range in I/O space.
Value
[in] Byte to be written to the port.
Return Values
None.
jc/md/lp-01/05 Driver UART en polling : présentation 18
Mise en œuvre
1. Préparation du driver
2. Préparation de l’application
3. Téléchargement dans la cible
4. Lancement du driver
5. Exécution de l’application
jc/md/lp-01/05 Driver UART en polling : présentation 19
File → New Project or File
Cocher
ValiderNommer
jc/md/lp-01/05 Driver UART en polling : présentation 20
Choix du projet
CocherValider
jc/md/lp-01/05 Driver UART en polling : présentation 21
Projet obtenu
jc/md/lp-01/05 Driver UART en polling : présentation 22
Fichiers créés sous la plate-forme
jc/md/lp-01/05 Driver UART en polling : présentation 23
Fichiers supplémentaires
• Pour un projet de Dll, deux fichiers doivent être ajoutés
• Fichier de définition de module .def pour :– Créer une Dll et lui attribuer un nom – Annoncer aux autres programmes les points
d’entrée du driver
• Fichier d’entête .h dans lequel on prépare des macros utilisables avec le driver pour faciliter l’utilisation des IOCTL
jc/md/lp-01/05 Driver UART en polling : présentation 24
Fichier .def (1)
• Fichier texte• Dans le menu principal de Platform Builder :
→ File
→ New Project or File
• Dans la fenêtre New Project or File→ Onglet Files
→ Choisir Text File
→ Renseigner le nom de fichier
→ Cocher Add to Project puis OK
jc/md/lp-01/05 Driver UART en polling : présentation 25
Fichier .def (2)
Onglet Files
Choisir
Renseigner
Cocher
OK
jc/md/lp-01/05 Driver UART en polling : présentation 26
TTYpoll_DRV.def (1)
LIBRARY TTYpoll_DRV
EXPORTS
TTY_Init
TTY_Open
TTY_IOControl
TTY_Close
TTY_Deinit
jc/md/lp-01/05 Driver UART en polling : présentation 27
TTYpoll_DRV.def (2)
jc/md/lp-01/05 Driver UART en polling : présentation 28
Fichier .h (1)
• Fichier d’entête habituel • Dans le menu principal de Platform Builder :
→ File
→ New Project or File
• Dans la fenêtre New Project or File→ Onglet Files
→ Choisir C/C++ Header File
→ Renseigner le nom de fichier
→ Cocher Add to Project puis OK
jc/md/lp-01/05 Driver UART en polling : présentation 29
Fichier .h (2)
jc/md/lp-01/05 Driver UART en polling : présentation 30
TTYpoll.h (1)
#define IOCTL_PUTC \ CTL_CODE(FILE_DEVICE_UNKNOWN,2048, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GETC \ CTL_CODE(FILE_DEVICE_UNKNOWN,2049, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GET_RX_STATUS \ CTL_CODE(FILE_DEVICE_UNKNOWN,2050, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
jc/md/lp-01/05 Driver UART en polling : présentation 31
TTYpoll.h (2)
jc/md/lp-01/05 Driver UART en polling : présentation 32
TTYpoll_DRV.cpp
• Fichiers d’entêtes• Constantes d’adressage des registres du 16550• Constantes de définition des bits de status• Point d’entrée de la dll• Code des points d’entrée du driver Init, Deinit,
Open, Close et IOControl avec des parties à compléter
• Code des IOCTL PUTC, GETC et GET_RX_STATUS avec des parties à compléter
jc/md/lp-01/05 Driver UART en polling : présentation 33
Driver : fichiers d’entêtes
#include "stdafx.h"
#include <wdm.h>
#include <windev.h>
#include "TTYpoll.h"
jc/md/lp-01/05 Driver UART en polling : présentation 34
Driver : adressage du sérialiseur
#define IoPortBase ((PUCHAR) 0x02F8)//Registres du sérialiseur : offset par rapport à IoPortBase#define comLineControl 3#define comDivisorLow 0#define comDivisorHigh 1#define comFIFOControl 2#define comIntEnable 1#define comModemControl 4#define comLineStatus 5#define comTxBuffer 0#define comRxBuffer 0
jc/md/lp-01/05 Driver UART en polling : présentation 35
Driver : définition des bits de status
//Bits de status du sérialiseur
#define LS_TSR_EMPTY 0x40
#define LS_THR_EMPTY 0x20
#define LS_RX_BREAK 0x10
#define LS_RX_FRAMING_ERR 0x08
#define LS_RX_PARITY_ERR 0x04
#define LS_RX_OVERRRUN 0x02
#define LS_RX_DATA_READY 0x01
#define LS_RX_ERRORS (LS_RX_FRAMING_ERR |
LS_RX_PARITY_ERR | LS_RX_OVERRRUN )
jc/md/lp-01/05 Driver UART en polling : présentation 36
Driver : point d’entrée de la dll
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
jc/md/lp-01/05 Driver UART en polling : présentation 37
Driver : TTY_Init
DWORD TTY_Init(DWORD dwContext)
{
DWORD dwRet = 1;
RETAILMSG(1,(TEXT("SERIAL: TTY_Init\n")));
// Initialisation du sérialiseur 16550
// 9600 bauds, 8 bits, pas de parité, pas d'IT, DTR, RTS
// pas de FIFO
// TODO
return dwRet;
}
jc/md/lp-01/05 Driver UART en polling : présentation 38
Driver : TTY_Deinit
BOOL TTY_Deinit(DWORD hDeviceContext)
{
BOOL bRet = TRUE;
RETAILMSG(1,(TEXT("SERIAL: TTY_Deinit\n")));
return bRet;
}
jc/md/lp-01/05 Driver UART en polling : présentation 39
Driver : TTY_Open
DWORD TTY_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode){ DWORD dwRet = 1; RETAILMSG(1,(TEXT("SERIAL: TTY_Open\n")));
// Vidage du buffer de réception pour éliminer les// caractères résiduels// TODO
return dwRet;}
jc/md/lp-01/05 Driver UART en polling : présentation 40
Driver : TTY_Close
BOOL TTY_Close(DWORD hOpenContext)
{
BOOL bRet = TRUE;
RETAILMSG(1,(TEXT("SERIAL: TTY_Close\n")));
return bRet;
}
jc/md/lp-01/05 Driver UART en polling : présentation 41
Driver : TTY_IOControl (début)
BOOL TTY_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut){
switch(dwCode)
jc/md/lp-01/05 Driver UART en polling : présentation 42
Driver : TTY_IOControl (IOCTL_PUTC)
case IOCTL_PUTC:
// Attente de transmetteur prêt
// TODO
// Envoi du caractère
// TODO
break;
jc/md/lp-01/05 Driver UART en polling : présentation 43
Driver : TTY_IOControl (IOCTL_GETC)
case IOCTL_GETC:
// Lecture du caractère
// TODO
RETAILMSG(1,(TEXT(" TTY caractère lu\n")));
break;
jc/md/lp-01/05 Driver UART en polling : présentation 44
Driver : TTY_IOControl (..._STATUS)
case IOCTL_GET_RX_STATUS:
// Lecture du status
// TODO
break;
jc/md/lp-01/05 Driver UART en polling : présentation 45
Driver : TTY_IOControl (fin)
} // Fin du switch
*pdwActualOut = 1;
return TRUE;
} // Fin IOControl
jc/md/lp-01/05 Driver UART en polling : présentation 46
Compilation du driver
jc/md/lp-01/05 Driver UART en polling : présentation 47
Création de l’image
jc/md/lp-01/05 Driver UART en polling : présentation 48
Application
• Application qui utilise le driver TTYpoll_DRV• Le programme est très simple, il doit :
– Écrire un $ avec IOCTL_ PUTC– Attendre la réception d’un caractère avec
IOCTL_GET_RX_STATUS – Lire le caractère reçu avec IOCTL_GETC– Envoyer l’écho avec IOCTL_PUTC– Boucler jusqu’à la réception du caractère ESCAPE
(0x1B)– Se terminer après la réception de ESCAPE
jc/md/lp-01/05 Driver UART en polling : présentation 49
File → New Project or File
ChoisirNomme
r
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 50
Choix du projet
Choisir
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 51
Projet obtenu
jc/md/lp-01/05 Driver UART en polling : présentation 52
Platform→Settings
ChoisirChoisir
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 53
Ajout de TTYpoll.h au projet (1)
• Ouvrir le répertoire des fichiers du projet TTYpoll_APP
• Faire un clic droit sur le répertoire des fichiers d’entête Header Files
• Dans le menu déroulant, choisir Add Files to Folder
• Sélectionner dans la fenêtre qui s’ouvre le répertoire à visiter
• Sélectionner le fichier à insérer TTYpoll.h• Valider
jc/md/lp-01/05 Driver UART en polling : présentation 54
Ajout de TTYpoll.h au projet (2)
Choix du répertoire
Choix du
fichier
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 55
Projet obtenu
jc/md/lp-01/05 Driver UART en polling : présentation 56
Choix du type d’image
Dérouler
Dérouler
Choisir Choisir
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 57
Schéma d’utilisation du driver
• Pour utiliser notre driver, notre application doit exécuter plusieurs phases :
– Enregistrement du driver dans la registry– Ouverture du driver– Utilisation des IOControl préparées– Fermeture du driver– Suppression du driver de la registry
• Le driver sera géré par un handle que l’application devrait fermer avant de se terminer
jc/md/lp-01/05 Driver UART en polling : présentation 58
Lancement d’un driver (1)
• Lancement (passage dans XXX_Init)HANDLE RegisterDevice( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib, DWORD dwInfo);
• Paramètres lpszType : nom du device (COM,TTY…) dwIndex : numéro du device (2 pour COM2) lpszLib : nom de la dll dwInfo : passage éventuel de paramètres
jc/md/lp-01/05 Driver UART en polling : présentation 59
Lancement d’un driver (2)
• Valeur de retourHandle associé au composant enregistré dans la
registry
• Remarque– En fait, c’est la fonction XXX_Init qui fournit le handle– Ce handle est communiqué aux fonctions
XXX_Open, XXX_Deinit, XXX_PowerUp et XXX_PowerDown
jc/md/lp-01/05 Driver UART en polling : présentation 60
Ouverture du driver
• CreateFile est la fonction à utiliser pour créer ou ouvrir un device ou un port COM. Ici, ce sera sous une forme simplifiée avec les seuls arguments :
– Pointeur sur le nom et numéro du driver (ce pointeur sera obtenu par la macro TEXT)
– Accès autorisés en lecture et en écriture :GENERIC_READ | GENERIC_WRITE
– OPEN_EXISTING paramètre dwCreationDispostion à utiliser dans le cas d’un appel lié à un device
– Les autre paramètres seront 0 ou NULL
jc/md/lp-01/05 Driver UART en polling : présentation 61
CreateFile (1)
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDispostion,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
jc/md/lp-01/05 Driver UART en polling : présentation 62
CreateFile (2)
• Paramètres lpFileName: à fournir (macro TEXT)
dwDesiredAccess: à fournir
dwShareMode: 0
lpSecurityAttributes: NULL
dwCreationDispostion: à fournir
dwFlagsAndAttributes: 0
hTemplateFile: 0
• Valeur de retourHandle ou INVALID_HANDLE_VALUE
jc/md/lp-01/05 Driver UART en polling : présentation 63
Utilisation des IOCTL
• La fonction DeviceIoControl envoie un IOCTL donné en paramètre à un device driver indiqué en paramètre.
• Nombreux paramètres• La valeur de retour indique si l’opération a réussi
ou échoué.
jc/md/lp-01/05 Driver UART en polling : présentation 64
DeviceIoControl (1)
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped);
jc/md/lp-01/05 Driver UART en polling : présentation 65
DeviceIoControl (2)
Paramètres
hDevice: handle sur le device ou le port
dwIoControlCode: IOCTL à exécuter
lpInBuffer: adresse du buffer de données d’entrée
nInBufferSize: longueur du buffer d’entrée
lpOutBuffer: adresse du buffer de données de sortie
nOutBufferSize: longueur du buffer de sortie
lpBytesReturned: pointeur sur la longueur des données effectivement dans le buffer de sortie
lpOverlapped: toujours NULL
jc/md/lp-01/05 Driver UART en polling : présentation 66
DeviceIoControl (3)
Valeur de retour
0 pour un échec, non 0 pour une réussite
Remarque
Le handle à utiliser est celui qui est fourni par la fonction CreateFile.
Les IOCTL sont ceux qui ont été définis par la macro CTL_CODE.
jc/md/lp-01/05 Driver UART en polling : présentation 67
Fermeture du handle du driver
• CloseHandle pour fermer le handle associé au driver
jc/md/lp-01/05 Driver UART en polling : présentation 68
Suppression du driver de la registry
• La fonction DeregisterDevice supprime le driver de la registry
BOOL DeregisterDevice( Handle hDevice );
Parameters
hDevice [in] Handle to a registered device
returned from RegisterDevice
Return Values
TRUE indicates success. FALSE indicates failure.
jc/md/lp-01/05 Driver UART en polling : présentation 69
Fermeture du handle du device
• DerigisterDevice ne ferme pas le handle associé au device d’où :
• Fermeture du handle associé au device par CloseHandle
jc/md/lp-01/05 Driver UART en polling : présentation 70
Application : includes
#include "stdafx.h"
#include "../TTYpoll_DRV/TTYpoll.h"
#include <windev.h>
jc/md/lp-01/05 Driver UART en polling : présentation 71
Application : entrée
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// Déclarations et réservations
// TODO
jc/md/lp-01/05 Driver UART en polling : présentation 72
Application : lancement du driver
// Lancement du driver (RegisterDevice) // TODO
// Test de Handle correct (Handle !=0) // TODO
// si incorrect // message et fin de l’application // TODO // si correct MessageBox(NULL,_T(" Register TTY1 OK"), _T("UartApp"),MB_OK);
jc/md/lp-01/05 Driver UART en polling : présentation 73
Application : ouverture du driver
// Ouverture du driver (CreateFile)
// TODO
// Test de Handle correct (Handle !=0)
// TODO
// si incorrect
// message et fin de l’application
// TODO
// si correct
jc/md/lp-01/05 Driver UART en polling : présentation 74
Application : boucle de réception
// Boucle d'émission et de réception d’un caractèrecarac[0]='$';while(carac[0]!=0x1B) // Attente du caractère escape {
// Envoi d'un caractère // TODO
// Lecture du status et attente de récepteur Ready // TODO // Acquisition d'un caractère
// TODO} // Fin de boucle while
jc/md/lp-01/05 Driver UART en polling : présentation 75
Application : fermetures
// Fermeture du driver
// TODO
// Déchargement du driver
// TODO
return 0;
}
jc/md/lp-01/05 Driver UART en polling : présentation 76
Génération de l’application
jc/md/lp-01/05 Driver UART en polling : présentation 77
Essai de TTYpoll_APP.exe
• Télécharger dans la cible le noyau avec le driver TTYpoll_DRV.dll qui a été inclus lors du Make Image
• Lancement du programme d’application
Target → Run Program
• Sélection de TTYpoll_APP
jc/md/lp-01/05 Driver UART en polling : présentation 78
Essai
jc/md/lp-01/05 Driver UART en polling : présentation 79
Sélection de TTYpoll_APP
Valider
jc/md/lp-01/05 Driver UART en polling : présentation 80
Cible
• On observe un $ sur l’écran, puis l’écho de tous les caractères tapés
• Le programme se termine lorsqu’on tape le caractère ESCAPE
jc/md/lp-01/05 Driver UART en polling : présentation 81
Conclusion
• Nous avons :– Construit un driver simple– Généré une image de système incluant ce driver– Utilisé ce driver dans une application– Téléchargé le système dans la cible– Téléchargé et exécuté l’application dans la cible
• TODO– Saisir une chaîne de caractères
Recommended