EDK tutorial 2

From ift

Installering av en generell IP og tilhørende softwaredriver for MicroBlaze i Xilix Projekt Studio 7.1i

En enkel steg-for-steg veiledning til implementasjon av en softwaredriver for LCD på MEMEC protokort DS-BD-V4LX25MB

Dette er en kort veiledning lage software-drivere til eksterne komponenter i et microblaze system. Dette oppsettet basere seg på et prototypekort fra MEMEC. Vi vil ta utgangspunkt i det lille 2x16 tegns LCD-skjermen som følger med på kortet. Har du kjørt tutorial 1 vil du legge merke til at LCD displayet ikke ble inkludert i prosjektet. Dette må dermed legges til manuelt i ettertid. Siden det er snakk om en enkel IO enhet kan vi bruke en generell buss-IP uten å tenke på ekstra VHDL-kode som må implementeres. Du vil trenge XPS innstalert på maskinen samt tilgang til hyperterminal eller annen terminal som kan lese com-portene på PC'en din.


DEL 1 - Legge til IP

Lage IP

Åpne prosjektet fra tutorial 1 i XPS. Åpne menyen "project" og velg "Add/Edit Cores... (dialog)".

File:EDK XPS 20.jpg

Du vil nå få opp en oversikt over alle enheter som er tilkoblet prosessoren. I listen over tilgjenglige IP'er, velg "opb_gpio" og trykk "add". Du vil nå legge til en ny ip. Gi Ip'en navnet "LCD_module" og klikk "apply".

File:EDK XPS 21.jpg

I samme vindu velger du så menyen "Bus Connections". Bla deg ned på listen her til du finner "LCD_module sopb". Marker enhenten som slave for mb_opb bussen. Klikk så på "apply".

File:EDK XPS 22.jpg

Gå videre til "Adresses". Her trykker du på knappen "Generate Addresses". XPS vil da automatisk generere en adresse til IP'en vår. Du vil få opp et vindu som spør om du vil fortsette. klikk "Yes". Ip'em din vil nå ligge i adresseområdet 0x40040000-0x4004ffff, har du fått en annen verdi så husk denne verdien da du må bruke denn og ikke 0x40040000 videre i tutorialen. Trykk så "apply".

File:EDK XPS 23.jpg

Gå nå til menyen "Ports". Her skal vi koble interne signaler fra IP'en til et signal som senere kan rutes til pinner på FPGA'en. Begynn med å velge "LCD_module" i "Ports Filter". Bøa deg så ned i "List of Ports" til du finner signalene til vår IP. Hold nede "ctrl" tasten og velg "OPB_CLK" samt "GPIO_d_out". Trykk så "Add" for å legge dem til "Internal Ports Connection". For signalet OPB_CLK forandrer du "Net name" til "sys_clk_s". For signalet "GPIO_d_out" forandrer du "Net name" til fpga_lcd_module". I listen over "External Ports Connection" trykker du "Add Port". Du får nå opp et lite vindu som du må fylle ut data i. I linjen for "Port Name" skriver du "fpga_lcd_module". Sett "Port Polaritet" til "OUT" og gi "connected to" navnet "fpga_lcd_module". Trykk "Ok". Du må nå legge til "Range" for den eksterne porten vi definerte. Skriv inn "[0:9]". Trykk "Apply".

File:EDK XPS 24.jpg

Velg så menyen "Parameters". I rullegardinlisten over IP'er velger du LCD_module. Marker parametrene; "C_GPIO_WIDTH", "C_IS_DUAL", "C_ALL_INPUTS" og "C_IS_BIDIR". Trykk "Add". Sett så verdien til 10 for "C_GPIO_WIDTH" og til 0 for de tre andre. Trykk "Apply" og "Ok".

File:EDK XPS 25.jpg

Du har nå lagt til en IP som er koblet til OPB bussen og har 10 signallinjer(utganger) som kan kobles til fpga'ens pinner. Siden det her er snakk om en Ip som allerede eksisterer slipper vi å lage egene softwaredrivere til IP'en.

Koble til eksterne pinner

Neste steg er nå å rute våre 10 signal til rette pinner på fpga'en. Det gjøres i "user constraint" filen. Denne finner en under "Project files" og den heter "system.ucf". Åpne denne filen.

File:EDK XPS 26.jpg

Her legger vil til signalene våre og hvilke pinner de skal bruke samt hvilke type signal det er snakk om:

############################################################################
## This system.ucf file is generated by Base System Builder based on the
## settings in the selected Xilinx Board Definition file. Please add other
## user constraints to this file based on customer design specifications.
############################################################################

