Tehát. Adott a következő kód:
#include "xparameters.h"
#include "stdio.h"
#include "xutil.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
#include "xintc_l.h"
#include "xgpio.h"
//====================================================
// Definitions
//====================================================
#define BAUDRATE 115200
#define USE_PARITY 0
#define PARITY_ODD 1
#define DATABITS 8
//====================================================
// GLOBAL VARIABLES
//====================================================
unsigned int counter = 0;
unsigned int c2 = 0;
int buchstabe;
XGpio leds;
XUartLite serial,second_serial;
//====================================================
// INTERRUPT HANDLER FUNCTION
//====================================================
void serial_interrupt_handler(void* addr_p)
{
int empty;
//XGpio_DiscreteWrite(&leds, 1, 255);
empty = XUartLite_IsReceiveEmpty(XPAR_RS232_PORT_BASEADDR);
if (empty == FALSE )
buchstabe = XUartLite_RecvByte(XPAR_RS232_PORT_BASEADDR);
//XGpio_DiscreteWrite(&leds, 1, buchstabe);
xil_printf("::%c::",buchstabe);
}
void second_serial_interrupt_handler(void* addr_p)
{
int empty;
//XGpio_DiscreteWrite(&leds, 1, 255);
empty = XUartLite_IsReceiveEmpty(XPAR_RS232_SECOND_BASEADDR);
if (empty == FALSE )
buchstabe = XUartLite_RecvByte(XPAR_RS232_SECOND_BASEADDR);
//XGpio_DiscreteWrite(&leds, 1, buchstabe);
xil_printf("XX%cXX",buchstabe);
}
//====================================================
// Delay
//====================================================
void ussleep(unsigned int delay)
{
unsigned int j, i;
for(i=0; i<delay; i++)
for(j=0; j<100; j++);
}
void mssleep(unsigned int delay)
{
unsigned int j, i;
for(i=0; i<delay; i++)
for(j=0; j<100; j++)
ussleep(1);
}
void ssleep(unsigned int delay)
{
unsigned int j, i;
for(i=0; i<delay; i++)
for(j=0; j<100; j++)
mssleep(1);
}
int main()
{
Xuint8 hello[4];
unsigned int i;
//-----------------
hello[0]=72;
hello[1]=69;
hello[2]=76;
hello[3]=79;
//-----------------
XUartLite_Config UART_Configuration;
UART_Configuration.DeviceId = XPAR_RS232_PORT_DEVICE_ID;
UART_Configuration.RegBaseAddr = XPAR_RS232_PORT_BASEADDR;
UART_Configuration.BaudRate = BAUDRATE;
UART_Configuration.UseParity = USE_PARITY;
UART_Configuration.ParityOdd = PARITY_ODD;
UART_Configuration.DataBits = DATABITS;
XUartLite_Config UART_Second_Configuration;
UART_Second_Configuration.DeviceId = XPAR_RS232_SECOND_DEVICE_ID;
UART_Second_Configuration.RegBaseAddr = XPAR_RS232_SECOND_BASEADDR;
UART_Second_Configuration.BaudRate = BAUDRATE;
UART_Second_Configuration.UseParity = USE_PARITY;
UART_Second_Configuration.ParityOdd = PARITY_ODD;
UART_Second_Configuration.DataBits = DATABITS;
//UART init:
XUartLite_CfgInitialize (&serial, &UART_Configuration, XPAR_RS232_PORT_BASEADDR) ;
XUartLite_CfgInitialize (&second_serial, &UART_Configuration, XPAR_RS232_SECOND_BASEADDR) ;
xil_printf("First and Second UART configured to send any data.\n");
//-----------------
XGpio_Initialize(&leds, XPAR_LEDS_8BIT_DEVICE_ID);
XGpio_SetDataDirection(&leds, 1,0x0);
XGpio_DiscreteWrite(&leds, 1, 1);
XIntc_RegisterHandler(XPAR_XPS_INTC_0_BASEADDR,
XPAR_XPS_INTC_0_RS232_PORT_INTERRUPT_INTR,
(XInterruptHandler)serial_interrupt_handler,
(void *)XPAR_RS232_PORT_BASEADDR);
XIntc_RegisterHandler(XPAR_XPS_INTC_0_BASEADDR,
XPAR_XPS_INTC_0_RS232_SECOND_INTERRUPT_INTR,
(XInterruptHandler)second_serial_interrupt_handler,
(void *)XPAR_RS232_SECOND_BASEADDR);
XGpio_DiscreteWrite(&leds, 1, 2);
XIntc_MasterEnable(XPAR_XPS_INTC_0_BASEADDR);
XGpio_DiscreteWrite(&leds, 1, 3);
XIntc_EnableIntr(XPAR_XPS_INTC_0_BASEADDR, XPAR_RS232_PORT_INTERRUPT_MASK);
XGpio_DiscreteWrite(&leds, 1, 4);
XIntc_EnableIntr(XPAR_XPS_INTC_0_BASEADDR, XPAR_RS232_SECOND_INTERRUPT_MASK);
XGpio_DiscreteWrite(&leds, 1, 5);
//XUartLite serial,second_serial;
XUartLite_Initialize(&serial,XPAR_RS232_PORT_DEVICE_ID);
XUartLite_Initialize(&second_serial,XPAR_RS232_SECOND_DEVICE_ID);
XGpio_DiscreteWrite(&leds, 1, 6);
XUartLite_SetRecvHandler(&serial,
(XUartLite_Handler) serial_interrupt_handler,
(void *)XPAR_RS232_PORT_BASEADDR);
XUartLite_SetRecvHandler(&second_serial,
(XUartLite_Handler) second_serial_interrupt_handler,
(void *)XPAR_RS232_SECOND_BASEADDR);
XGpio_DiscreteWrite(&leds, 1, 7);
XUartLite_EnableInterrupt(&serial);
XUartLite_EnableInterrupt(&second_serial);
XGpio_DiscreteWrite(&leds, 1, 8);
microblaze_enable_interrupts();
XGpio_DiscreteWrite(&leds, 1, 0);
//------------------------------------
while(XUartLite_IsSending(&serial));
XUartLite_Send(&serial, (Xuint8*)(hello), 4);
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)(hello), 4);
//XGpio_DiscreteWrite(&leds, 1, (Xuint8)i);
//------------------------------------
while(1);
}
A program nem nagyon hosszú és szerintem könnyű is megérteni. Lényeg belőle : adott két soros bemenet. Azt szeretnénk elérni, hogy az egyik soros bemeneten érkező adat irányítsa a ledeket (8 biten beküldött karakter 8 ledet... semmi extra), a másik soros porton küldött adat pedig vissza legyen küldve az elsőn (vagyis egy sima átirányítás). Az elgondolásom a következő volt : írok két interrupt kezelő függvényt, egyet az első számú soros portra (erre megy a xil_printf() függvény is), ami a ledeket villogtatja, majd írok egy másik szintén megszakítás kezelő függvényt, amiben csak továbbküldöm az érkezett adatokat xil_printf segítségével.
Induljunk ki abból, hogy a hardver kompozíció hibátlan, viszont a kód hibás. Hogyan jövünk rá, hogy mi a hiba? Az egyik legegyszerűbb változat az, amit Balázs is mondott, villogtatjuk a ledeket, mikor elértünk valahová. Ez megvolt. A program kiküldte a HELO üzenetet mindkét soros terminálra. És valami mégsem megy. Aki most megkapja a hibát, továbbolvasás nélkül, annak van egy söre... ;)
Amit még tudni kell, hogy az interrupt kontrollerben prioritás szerint rendezni lehet a megszakítás kéréseket, annak érdekében, hogy egy alacsonyabb szintű megszakítás kiszolgálását félbe lehessen hagyni, ha egy magasabb szintű megszakítás kérés érkezik.
Mégegy részlet a programbol, amire szükség lesz a mai debuggoláshoz a következő:
#define XPAR_INTC_SINGLE_BASEADDR 0x81800000
#define XPAR_INTC_SINGLE_HIGHADDR 0x8180FFFF
#define XPAR_INTC_SINGLE_DEVICE_ID XPAR_XPS_INTC_0_DEVICE_ID
#define XPAR_RS232_PORT_INTERRUPT_MASK 0X000001
#define XPAR_XPS_INTC_0_RS232_PORT_INTERRUPT_INTR 0
#define XPAR_RS232_SECOND_INTERRUPT_MASK 0X000002
#define XPAR_XPS_INTC_0_RS232_SECOND_INTERRUPT_INTR 1
Miután háromszor újraírtam az interrupt kezelő függvényt kezdtem gyanakodni, hogy a hiba valahol máshol leledzik, és sorrol sorra megvizsgáltam a teljes programot. Legelső szarvashiba a következő volt:
//UART init:
XUartLite_CfgInitialize (&serial, &UART_Configuration, XPAR_RS232_PORT_BASEADDR) ;
XUartLite_CfgInitialize (&second_serial, &UART_Configuration, XPAR_RS232_SECOND_BASEADDR) ;
Minek kínlódtam én azzal, hogy két soros eszközt definiáljak, ha az inicializálásnál mindkettőhöz az &UART_Configuration prekonfigurált beállítás került? Ennek kellett egy gyors csere. Tovább tesztelve a progit rájöttem, hogy csak egyetlen interrupt aktiválódik, bármennyire is kínozom... S mindig az, amelyiket másodiknak írom be... Nem az számít, hogy melyik magasabb prioritású, hanem az, hogy a forráskódban melyiknek a maszkját írtam később... Lássuk a kódot megint:
XIntc_EnableIntr(XPAR_XPS_INTC_0_BASEADDR, XPAR_RS232_PORT_INTERRUPT_MASK);
XGpio_DiscreteWrite(&leds, 1, 4);
XIntc_EnableIntr(XPAR_XPS_INTC_0_BASEADDR, XPAR_RS232_SECOND_INTERRUPT_MASK);
XGpio_DiscreteWrite(&leds, 1, 5);
Aztán ide is megjött a megvilágosodás. Ha én veszek egy lapot s ráírom, hogy 0x00000001 majd letörlök mindent a lapról és ráírom, hogy 0x00000002, akkor a másodikat fogja látni mindenki, aki benéz oda. Binárisan felbontva a feladatot :
Az "1" binárisan 8 biten: 00000001
A "2" binárisan 8 biten: 00000010
Ez egy megszakítás maszk. Amikor egy megszakítás érkezik a megszakítás vonalra, a CPU megnézi, hogy szabad-e attól az egységtől megszakítást fogadni, vagy sem. S ezt az az egyes határozza meg, amit két sorral fennebb leírtam. Vagyis ha én 00000001-et írok, akkor csak az első soros porttól jöhet megszakítás. Ha 00000010-et írok, akkor csak a második soros port megszakításait kezelem. Ha viszont 00000011-et írok, akkor mindkét megszakítás kérést engedélyezem.
Hibák kijavítva. Az eredmény az lett, amit vártam. Villogtak a ledek, jöttek a számok. Mindenki boldog.
0 megjegyzés:
Megjegyzés küldése