3. Driver
● Driver é uma abstração em software do
hardware da placa, suas funcionalidades,
opções e modos de funcionamento.
● É dependente do processador,dos
componentes conectados e das ligações
entre eles.
4. Criação de um driver
● Para a criação de um driver basta
encapsular estas funções num conjunto
organizado e de fácil acesso.
● Headers e defines
● A mudança do driver não deve gerar
nenhuma alteração no código da aplicação.
● A criação de um driver deve se concentrar
na função e não nos recursos do
dispositivo.
7. Controladora de Drivers
● É utilizada como uma interface entre o
kernel e os drivers
● É a responsável pela inicialização e
manutenção dos drivers
● Armazena informações sobre os drivers
carregados
● Funciona como uma camada de segurança,
evitando que comandos “errados” sejam
repassados aos drivers.
8. ● A implementação a ser apresentada possui
apenas 2 funções:
● Uma para inicialização de um driver
– Além da inicialização deve fornecer um ID para o
driver.
● Uma para repassar os comandos da aplicação
para os drivers
Controladora de Drivers
9. ● Para obter acesso à todos os drivers é
necessário que a controladora obtenha o
endereço de uma estrutura do tipo driver.
● Estáticamente:
● é montada uma lista com funções que retornam
esta estrutura.
● Dinâmicamente:
● recebe-se esta estrutura via comunicação
serial e retorna-se o endereço onde os dados
foram salvos.
Controladora de Drivers
10. static driver* driversLoaded[QNTD_DRV];
static char qntDrvLoaded;
char initDriver(char newDriver) {
char resp = FAIL;
if(dLoaded < QNTD_DRV) {
//obtem a estrutura do driver desejado
drivers[dLoaded] = drvInitVect[newDriver]();
//should test if driver was loaded correcly
resp = drivers[dLoaded]->drv_init(&newDriver);
dLoaded++;
}
return resp;
}
Controladora de Drivers
11. ● As funções de retorno de estrutura são
apresentadas à controladora no arquivo de
header.
● O header da controladora inclui cada um dos
arquivos de header dos drivers conhecidos em
tempo de execução.
● Uma lista com as funções é montada
juntamente com um enumerado descritivo
desta mesma lista.
Controladora de Drivers
13. //ddCtr.h
#include "drvGenerico.h"
#include "drvInterrupt.h"
#include "drvTimer.h"
enum {
DRV_GEN, /*1st driver*/
DRV_INTERRUPT, /*2nd driver*/
DRV_TIMER, /*3rd driver*/
DRV_END /*DRV_END must always be the last*/
};
//the functions to get the drivers should be put in
the same order as in the enum
static ptrGetDrv drvGetFunc[DRV_END] = {
getGenericoDriver, /*1st driver*/
getInterruptDriver, /*2nd driver*/
getTimerDriver /*3rd driver*/
};
Controladora de Drivers
14. char callDriver(char drv_id,
char func_id,
void *param) {
char i;
for (i = 0; i < dLoaded; i++) {
//find the right driver
if (drv_id == drivers[i]->drv_id) {
return
drivers[i]->func[func_id].func_ptr(param);
}
}
return DRV_FUNC_NOT_FOUND;
}
Controladora de Drivers
18. Interrupt Abstract Layer - IAL
● Um tipo de hardware comum a quase todo
microcontrolador é o dispositivo de
interrupção.
● Este dispositivo pausa o processador
quando há uma chamada de interrupção.
● Em seguida ele verifica qual a fonte da
chamada e, após salvar as variáveis da
CPU na stack, começa a executar de um
endereço pré-definido.
19. Interrupt Abstract Layer - IAL
● Com o intuito de simplificar este dispositivo
do ponto de vista do software é comum
criar um driver para realizar a gestão deste.
● Este driver receberá o endereço de funções
que serão executadas quando uma
determinada interrupção acontecer.
● É necessário uma função para receber o
endereço e uma variável para armazená-lo
internamente
20. Interrupt Abstract Layer - IAL
//drvInterrupt.c
//define o ponteiro de função a ser chamado
//na interrupção
typedef void (*intFunc)(void);
//variável para armazenar o endereço da função
//a ser executada na interrupção
static intFunc thisInterrupt;
//setup da função de interrupção
char setInterruptFunc(void *parameters) {
thisInterrupt = (intFunc) parameters;
return SUCESS;
}
21. Interrupt Abstract Layer - IAL
● A função para execução da interrupção é
dependente do compilador e do
processador utilizado. Deste modo a função
deve ser customizada para cada aplicação.
● Seguem-se três exemplos de
implementação.
23. Interrupt Abstract Layer - IAL
● A IAL facilita o uso das interrupções por
parte do programador, bastando apenas 3
passos
● O driver desejado é inicializado.
● O driver de interrupção é inicializado
● A função desejada é configurada
24. Interrupt Abstract Layer - IAL
//Função desejada para rodar na interrupção do timer
void timerISR(void) {
callDriver(DRV_TIMER, TMR_RESET, 1000);
kernelClock();
}
void main (void){
kernelInit();
//inicializando e configurando o timer
initDriver(DRV_TIMER);
callDriver(DRV_TIMER, TMR_START, 0);
callDriver(DRV_TIMER, TMR_INT_EN, 0);
//inicializando e configurando a interrupção
initDriver(DRV_INTERRUPT);
callDriver(DRV_INTERRUPT, INT_ENABLE, 0);
//configurando a rotina a ser chamada
callDriver(DRV_INTERRUPT, INT_TIMER_SET, (void*)timerISR);
kernelLoop();
}
26. Callback
● Funções de callback lembram os eventos
nas linugagens de alto nível
● Quando o mouse clicar no botão Y execute X
● Quando a tecla “t” for pressionada execute Z
● Para isso é necessário que o hardware seja
capaz de iniciar uma interrupção
27. Controladora de Drivers
● No processo do callback existem duas
partes separadas que devem ser
executadas sequencialmente.
● A primeira é o código que é executado dentro
da interrupção. Ele deve ser rápido e utilizar
poucos recursos. Geralmente são apenas
salvos os dados ou informações geradas pela
interrupção e seu processamento é postergado
neste momento
● A segunda é o processo de callback, rodado
agora pelo kernel pode levar mais tempo sem
atrapalhar a temporização do sistema.
29. Callback
//********** Excerpt from drvAdc.c **********
// called from setup time to enable ADC interrupt
// and setup ADC ISR callback
char enableAdcInterrup(void* parameters){
callDriver(DRV_INTERRUPT,INT_ADC_SET,(void*)adcISR);
BitClr(PIR1,6);
return FIM_OK;
}
//********** Excerpt from drvInterrupt.c **********
// store the pointer to the interrupt function
typedef void (*intFunc)(void);
static intFunc adcInterrupt;
// function to set ADC ISR callback for latter use
char setAdcInt(void *parameters) {
adcInterrupt = (intFunc)parameters;
return FIM_OK;
}
30. Callback
//********** Excerpt from main.c **********
// Process called by the kernel
char adc_func(void) {
//creating callback process
static process proc_adc_callback = {adc_callback, 0, 0};
callDriver(DRV_ADC,ADC_START,&proc_adc_callback);
return REPEAT;
}
//********** Excerpt from drvAdc.c **********
//function called by the process adc_func (via drv controller)
char startConversion(void* parameters){
callBack = parameters;
ADCON0 |= 0b00000010; //start conversion
return SUCCESS;
}
31. Callback
//********** Excerpt from drvInterrupt.c **********
//interrupt function
void isr(void) interrupt 1 {
if (BitTst(INTCON, 2)) { //Timer overflow
}
if (BitTst(PIR1, 6)) { //ADC conversion finished
//calling ISR callback stored
adcInterrupt();
}
}
//********** Excerpt from drvAdc.c **********
//ADC ISR callback function
void adcISR(void){
value = ADRESH;
value <<= 8;
value += ADRESL;
BitClr(PIR1,6);
kernelAddProc(callBack);
}
32. Callback
//********** Excerpt from main.c **********
//callback function started from the kernel
char adc_callback(void) {
unsigned int resp;
//getting the converted value
callDriver(DRV_ADC,ADC_LAST_VALUE,&resp);
//changing line and printing on LCD
callDriver(DRV_LCD,LCD_LINE,1);
callDriver(DRV_LCD,LCD_INTEGER,resp);
return SUCCESS;
}