Net sys_clk_pin LOC=B13 | IOSTANDARD = LVCMOS25;
Net sys_rst_pin LOC=AB9;
Net sys_rst_pin PULLUP | IOSTANDARD = LVCMOS25;
## System level constraints
Net sys_clk_pin PERIOD = 10000 ps;
Net sys_rst_pin TIG;

## FPGA pin constraints

## Legg til våre signaler her
## lcd_enable (9)
Net fpga_lcd_module<0> LOC = AD10 | IOSTANDARD = LVCMOS25;
## lcd_RS (8)
Net fpga_lcd_module<1> LOC = AC11 | IOSTANDARD = LVCMOS25;
## lcd_data( 7-0 )
Net fpga_lcd_module<2> LOC = Y6   | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<3> LOC = W7   | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<4> LOC = AD6  | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<5> LOC = AE6  | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<6> LOC = AC7  | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<7> LOC = AD8  | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<8> LOC = AC8  | IOSTANDARD = LVCMOS25;
Net fpga_lcd_module<9> LOC = AC9  | IOSTANDARD = LVCMOS25;

Net fpga_0_RS232_RX_pin LOC=B14 | IOSTANDARD = LVCMOS25;
Net fpga_0_RS232_TX_pin LOC=T7  | IOSTANDARD = LVCMOS33;
Net fpga_0_RS232_req_to_send_pin LOC=T8  | IOSTANDARD = LVCMOS33;

Lagre filen når du er ferdig. Gå på "tools" menyen og velg "Update bitstream". XPS vil nå lage nye bitfiler med driveren inkludert. Dette tar gjene 1 til 2 timer. Bruk denne tiden til å ta deg en kaffe og gratulere deg selv over at du nå er klar til neste steg.

DEL 2 - Lage program til LCD

Includefil for lcd-skjerm

For å kunne teste ut lcd-skjermen og IP'en vi har laget til den trenger vi et lite bibliotek med funkjsoner som lar oss skrive på skjermen. Nedenfor er det listet opp enn c fil som inneholder disse rutinene, samt en header fil. Disse filene, <a href="uploads/lcd.c">lcd.c</a> og <a href="uploads/lcd.h">lcd.h</a>, må legges inn i prosjektkatalogen din på følgende sted: "...test/TestApp_Memory/src"

//-------------------------------------
//--       Masteroppgave 2005        --
//--                av               --
//--  Tor Aleksander Birk Danielsen  --
//--                                 --
//--  Driverfunkjsoner for 2x16      --
//--  lcd display                    --
//-------------------------------------
// 
// LCD_module_address må defineres

#include "xgpio_l.h"
#include "xutil.h"

#define LCD_module_address 0x40040000
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line

//=======================================
//== liten delayfunkjson brukt i lcd.c ==
//=======================================
void delay_ms(int delay_m){
   volatile int delay=0;
   volatile int i=0;
   for (i=0; i<= delay_m; i++){
     for (delay=0; delay<9000; delay++){
       //delay
     }
   }
}

//================================
//== sender byte til lcd skjerm ==
//================================
void lcd_send_byte(int address, Xuint32 data){
   if (address != 0) data = data | 0x100;
   else data = data & 0xFF;
   XGpio_mSetDataReg(LCD_module_address, 1, data);
   data = data | 0x200;
   delay_ms(2);
   XGpio_mSetDataReg(LCD_module_address, 1, data);
   delay_ms(5);
   data = data & 0x1FF;
   XGpio_mSetDataReg(LCD_module_address, 1, data);
}

//=================================*
//== gå til punkt på lcd skjermen ==
//=================================*
void lcd_gotoxy(int x,int y) {
   int address;
   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

//========================*
//== skriver tegn på lcd ==
//========================*
void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}

//================================
//== initialiserer LCD skjermen ==
//================================
void lcd_init(void){
   int i;
   Xuint32 init[4];
   init[0] = 0x00f; //init display
   init[1] = 0x001; //clear display
   init[2] = 0x038; //enable 8 bit data
   XGpio_mSetDataDirection(LCD_module_address, 1, 0x00000000);
   delay_ms(100);
   for(i=0; i<=2; i++){
     XGpio_mSetDataReg(LCD_module_address, 1, init[i]);
     init[i] = init[i] | 0x200; //enable høy
     delay_ms(2);
     XGpio_mSetDataReg(LCD_module_address, 1, init[i]);
     delay_ms(100);
     init[i] = init[i] & 0x1FF;    //enable lav
     XGpio_mSetDataReg(LCD_module_address, 1, init[i]);
     delay_ms(100);
   }
}


