📄 apbuart.c
字号:
#include <stdio.h>/* * test suite for the GRLIB UART with FIFOs. Set FIFOSIZE, FREQUENCY to the * current configuration and select a baudrate. If an error is found, the cpu * will trap and the failure number will be written to the memory location * given by MSGAREA. The trap is generated by writing to address zero which * should be write protected. An interactive test which checks parity, * frame and break is also available. It is enabled by defining INTERACTIVE * to 1 (default 0). It should not be used when running the code in a VHDL * simulation. When the interactive test is run instructions are printed on * the terminal. Make sure that it is set to odd parity initially. The * ONLY_INTERACTIVE parameter disables the initial automatic test when it is * set to 1.This is used when one only wants to run the interactive test. If * a failure is found it can be located in the code and the reason * determined. If everything is ok the program ends with * "program exited normally." or if the interactive test is run, "Test * completed without errors" is printed on the terminal. The initial part * can take a few minutes to run. * * Modified : The routine now returns error code instead of trapping * */#define SHORT_TEST 1 #define INTERACTIVE 0#define ONLY_INTERACTIVE 0#define FIFOSIZE 16#define FREQUENCY 40#if SHORT_TEST == 1#define BAUDRATE ((FREQUENCY*100)/80)*1E4 #else#define BAUDRATE 38400#endif#define MSGAREA 0x40008000#define DATA_REG_ADDR 0x80000100#define STATUS_REG_ADDR 0x80000104#define CONTROL_REG_ADDR 0x80000108#define SCALER_REG_ADDR 0x8000010c#define IRQ_CTRL_ADDR 0x80000200#define DISABLE 0x0#define ENABLE_RX 0x1#define ENABLE_TX 0x2#define RX_INT 0x4#define TX_INT 0x8#define EVEN_PARITY 0x20#define ODD_PARITY 0x30#define LOOP_BACK 0x80#define FLOW_CONTROL 0x40#define FIFO_TX_INT 0x200#define FIFO_RX_INT 0x400#define CR 13#define LINEFEED 10 extern void *catch_interrupt(void func(), int irq);static int irqrx = 0;static int irqtx = 0;static int interactive = 0;static volatile int *lreg = (int *) IRQ_CTRL_ADDR;static volatile int *data = (int *) DATA_REG_ADDR;static volatile int *control = (int *) CONTROL_REG_ADDR;static volatile int *status = (int *) STATUS_REG_ADDR;static volatile int *scaler = (int *) SCALER_REG_ADDR;char test[] = "40ti94a+0ygiyu05yhap5yi4h+a+iiyxhi4k59j0q905jkoyphoptjrhia4iy0+4";char oddpartest[] = "Type in five characters on the terminal.";char oddpartest2[] = "OK. Now change to even parity and send five characters";char evenpartest[] = "OK. Now type in five characters again. This time they will be echoed"; char breaktest[] = "OK. Now send a break frame";char testok[] = "Test completed without errors";int testsize = sizeof test / sizeof test[0];static enable_irq (int irq) { lreg[0x8/4] = ~(1 << irq); // clear bit in force reqister lreg[0xC/4] = (1 << irq); // clear any pending irq lreg[0x40/4] |= (1 << irq); // unmasks irq}static disable_irq (int irq) { lreg[0x40/4] &= ~(1 << irq); } // mask irqstatic force_irq (int irq) { lreg[0x8/4] = (1 << irq); } //force irqstatic clear_irq (int irq) { lreg[0xC/4] = (1 << irq); }/*fail function called when a failure is found, it writes to address 0with the fail number * 4 as offset. This memory area should be writeprotected so that the cpu traps*/static void fail(int i) { int *x = (int *) MSGAREA; int *y = (int *) 0; *x = i; *y = 0; }void sendstring(char *str, int parity, int length) { int i = 0; *data = CR; while( !(*status & 4) ) ; *data = LINEFEED; while( !(*status & 4) ) ; while( i < length) {#if FIFOSIZE == 1 while( !(*status & 4) ) ;#else while( (*status & 0x200) ) ;#endif *data = str[i]; i++; } while( !(*status & 4) ) ; *data = CR; while( !(*status & 4) ) ; *data = LINEFEED; while( !(*status & 4) ) ;} void irqhandler1(int irq){ int temp; if( (*control & 0xf) != 0xf ) { /*interrupt error*/ fail(31); } if( !(*status & 1) && !(*status & 4) ) { /* int error */ fail(32); } if( (*status & 1) ) { temp = *data; if(temp != (int) test[irqrx % testsize] ) { /*receive error */ fail(33); } irqrx++; } if( (*status & 4) ) { *data = test[irqtx % testsize]; irqtx++; } if( irqrx > 100000 ) { disable_irq(2); }}void irqhandler2(int irq){ int temp; if( !(*status & 0x80) && !(*status & 0x100) ) { /*fifo int error*/ fail(34); } if( (*status & 0x80) ) { *data = test[irqtx % testsize]; irqtx++; } if( (*status & 0x100) ) { temp = *data; if( temp != test[irqrx % testsize] ) { /*receive data error */ fail(35); } irqrx++; } if(irqrx > 100000) { disable_irq(2); } clear_irq(2);}void irqhandler3(int irq) { int temp; if((*status & 0x20) != 0 ) { /*parity error*/ fail(39); } else if( (*status & 0x58) != 0) { /*receive error */ fail(40); } else if( (*status & 1) == 0) { /*int error*/ fail(41); } else { temp = *data; *data = temp; interactive++; while(!(*status & 2)) ; if(interactive > 4) { disable_irq(2); } }}void irqhandler4(int irq) { if( !(*status & 0x20) ) { /*no parity error when there should be*/ fail(42); } else { interactive++; if(interactive > 4) { disable_irq(2); } *status = 0; }}void irqhandler5(int irq) { if(!(*status & 8)) { /*break failed*/ fail(43); } else { disable_irq(2); interactive++; } }int apbuart_test(void) { int temp; int i; *scaler = (int)((FREQUENCY*1E6)/(BAUDRATE*8)); *control = ENABLE_RX | ENABLE_TX | LOOP_BACK; /*set counters to 0, and status bits to reset values*/ while( (*status & 1) || !(*status & 4) ) { temp = *data; } temp = 0; *control = DISABLE; *status = 0;#if !ONLY_INTERACTIVE /********************************** * TRANSMITTER TEST **********************************/ for(i = 0; i < FIFOSIZE; i++) { if( (FIFOSIZE > 1) && ( (*status >> 20 & 0x3F) != i) ) { /*tcnt incorrect*/ return 1; } if((i == 0) && ((*status & 4) == 0) || (i != 0) && ((*status & 4) != 0) ) { /*te bit incorrect*/ return 2; } if(*status & 2 == 0) { /*ts bit incorrect*/ return 3; } if((FIFOSIZE > 1) && (i < FIFOSIZE / 2) && ((*status & 0x80) == 0) || (FIFOSIZE > 1) && (i >= FIFOSIZE / 2) && ((*status & 0x80) != 0)) { /*th bit incorrect*/ return 4; } *data = (int) test[i % testsize]; if((FIFOSIZE > 1) && (*status & 0x100 == 0)) { /*tf bit incorrect*/ return 5; } } /*te bit test for fifosize = 1*/ if(FIFOSIZE == 1 && (*status & 4) != 0) { /*te bit incorrect*/ return 6; } /********************************* * RECEIVER TEST (WITH LOOPBACK) *********************************/ if(*status & 1 != 0) { /*dr bit incorrect*/ return 7; } *control = ENABLE_TX | ENABLE_RX | LOOP_BACK; i = 0;#if SHORT_TEST == 0#if FIFOSIZE == 1 while((*status & 1) == 0) { if( i > (int)( FIFOSIZE * ( (FREQUENCY * 1E6)/ BAUDRATE ) ) ) { /*transmission not finished on time*/ return 8; } i++; }#else while((*status & 0x400) == 0) { if( i > (int)( FIFOSIZE * ( (FREQUENCY * 1E6) / BAUDRATE) ) ) { /*transmission not finished on time*/ return 8; } i++; } #endif#else#if FIFOSIZE == 1 while((*status & 1) == 0) ;#else while((*status & 0x400) == 0) ; #endif#endif if( (*status & 1) == 0 ) { /*dr bit incorrect*/ return 9; } for(i = 0; i < FIFOSIZE; i++) { if( (FIFOSIZE > 1) && ( ((*status >> 26) & 0x3F) != (FIFOSIZE - i) ) ) { /*rcnt error*/ return 10; } temp = *data; if( temp != (int) test[i % testsize]) { /*incorrect data received*/ return 11; } if( (i != FIFOSIZE - 1) && (*status & 1 == 0) || (i == FIFOSIZE) && (*status & 1 != 0) ) { /*dr bit incorrect*/ return 12; } if( (FIFOSIZE > 1) && (i < FIFOSIZE / 2) && (*status & 0x100 == 0) || (FIFOSIZE > 1) && (i >= FIFOSIZE / 2) && (*status & 0x100 == 1) ) { /*rh bit incorrect*/ return 13; } } *control = DISABLE; /************************************* *TRANSMITTER OVERFLOW TEST *************************************/ for(i = 0; i < FIFOSIZE * 2; i++ ) { *data = test[i % testsize]; } if( *status & 0xfff != 512 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -