Interrupcions


Per que volem interrupcions?

Moltes vegades ens interesarà gestionar certs events que passin al nostre microcontrolador, principalment d’entrada i sortida. El computador té una limitació d’execució, només s’executa una intrucció a la vegada, i és a la que apunta el PC. Per tant, si volem detectar aquests events en temps real hem de fer el que es coneix com a espera activa, es a dir, un bucle on comprovem els valors que ens interessin constantment. Per això, el microprocessador ens ofereix una solució implementada mitjantçant hardware.

Com funciona una interrupció?

Cada interrupció té associats 3 bits principals, que estan emmagatzemats en registres especials del microprocessador.

Quan el bit IF d’una interrupció pren valor 1, s’interromp la execució i el PC apunta a on està el codi que controla les interrupcions. En el nostre microprocessador trobem que una interrupció pot ser de prioritat alta o baixa. El codi en assemblador que controla les interrupcions de alta prioritat es troba a partir de la posició de memoria 0x08 i el de les de baixa prioritat a 0x18. Si es necessita més espai per a gestionar les interrupcions es pot cridar a funcions que estiguin a qualsevol lloc de memoria.

Per a que el CiruitLogicCombinacional que gestiona les interrupcions funcioni com nosaltres volguem hem de configurar certs registres del microprocessador. Si fem un seguiment de que passa amb cada bit a les portes logiques ens adonem facilment de que vol dir cada un.

Per saber on trobar aquests bits tenim aquesta taula, que ens diu en quins registres trobarlos. Per assignar el seu valor podem utilitzar les instruccions BTFSC (bit file set clear) i BTFSS (bit file set set):

La prioritat d’una interrupció resulta en que mai es tractara una interrupció de baixa prioritat si n’hi ha una de alta prioritat per tractar (veiem que en el CLC la sortida que interrucpeix esta conectada negada amb el final de les interrucions de baixa prioritat en una AND. Si val 1, no interrumpirem de baixa prioritat) . En resum el CLC que tracta les interrupcions té dos sortides principals

Quan es produeix una interrupció s’ha de gestionar d’alguna manera que no es tracti una altra interrupció, ja que podria causar problemes. Per tant quan interrumpim, el bit GIE (en cas de les de alta prioritat)/GIEL (en cas de baixa prioritat) passa a valdre 0 mentre es tracta la intrucció. Per tant podem veure que si interrumpim, i despres arriben dos interrupcions, primer una de baixa i despres una de alta, quan s’acabi de tractar i GIE torni a valdre 1, per la lògica del CLC tractarem primer la de alta prioritat, i despres la de baixa.

En acabar el tractament de la interrupció hem de tornar a la intrucció a la que estavem. La intrucció RETFIE ens ho fa: PC = PC(abans de la interrupció). A més, dins del codi que tracta la interrupció hem de posar el IF (interrupt flag) a 0 ja que la interrució ha estat tractada, sino estariem en un bucle infinit tractant la interrupció continuament.

Una altre tema a tenir en compte és que el codi que s’estava executant tenia com a premisa que els registres WREG, STATUS i BSR no canvien si no els modica una intrucció. Per tant, per que el programa segueixi funcionant quant acabem de tractar la interrupció hem de deixar aquests registres tal i com estaven. Per al cas de les interrupcions de alta prioritat en tenim prou amb fer un RETFIE FAST, que copia als registres una copia que havia fer el microprocessador quan ha saltat la interrupció (només si la interrupció es de altat prioritat). Si gestionem interrupcions de baixa priortat hem de salvar i restaurar aquest registres manualment (mitjançant instruccions).