//=======================================*
//== Skriver strenger til LCD displayet ==
//=======================================*
void lcd_string(char *s){
  while (*s)
  {
    lcd_putc(*s);
    s++;
  }
  return;
}

//===============================================
//== Skriver ut en testmelding på lcd skjermen ==
//===============================================
void lcd_test_msg(void){
   lcd_putc('\f');
   lcd_gotoxy(1,1);
   lcd_string("* Test av LCD  *");
   lcd_gotoxy(1,2);
   lcd_string("*abcdefghijklmn*");
}

//=====================================
//==       Masteroppgave 2005        ==
//==                av               ==
//==  Tor Aleksander Birk Danielsen  ==
//=====================================
//--                                 --
//--       Filnavn: lcd.h            --
//--       Dato: 06/06-2005          --
//--                                 --
//-------------------------------------
#include "xgpio_l.h"
#include "xutil.h"

//-------------------------------------
//    delay_ms(millisekund);
//-------------------------------------
// enkel funksjon som generer delay i ms området
void delay_ms(int delay_m);

//-------------------------------------
//    lcd_string();
//-------------------------------------
// Skriver ut en streng på lcd-skjermen
void lcd_string(char *s);

//-------------------------------------
//    lcd_init();
//-------------------------------------
// initialiserer et 2x16 lcd display
void lcd_init(void);

//-------------------------------------
//    lcd_send_byte(address,data);
//-------------------------------------
// Sender en byte til lcd displayet
// Første variabel er '0' hvis det
// registerinfo som sendes, ellers
// er den '1' for tegn
void lcd_send_byte(int address, Xuint32 data);

//-------------------------------------
//    lcd_send_nibble(data,address);
//-------------------------------------
//??? ikke i bruk
void lcd_send_nibble(int data, int address);

//-------------------------------------
//    lcd_gotoxy(x,y);
//-------------------------------------
// Gå til et punkt på lcd skjermen
void lcd_gotoxy(int x,int y);

//-------------------------------------
//    lcd_putc(c);
//-------------------------------------
// skriver ut en bokstav på lcd skjerm
// spesialtegn:
// '\f' 
// '\n'
// '\b'
void lcd_putc( char c);

//-------------------------------------
//    lcd_test_msg();
//-------------------------------------
// skriver ut en testmelding
void lcd_test_msg(void);

Main fil

Du vil også trenge en main rutine som kjører hovedprogrammet ditt. Denne filen <a href="uploads/main.c">main.c</a> må du også legge inn i samme prosjektkatalog, "...test/TestApp_Memory/src", som de to forrige filene.

//-----------------------------------
//--          toturial 2           --
//--      test av lcd-skjerm       --
//--                               --
//-- Tor Aleksander Birk Danielsen --
//-----------------------------------

//-- include headers --
#include "xparameters.h"
#include "xgpio_l.h"
#include <stdio.h>
#include "lcd.h"

int main(void) {

	print("--main_rutine--\n\r");
	print("lcd init....");
	lcd_init(); //inintialiserer lcd skjerm
	print("ok\n\r");
	print("skriver test msg på lcd\n\r");
	lcd_test_msg();
	delay_ms(2000);					// 2sek delay
	print("skiver streng på lcd\n\r");
	lcd_putc('\f'); 				//ny skjerm
	lcd_gotoxy(1,1);				//setter markør i øvre venstre hjørne
	lcd_string("dette virker jo!"); //skriver ut en streng
	while(1); //stopper programmet her med evig sløyfe
}

Du må nå åpne "applications" menyen og åpne prosjektet "TestApp_Memory". Høyreklikk på filen "TestApp_Memory.c" og slett den. Høyreklikk på "source" og velg "add file..". Legg til "lcd.c" og "main.c". Velg "header" og legg til på samme måte "lcd.h".

File:EDK XPS 27.jpg

Pass på at "#define LCD_module_address 0x40040000" i lcd.c peker til rett adresse. Denne adressen ble automatisk generert tidligere i oppgaven og skal ideelt sett være lik.

Gå på "tools" menyen og velg "Build All User Aplications". Du vil nå få kompilert c-koden din. Start så opp hyperterminal med samme innstilinger som forrige gang. Gå på "tools" menyen og velg "downloads". Du vil nå få lastet over prosessor og programkode på fpga'en. På lcd skjermen vil du få opp følgende to meldinger med 2 sek mellomrom:

* Test av LCD  *
*abcdefghijklmn*
dette virker jo!

og på hyperterminal vil følgende melding komme opp:

--main_rutine--
lcd init....ok
skriver test msg på lcd
skiver streng på lcd