Download as pdf or txt
Download as pdf or txt
You are on page 1of 42

DPS Training Manual

Version: 1.0

Copyright © Vayavya Labs 2018 Pvt. Ltd. 1


Private and confidential
Document versions:

Date Version Author Comments


number
28th Nov 2018 1.0 Uma Bondada First draft with review comments
incorporated

Copyright © Vayavya Labs Pvt. Ltd. 2


Private and confidential
Table of Contents
1 Overview ............................................................................................................... 4
2 Typographical Conventions .................................................................................... 5
3 Getting started with DPS files ................................................................................ 6
3.1 DPS file from command line: ...................................................................................... 6
3.2 DPS file on devicedrivers.org ...................................................................................... 6
3.3 DPS file from DDGEN Eclipse plug-in: ......................................................................... 6
3.3.1 Using pre-defined template DPS files ........................................................................ 6
3.3.2 Using empty DPS files ................................................................................................ 7
3.3.3 Importing existing DPS files ....................................................................................... 7
4 Populating the DPS files ......................................................................................... 9
4.1 Register definitions .................................................................................................... 9
4.1.1 Register fields in DPS ............................................................................................... 10
4.1.2 Register field specification in DPS ............................................................................ 11
4.1.1 Register with multiple field specification in DPS ..................................................... 13
4.1.1 Register categories in DPS ....................................................................................... 15
4.2 Device specification ................................................................................................. 18
4.3 Bus specification ...................................................................................................... 20
4.4 Sequences ................................................................................................................ 21
4.5 Memory specification .............................................................................................. 28
4.6 Interrupt specification ............................................................................................. 30
5 Multiple DPS files ................................................................................................ 34
APPENDIX A – pc16550d_reg_def.dps ........................................................................ 35
APPENDIX B – pc16550d.dps ...................................................................................... 40

Copyright © Vayavya Labs 2018 Pvt. Ltd. 3


Private and confidential
DPS Training manual

1 Overview
This document explains how to write a DPS (Device Programming Specification)
file, a formal representation of the hardware IP. DPS has been specifically devised
for DDGEN (Device Driver Generator) so that it can be used to generate code in C
to program the hardware.
DDGEN is a tool that generates device drivers automatically if provided with two
inputs:
• The DPS file.
• The run time environment specified in a configuration file called as the
Run Time Specification file (also referred as RTS file).
DDGEN can be run from the command line or from the Eclipse IDE by using the
DDGEN plug-in.

Copyright © Vayavya Labs Pvt. Ltd. 4


Private and confidential
DPS Training manual

2 Typographical Conventions
Symbol/Meta charaters Meaning
Courier 11 • DPS keywords and characters that are part of
the DPS syntax.
• Code snippets, or reference to code snippets.
• Literals

Times New Roman 12 Regular Text


italics This means that the word is a placeholder to be
replaced by another word/value.
[] Specifies Optional field.
() Specifies clubbing of different options.
Example: (K|G|M) would mean either K or G or M
| Means "or" and is not part of the syntax unless it is in
courier font.

Copyright © Vayavya Labs Pvt. Ltd. 5


Private and confidential
DPS Training manual

3 Getting started with DPS files


The DPS file can be created from DDGEN Eclipse plug-in, or from the command
line.

3.1 DPS file from command line:


The DPS file can be created just like a text file with the .dps extension using
command line editor of your choice.

3.2 DPS file on devicedrivers.org


When you create a new project, file.dps is an empty file, which represents the
DPS file. Enter data into this file.

3.3 DPS file from DDGEN Eclipse plug-in:


DPS files are by default created during the creation of new projects. They can be
populated in 3 different ways.

3.3.1 Using pre-defined template DPS files


When the window to “select the type of the driver” is launched
(Refer to point 2e in section 3.1 in the DDGen Eclipse Plugin User Manual.pdf
for more details), and the user selects “Create from Template”, then a
partially filled DPS files are created. These files would look something like this:

Copyright © Vayavya Labs Pvt. Ltd. 6


Private and confidential
DPS Training manual

The partially filled files can be completed with help of auto-completion (short cut
key: CTRL+SPACE). Syntax highlighting, mouse hover and outline view can
help the user in completing the DPS files correctly.

3.3.2 Using empty DPS files


When the window to “select the type of the driver” is launched
(Refer to point 2e in section 3.1 in the DDGen Eclipse Plugin User Manual.pdf
for more details), and the user un-checks “Create from Template”, then
empty DPS and RTS files named new.dps and new.rts are created. The user
would have to edit the files using valid DPS constructs specified in the reference
manuals, or do a copy-paste from existing DPS files.

3.3.3 Importing existing DPS files


Create empty DPS files as specified in section 3.2.2, delete them and import new
DPS files in the project by using the following steps:

! Right click on the project select Import. Import window will appear

Copyright © Vayavya Labs Pvt. Ltd. 7


Private and confidential
DPS Training manual

! Select File System and click Next and browse the folder path where
the file is present, Click on OK and select the file that needs to be
imported.



! Click on finish in order to import a file to present project.

To help the user in editing the DPS files, the DDGen Eclipse plugin provides
auto-completion, syntax highlighting, and mouse hover. Please refer to the
document “DDGen Eclipse Plugin User Manual.pdf” for more details.

Copyright © Vayavya Labs Pvt. Ltd. 8


Private and confidential
DPS Training manual

4 Populating the DPS files


The DPS specification for a device describes the characteristics, in terms of the
registers on the device, interrupts, interconnects and hardware FIFO/memory
supported by the device. The DPS also provides programming constructs to specify
the various features of the device as programming sequence.
This section helps in writing the commonly used constructs of a DPS file using
snippets from an actual datasheet of a UART device PC16550D as reference.
Please refer to the DPS reference manual (DDGen-DPS.pdf) for the complete
language constructs.

4.1 Register definitions


Registers are an integral part of any device. They are used to program the IP to
operate in different ways. Most IPs will have at least one register in it.
Let’s look at the different aspects of a register that would be relevant from DPS
register definition point of view. Following is a page from the datasheet showing
the table summarizing the registers from PC16550D.

Copyright © Vayavya Labs Pvt. Ltd. 9


Private and confidential
DPS Training manual

The above table shows 12 registers each identified by a name, description,


access type, size in bits, offset and the significance of each of the bits of the
register.

4.1.1 Register fields in DPS


At register level, DPS requires the following information:
• Names of the registers. Example: RBR, THR, IER, etc… in PC16550D.
• Size of the register in bits. In the case of PC16550D, it is 8.
• Offsets with respect to the base address at which the registers can be accessed.
For example in PC16550D the offsets are specified as highlighted below:

Sometimes the offset can be specified by an actual address value, in


which case the offset will be the difference of the current register
address value from the first register address value.
• Description of the register. For example in PC16550D the description of
RBR is highlighted below:

• Software access type in terms of the register being read-writeable, readable


only or writeable only. This is represented as RW/RO/WO. In the case of
PC16550D, it is specified as follows:

Copyright © Vayavya Labs Pvt. Ltd. 10


Private and confidential
DPS Training manual

This information is captured as follows in DPS format:


name [size] @ offset {
[description = string;]
sw_axs = access-type;
[value_on_reset = reset-value;]

}

Note: the description and value_on_reset fields are optional and


register definition is incomplete without the field specification (will be
explained later).
Applying the DPS format to PC16550D’s register RBR, the register is
defined as follows:
RBR [8] @ 0 {
description = “Receiver Buffer Register”;
sw_axs = ro;

}

Register definition in DPS is incomplete without the register field


specification, i.e the specification of how each bit in the register is used.

4.1.2 Register field specification in DPS


In case of PC16550D, the register bits of RBR are specified as follows:

Copyright © Vayavya Labs Pvt. Ltd. 11


Private and confidential
DPS Training manual

The register bits 0 to 7 of RBR and THR are


specified as data bits. Hence the bits 0 to 7 can
be considered as a single field.
The field information is captured as follows in
DPS format:

field field-name <low-bit : high-bit > {


[description = string;]
sw_axs = access-type;
[value_on_reset = reset-value;]
[clearing_mode = mode-value;]
}

Note: description, clearing_mode and


value_on_reset fields are optional.

Applying the DPS register field format to RBR’s register bits, the register
field is defined as follows:
field RBR <0:7> {
description = “Received data”;
sw_axs = ro;
clearing_mode = dc;
}

Combining the RBR’s register with field specification, the complete register
definition of RBR in DPS is:
RBR [8] @ 0 {
description = “Receiver Buffer Register”;
sw_axs = ro;

field RBR <0:7> {


description = “Received data”;
sw_axs = ro;
clearing_mode = dc;

Copyright © Vayavya Labs Pvt. Ltd. 12


Private and confidential
DPS Training manual

}
}

4.1.1 Register with multiple field specification in DPS


Let’s take a look at another register LCR from PC16550D, which has multiple
register fields.

The relevant register and field information are:


• register name: LCR
• register size: 8
• register offset: 3
• access type: read-write (RW)
• register bits 0 and 1 are related to the same feature, i.e word length select
(WLS), hence bits 0 – 1 can be specified as one field.
• register bit 2 is related to number of stop bits (STB), hence bit 2 is one
field.
• register bit 3 is related to parity enable (PEN), hence bit 3 is one field.

Copyright © Vayavya Labs Pvt. Ltd. 13


Private and confidential
DPS Training manual

• register bit 4 is related to even parity select (EPS), hence bit 4 is one field.
• register bit 5 is related to stick parity (SP), hence bit 5 is one field.
• register bit 6 is related to set break (SB), hence bit 6 is one field.
• register bit 7 is related to divisor latch access bit (DLAB), hence bit 7 is
one field.
Using the above information LCR can be specified in DPS in the following
manner:
LCR [8] @ 3 {
description = “Line Control Register”;
sw_axs = rw;

field WLS <0:1> {


description = “Word Length Select”;
sw_axs = rw;
clearing_mode = dc;
}
field STB <2:2> {
description = “Number of stop bits”;
sw_axs = rw;
clearing_mode = dc;
}
field PEN <3:3> {
description = “Parity enable”;
sw_axs = rw;
clearing_mode = dc;
}
field EPS <4:4> {
description = “Even Parity Select”;
sw_axs = rw;
clearing_mode = dc;
}
field SP <5:5> {
description = “Stick Parity”;
sw_axs = rw;
clearing_mode = dc;
}
field SB <6:6> {
description = “Set break”;
sw_axs = rw;
clearing_mode = dc;
}
field DLAB <7:7> {
description = “Divisor Latch Access Bit”;
sw_axs = rw;
clearing_mode = dc;
}
}

Copyright © Vayavya Labs Pvt. Ltd. 14


Private and confidential
DPS Training manual

Alternately LCR can be specified in DPS with its bits 3, 4 and 5 clubbed as one
field that controls the parity. This is entirely left to the discretion of the driver
writer on the granularity of control required. The LCR definition would look
like this:
LCR [8] @ 3 {
description = “Line Control Register”;
sw_axs = rw;

field WLS <0:1> {


description = “Word Length Select”;
sw_axs = rw;
clearing_mode = dc;
}
field STB <2:2> {
description = “Number of stop bits”;
sw_axs = rw;
clearing_mode = dc;
}
field PEN <3:5> {
description = “Parity selection”;
sw_axs = rw;
clearing_mode = dc;
}
field SB <6:6> {
description = “Set break”;
sw_axs = rw;
clearing_mode = dc;
}
field DLAB <7:7> {
description = “Divisor Latch Access Bit”;
sw_axs = rw;
clearing_mode = dc;
}
}

4.1.1 Register categories in DPS


DPS categorizes registers as follows:
• Data Registers: Registers that contain data to be read/written to the
device.
• Control Registers: Registers that configure the operation of the device.
• Status Registers: Registers that contain the status of an operation of the
device.
• Interrupt Registers: Registers that are used in enabling/disabling and
identifying different interrupts supported by the device.

Copyright © Vayavya Labs Pvt. Ltd. 15


Private and confidential
DPS Training manual

• General purpose Registers: Registers that cannot be categorized into any


of the above types of registers fall under this category.
In case of PC16550D, RBR is a data register, while LCR is a control
register. The complete DPS specification of RBR and LCR registers
would be as follows:
DATA_REGISTERS {
RBR [8] @ 0 {
description = “Receiver Buffer Register”;
sw_axs = ro;

field RBR <0:7> {


description = “Received data”;
sw_axs = ro;
clearing_mode = dc;
}
}
}
CONTROL_REGISTERS {
LCR [8] @ 3 {
description = “Line Control Register”;
sw_axs = rw;

field WLS <0:1> {


description = “Word Length Select”;
sw_axs = rw;
clearing_mode = dc;
}
field STB <2:2> {
description = “Number of stop bits”;
sw_axs = rw;
clearing_mode = dc;
}
field PEN <3:5> {
description = “Parity selection”;
sw_axs = rw;
clearing_mode = dc;
}
field SB <6:6> {
description = “Set break”;
sw_axs = rw;
clearing_mode = dc;
}
field DLAB <7:7> {
description = “Divisor Latch Access Bit”;
sw_axs = rw;
clearing_mode = dc;

Copyright © Vayavya Labs Pvt. Ltd. 16


Private and confidential
DPS Training manual

}
}
}

Copyright © Vayavya Labs Pvt. Ltd. 17


Private and confidential
DPS Training manual

4.2 Device specification


The main DPS file normally starts with the device specification. This
specification is mandatory for a given DPS specification, since it identifies the
type of device. This is more or less similar to what is shown in the example
device specification for PC16550D.
In case of PC16550D, the device specification will be written as follows:
DEVICE_SPEC {
DEVICE_NAME = pc16550d;
MANUFACTURER_NAME = “National Semiconductor”;
DEVICE_VERSION = “Improved version of 16450”;
DEVICE_CLASS = SERIAL;
DEVICE_INPUT_CLOCK = 0Hz – 24MHz;
}

Notes on what can be specified on the right hand side of each of the device
specification fields:
• DEVICE_NAME: Should be a sequence characters that can ONLY be
alphanumeric or underscore. Starting character to be an alphabet.
• MANUFACTURER_NAME: Should be the manufacturer’s name enclosed in
double quotes.
• DEVICE_VERSION: Should describe the device version, or a device
version number enclosed in double quotes.
• DEVICE_CLASS: Should be one of the DPS keywords specifying the type
of device that best describes the device under consideration. The valid
keywords that can be used are the following:
o SERIAL
o MEMORY
o NETWORK
o USB_DEVICE
o USB_HOST
o AUDIO
o VIDEO
o DMA_CONTROLLER
o I2C_MASTER
o SPI_CONTROLLER
o MEMORY_CONTROLLER
o STANDARD_DATA_CONTROL
o VIDEO_CAPTURE
o INTERNAL_SUB_DEV
o VIDEO_BUFFER
o VIDEO_DECODER
o AUDIO_INTERFACE

Copyright © Vayavya Labs Pvt. Ltd. 18


Private and confidential
DPS Training manual

o INPUT_DEVICE_CONTROLLER
o DEFAULT
Please use DEFAULT for all other device classes to generate bare metal
drivers.
• DEVICE_INPUT_CLOCK: Could be a frequency or a set/range of
frequencies that specify the input clock frequencies to the device. This
field is optional. If the DEVICE_INPUT_CLOCK specifies multiple values,
and a single value required to be used in the driver as part of DPS sequence, then
the required value will have be picked up from the “run time environment file”
(the RTS file ) given as the second input to DDGEN.

Copyright © Vayavya Labs Pvt. Ltd. 19


Private and confidential
DPS Training manual

4.3 Bus specification


The only other specification that is mandatory other than the device specification
is the bus specification. This specifically consists of a single field in most cases.
In case of PC16550D, the bus specification written as follows:
BUS_SPEC {
REGISTER_ACCESS_TYPE = MEMORY_MAPPED;
}

Copyright © Vayavya Labs Pvt. Ltd. 20


Private and confidential
DPS Training manual

4.4 Sequences
The DPS sequences are the DPS equivalent of a device driver API that programs
the device for a specific functionality.

In case of a UART device, the typical features to be implemented would be:


• Configure the baud rate
• Configure the word length, stop bit, parity for the data transmission
• Receive data
• Transmit data
Let’s take up each of these features with respect to PC16550D.
1. configure the baud rate:
The snippet of the data sheet related to programming the baud rate of
PC16550D is as follows:

Based on the data sheet the formula co-relating the baud rate and the 16-
bit divisor is:
16-bit divisor = input clock frequency / (baud rate * 16)

Copyright © Vayavya Labs Pvt. Ltd. 21


Private and confidential
DPS Training manual

Since transmitting and receiving UARTs need


to have identical baud rates, the baud rate will
be known and so will the value of input clock
frequency. The 16-bit divisor calculated using
the above formula needs to be loaded into the
two divisor latches. The two divisor latches
would be the divisor latch registers DLL and
DLM based on the search for “divisor latch”.

What needs to be done to implement the feature:


• Calculate the 16-bit divisor value based on baud and clock frequency.
• Load the calculated 16-bit divisor value into the registers DLL and
DLM
How to do it:
• divisor = clock_frequency / (baud * 16).
• Set the bit 7 of register LCR to 1 in order to program registers DLL
and DLM
• Write the most significant 8 bits of the 16-bit divisor into DLM
• Write the least significant 8 bits of the 16-bit divisor into DLL
• Set the bit 7 of register LCR to 0 so that the data registers RBR and
THR can be accessed as this would be required for the normal
operation of the UART
The DPS sequence:

DESCRIPTION = "This function configures the baud rate


for data transmission and reception";
sequence configure_baud_rate
{
input unsigned int baud;
input unsigned long clk_freq;

Copyright © Vayavya Labs Pvt. Ltd. 22


Private and confidential
DPS Training manual

local unsigned short divisor;

divisor = clk_freq / (16 * baud);


LCR.DLAB = 1;
DLL = divisor & 0x00ff;
DLM = (divisor >> 8) & 0x00ff;
LCR.DLAB = 0;
}

2. configure the word length, stop bit, parity for the data transmission
Configuring the word length, stop bit and parity are related to the
programming of the LCR register. The snippet of the data sheet related to
describing these bits in LCR of PC16550D is as follows:

What needs to be done to implement the feature:


• Based on the value of word length, program the bit 0 and 1 of LCR
accordingly.
• Based on the value of stop bit, program the bit 2 of LCR accordingly.
• Based on the value of parity, program the bit 4 of LCR accordingly.

Copyright © Vayavya Labs Pvt. Ltd. 23


Private and confidential
DPS Training manual

How to do it:
As a good programming practice it is important to have defensive
programming in place so that invalid values passed to the function are
handled gracefully. It is important to decide on what is expected as the
valid values for each of the parameters based on its functionality. It should
be meaningful at the application level and at the same time keep the code
size of the driver as small as possible. For example:
• Word length as per the datasheet can be 5, 6, 7 or 8, where as the
values to be set in the register field are 0, 1, 2 or 3. So if the input
parameter word_length can be an enum descriptive of the
functionality while its value is what needs to programmed in the
register field, then it would satisfy both the conditions without any
coding overhead.
• Stop bit as per datasheet can be 1, 1.5 or 2, but this is also dependent
on the data length. If data length is 5 bits, then the stop bit can be 1 or
1.5, but not 2. However if data length is 6, 7 or 8, then the stop bit can
be 1 or 2. To avoid confusion we can have enums like short_stopbit
and long_stopbit, which means 1 stop bit, or 1.5/2 stop bits. These
enums can be assigned values that are required to program the bit 2 of
LCR to set the stop bit length accordingly.
• Even/odd parity can be set by programming bit 4 of LCR to 1/0
accordingly. So if we use enums like even_parity = 1 and odd_parity =
0, that can be passed as the parity parameter, then the value can be
used to program the LCR directly.

The DPS sequence:

DESCRIPTION="This function configures the different


parameters for
data transmission";
SEQUENCE configure_data_transmission {
INPUT word_length (0-3);
INPUT stop_bit (0,1);
INPUT parity(0,1);

LCR.WLS = word_length;
LCR.STB = stop_bit;
# Enable parity before setting even, or odd parity
LCR.PEN = 0x1;
LCR.EPS = parity;
}

Copyright © Vayavya Labs Pvt. Ltd. 24


Private and confidential
DPS Training manual

Please note the following in the DPS sequence:


• The input arguments don’t have the data types, instead have the
valid values specified in brackets.
Example code: INPUT word_length (0-3).
By specifying the values, DDGEN will know what data type to use
for word_length and can also insert an assert statement to check
for these values. Insertion of the assert statement is based on the
RTS field DEFENSIVE_PROGRAMMING being turned on.
• The statement starting with the # is treated as a C comment
statement that gets retained in the generated code. Example code:
# Enable parity before setting even, or odd parity
in the sequence configure_data_transmission is such a
comment.
In order to handle the enums, DPS’s register definition will need to be
enhanced with an enum section in the following manner:

field wls <0:1> {


description = “Word Length Select”;
sw_axs = rw;
clearing_mode = dc;
enum {
fivebit = 0;
sixbit = 1;
sevenbit = 2;
eightbit = 3;
}
}

}
DDGEN generates the following enums when the enum section is
specified.
typedef enum {
lcr_wls_eightbit = 3,
lcr_wls_sevenbit = 2,
lcr_wls_sixbit = 1,
lcr_wls_fivebit = 0
}
The application that calls configure_data_transmission can use
the enum as follows:
configure_data_transmission(lcr_wls_sevenbit,
lcr_stb_short_stopbit, lcr_eps_even_parity);

Copyright © Vayavya Labs Pvt. Ltd. 25


Private and confidential
DPS Training manual

3. Receive data
The data received by the UART PC16550D is stored in a FIFO. The FIFO
can store up to 16 bytes of data, but the access to the FIFO is one byte at a
time through the register RBR.
What needs to be done to implement the feature:
Read RBR and store it in the memory pointed to by character pointer buff
How to do it:
The implementation would be:
• Wait until bit 0 of LSR is 1 indicating that data is available in the Receiver
buffer Register (RBR)
• Once data is available, check if any errors like: parity, overrun, framing or
break error has occurred.
• If no errors have occurred, then read RBR register until bit 0 of LSR is 0.

The DPS sequence:


DESCRIPTION="This function reads the data from the
receive register RBR";
SEQUENCE device_read {
OUTPUT unsigned char buff;
#poll as long as there is some data available
poll until (LSR.dr == 1)
error (LSR.oe == 1 || LSR.pe == 1 ||
LSR.fe == 1 || LSR.bi == 1);
buf = RBR;
}
Explanation:
• The DPS keyword output indicates that buf is an output parameter
whose value is available to the caller of the sequence. The C translation is
that of a pointer of type char.
• poll until condition will translate to a while (1) loop that breaks
when the condition is true. To avoid looping infinitely a retry count is used
to break out of the loop even if the condition is not true. The value of the
retry count is picked up from the RTS file.
• The DPS keyword error indicates that this an error condition and return
Y_FAILURE if the condition specified is true.

4. Transmit data

The data to be transmitted by the UART PC16550D is the data written into

Copyright © Vayavya Labs Pvt. Ltd. 26


Private and confidential
DPS Training manual

THR register. Up to 16 bytes of data can be written that is stored in the


FIFO accessed only through THR.
What needs to be done to implement the feature:
Write into THR from the memory pointed to by buff.
How to do it:
The implementation would be:
• Wait until bit 5 of LSR is 1 indicating that the transmitter holding register
is empty.
• On this condition write 1 byte at a time until the FIFO is full.

The DPS sequence:


DESCRIPTION="This function write the data into the
transmit register THR";
SEQUENCE device_write {
INPUT unsigned char buf;
if (LSR.THRE == 1) {
THR = buf;
}
}

Copyright © Vayavya Labs Pvt. Ltd. 27


Private and confidential
DPS Training manual

4.5 Memory specification


If the device is a memory device or contains a memory element like a hardware
FIFO, Endpoint, memory space, etc… then the DPS specification
memory_spec is specified.
PC16550D supports a FIFO mode that can store up to16 bytes as shown by the
following snippet from the data sheet:

The DPS specification of the memory_spec is as follows:


memory_spec {
type = fifo;
fifo xmitfifo {
type = HW_FIFO;
transfer_type = transmit;
max_depth = 16;
max_wordsize = 1;
access_mechanism = THR.THR;
configured_depth = FCR.RT;
}
fifo rcvfifo {
type = hw_fifo;
transfer_type = receive;
max_depth = 16;
max_wordsize = 1;
access_mechanism = RBR.RBR;
configured_depth = FCR.RT;
}
}
Explanation:
• The memory_spec defines two FIFOs called:
o xmitfifo that stores the data to be transmitted indicated by the
field: TRANSFER_TYPE = TRANSMIT
o rcvfifo that stores the data to be received indicated by the field:
TRANSFER_TYPE = RECEIVE
• The size (depth) of the FIFO is 16 bytes indicated by the field:
MAX_DEPTH = 16

Copyright © Vayavya Labs Pvt. Ltd. 28


Private and confidential
DPS Training manual

• The access to the FIFO is indicated by the field: ACCESS_MECHANISM =


RBR.RBR
• The effective size (depth) FIFO in PC16550D can be changed by setting
the value of bit 6 and 7 of Fifo Control Register (FCR) as follows:

• This is captured by the field: CONFIGURED_DEPTH = FCR.RT


Following are the DPS sequences device_write and device_read modified
to use the transmit and receive FIFOs xmitfifo and rcvfifo:

DESCRIPTION = "UART Transmit";


sequence device_write {
input unsigned char buf[];
input unsigned int cnt;

xmitfifo(cnt) = buf;
}

DESCRIPTION = "UART Receive";


sequence device_read {
output unsigned char buf[];
input unsigned int cnt;

buf = rcvfifo(cnt);
}

Copyright © Vayavya Labs Pvt. Ltd. 29


Private and confidential
DPS Training manual

4.6 Interrupt specification


One of the key aspects of a device is to understand the interrupts supported by it.
If the device supports interrupts, then the DPS specification interrupt_spec
is specified.

PC16550D supports the interrupts shown by the following snippet from the data
sheet:

The above information can be captured in DPS’s interrupt_spec as follows:


interrupt_spec {
interrupt_pending = IIR.INT_PEND(0x0) ;
uart {
tx_reg_empty {
status = IIR.INT_ID(1);
int_type = device_write ;
enable_field = IER.ETBEI(0x1) ;
disable_field = IER.ETBEI(0x0) ;
clear_field = auto_clear ;
interrupt_priority = 2;
}
time_out {
status = IIR.INT_ID(6);
int_type = error;
clear_field = auto_clear;
enable_field = IER.ERBFI(0x1);
disable_field = IER.ERBFI(0x0);
interrupt_priority = 1;
}

Copyright © Vayavya Labs Pvt. Ltd. 30


Private and confidential
DPS Training manual

rx_data_av {
status = IIR.INT_ID(2);
int_type = device_read;
enable_field = IER.ERBFI(0x1);
disable_field = IER.ERBFI(0x0);
clear_field = auto_clear;
interrupt_priority = 1;
}
rx_line_stat {
status = IIR.INT_ID(3);
int_type = error;
enable_field = IER.ELSI(0x1);
disable_field = IER.ELSI(0x0);
clear_field = cor LSR;
interrupt_priority = 0;
parity_error {
status = LSR.PE(1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
overrun_error {
status = LSR.OE(1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
frame_error {
status = LSR.FE(1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
break_error {
status = LSR.BI(1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
}
}
}
Explanation:
• PC16550D supports only one interrupt line and this is captured under an
identifier uart{…}. If the device supported multiple interrupt lines, then
there would be multiple specifications like uart{…} under different unique
identifiers within interrupt_spec.

Copyright © Vayavya Labs Pvt. Ltd. 31


Private and confidential
DPS Training manual

• In PC16650D, bit 0 (referred to as INT_PEND register field in the DPS


register definitions) of the register IIR will indicate that an interrupt is
pending if it is 0. This check can be used to service multiple interrupts,
hence it is captured as a global field: INTERRUPT_PENDING =
IIR.INT_PEND(0x0);
• All the interrupts serviced by PC16650D are connected to the same interrupt
line, hence it is captured within the uart{…}.
• The value in bit 1 - 3 (referred to as INT_ID register field in the DPS
register definitions) of the register IIR indicates identity of the interrupt.
The different interrupts are:

Value in Interrupt description Interrupt identifier in


INT_ID interrupt_spec
3 Receiver line status rx_line_status
2 Received data available rx_data_available

6 Time out timeout


1 Transmitter holding register tx_reg_empty
empty
0 Modem status modem_status

• Each interrupt captures the following information:


o The status indicates the register field and the value that is set in it to
flag that the interrupt has occurred.
o int_type indicates the type of interrupt. The right hand side on this
field can be one the DPS keywords:
! device_read: interrupt associated with receiving of data by the
device.
! device_write: interrupt associated with transmitting of data by
the device.
! error: interrupt associated with occurrence of an error condition.
! status: interrupt associated with a change of device status.
o enable/disable_field: specifies the mechanism to enable/disable
the particular interrupt by writing the specified value into the register
field.
o clear_field: specifies the mechanism to clear the particular interrupt.
This can be done by:
! Reading a particular register as is the case in the above example. cor
means “clear on read”.

Copyright © Vayavya Labs Pvt. Ltd. 32


Private and confidential
DPS Training manual

! Writing the specified value into the register field. This would be cow
register.field(value). cow means “clear on write”.
! auto_clear: this would mean “nothing specific to be done”.
o interrupt_priority indicates the priority of the interrupt.

Copyright © Vayavya Labs Pvt. Ltd. 33


Private and confidential
DPS Training manual

5 Multiple DPS files

The DPS constructs can span across multiple files. Typically the register definitions
are specified in a separate DPS file, while the remaining DPS constructs are written
in different DPS file.
DDGEN does not impose any restrictions on the number of files or how the files
need to be named, but all the DPS files available to the user follow the convention
of naming the main DPS file based on the IP and the register definition file as ip-
name_reg_def.dps. For example in case of PC16550D, the main DPS file can be
called pc16550d.dps and the file containing the register definitions can be
pc16550d_reg_def.dps.
In order for DDGEN to pick up all the DPS files any one of the following
approaches can be used:
1. On command line:

• Specify all the DPS files separated by a space on the command line following the
–E option. Example:

$> ddgen.py -E pc16550d_reg_def.dps pc16550d.dps

• #include the other DPS files the main DPS file. E.g In pc16550d.dps specify:

#include " pc16550d_reg_def.dps"


2. DDGEN Eclipse plug-in:

• Place all the DPS files in in the project folder in order for it to be picked up by
DDGEN.

Copyright © Vayavya Labs Pvt. Ltd. 34


Private and confidential
DPS Training manual

APPENDIX A – pc16550d_reg_def.dps
This is the DPS file containing the register definitions of PC16550D – Universal
Asynchronous Receiver/Transmitter.
/*
* This is the DPS file for PC16650D Universal Asynchronous
* Transmitter/Receiver with FIFOs
*/

DATA_REGISTERS {
RBR [8] @ 0 {
SW_AXS = RO;
DESCRIPTION = "RECEIVER BUFFER REGISTER";
FIELD RBR <0:7> {
SW_AXS = RO;
DESCRIPTION = "This register holds the receives data";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
}

THR [8] @ 0 {
SW_AXS = WO;
DESCRIPTION = "TRANSMITTER HOLDING REGISTER";
FIELD THR <0:7> {
SW_AXS = WO;
DESCRIPTION = "This register holds the data to be transmitted";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
}
}
INTERRUPT_REGISTERS {
IER [8] @ 1 {
SW_AXS = RW;
DESCRIPTION = " INTERRUPT ENABLE REGISTER";
FIELD ERBFI <0:0> {
SW_AXS = RW;
DESCRIPTION = "Enable Receive Data Available Interrupt";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
FIELD ETBEI <1:1> {
SW_AXS = RW;
DESCRIPTION = "Enable Transmit Holding Register Empty Interrupt";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
FIELD ELSI <2:2> {
SW_AXS = RW;
DESCRIPTION = "Enable Receive Line Status Interrupt";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
FIELD EDSSI <3:3> {
SW_AXS = RW;
DESCRIPTION = "Enable Modem Status Interrupt";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
RESERVED <4:7> = 0;
}

IIR[8] @ 2 {
SW_AXS = RO;

Copyright © Vayavya Labs Pvt. Ltd. 35


Private and confidential
DPS Training manual

DESCRIPTION = " INTERRUPT INDENTIFICATION REGISTER";


FIELD INT_PEND <0:0> {
SW_AXS = RO;
DESCRIPTION = "0 logic indicates Interrupt Pending";
CLEARING_MODE = DC;
VALUE_ON_RESET = 1;
}
FIELD INT_ID <1:3> {
SW_AXS = RO;
DESCRIPTION = "Indicates the Interrupt ID";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
ENUM {
ModemStat = 0x0;
TxRegEmpty = 0x1;
TimeOut = 0x6;
RxDataAv = 0x2;
RxLineStat = 0x3;
}
}
RESERVED <4:5> = 0;
FIELD FIFOENBD <6:7> {
SW_AXS = RO;
DESCRIPTION = "FIFO Enable";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
}
}
CONTROL_REGISTERS {
LCR [8] @ 3 {
SW_AXS = RW;
DESCRIPTION = "LINE CONTROL REGISTER";
FIELD WLS <0:1> {
SW_AXS = RW;
DESCRIPTION = "WORD LENGTH SELECT\
These two bits specify the number of bits in each\
transmitted or received serial character\
0 : 5 bits\
1 : 6 bits\
2 : 7 bits\
3 : 8 bits";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
ENUM {
five_bit = 0;
six_bit = 1;
seven_bit = 2;
eight_bit = 3;
}
}
FIELD STB <2:2> {
SW_AXS = RW;
DESCRIPTION = "Number of Stop Bits\
This bit specifies the number of Stop bits transmitted\
and received in each serial character. If bit 2 is a \
logic 0,one Stop bit is generated in the transmitted \
data. If bit 2 is a logic 1 when a 5-bit word length \
is selected via bits 0 and 1,one and a half Stop bits \
are generated. If bit 2 is a logic 1 when either a 6-, \
7-, or 8-bit word length is selected, two Stop bits \
are generated The Receiver checks the first Stopbit\
only, regardless of the number of Stop bits selected";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
ENUM {
short_stop_bit = 0;
long_stop_bit = 1;
}

Copyright © Vayavya Labs Pvt. Ltd. 36


Private and confidential
DPS Training manual

}
FIELD PEN <3:3> {
SW_AXS = RW;
DESCRIPTION = "PARITY ENABLE BIT\
The Parity bit is used to produce an even or odd number \
of 1s when the data word bits and the Parity bit are \
summed. When bit 3 is a logic 1, a Parity bit is \
generated or checked between the last data word bit \
and Stop bit of the serial data.";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
FIELD EPS <4:4> {
SW_AXS = RW;
DESCRIPTION = "EVEN PARITY Select \
When bit 3 is a logic 1 and bit 4 is a logic 0, an odd \
number of logic 1s is transmitted or checked in the \
or checked in the data word bits and Parity bit. When \
bit 3 is a logic 1 and bit 4 is a logic 1, an even \
number of logic 1s is transmitted or checked";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
ENUM {
even_parity = 1;
odd_parity = 0;
}
}
FIELD STKPAR <5:5> {
SW_AXS = RW;
DESCRIPTION = "STICKY PARITY Bit\
When set to logic 0 Stick Parity disable\
When bits 3, 4 and 5 are logic 1 the Parity bit is \
transmitted and checked as a logic 0. If bits 3 and 5 \
are 1 and bit 4 is a logic 0 then the Parity bit is \
transmitted and checked as a logic 1.";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
ENUM {
disable_sticky_par = 0;
enable_sticky_par = 1;
}
}
FIELD SETBRK <6:6> {
SW_AXS = RW;
DESCRIPTION = "Break Control Bit\
When set to logic 0 : break control is disabled\
It causes a break condition to be transmitted to the \
receiving UART. When it is set to a logic 1, the \
serial output (SOUT) is forced to the Spacing \
(logic 0) state.";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
FIELD DLAB <7:7> {
SW_AXS = RW;
DESCRIPTION = "Divisor Latch Access Bit\
Set to logic high to access divisor latches of the \
baud generator during R/W. Set logic low to access Rx\
buffer ,THR, IER";
CLEARING_MODE = DC;
VALUE_ON_RESET = 0;
}
}
}
STATUS_REGISTERS {
LSR [8] @ 5 {
SW_AXS = RW;
DESCRIPTION = " LINE STATUS REGISTERS";
FIELD DR <0:0> {

Copyright © Vayavya Labs Pvt. Ltd. 37


Private and confidential
DPS Training manual

SW_AXS = RW;
DESCRIPTION = "Date Ready Indicator";
CLEARING_MODE = COR RBR;
VALUE_ON_RESET = 0;
}
FIELD OE <1:1> {
SW_AXS = RW;
DESCRIPTION = "Over Run Error received";
CLEARING_MODE = COR LSR;
VALUE_ON_RESET = 0;
}
FIELD PE <2:2> {
SW_AXS = RW;
DESCRIPTION = "Parity Error received";
CLEARING_MODE = COR LSR;
VALUE_ON_RESET = 0;
ENUM {
enabled = 0x1;
disabled = 0x0;
}
}
FIELD FE <3:3> {
SW_AXS = RW;
DESCRIPTION = "Framing Error received";
CLEARING_MODE = COR LSR;
VALUE_ON_RESET = 0;
}
FIELD BI <4:4> {
SW_AXS = RW;
DESCRIPTION = "Break Interrupt received";
CLEARING_MODE = COR LSR;
VALUE_ON_RESET = 0;
}
FIELD THRE <5:5> {
SW_AXS = RW;
DESCRIPTION = "Transmitter Holding Register Empty";
CLEARING_MODE = DC;
VALUE_ON_RESET = 1;
}
FIELD TEMT <6:6> {
SW_AXS = RW;
DESCRIPTION = "Transmitter holding and shift register empty";
CLEARING_MODE = DC;
VALUE_ON_RESET = 1;
}
FIELD ERXFIFO <7:7> {
SW_AXS = RW;
DESCRIPTION = "Error In Receiver FIFO";
CLEARING_MODE = COR LSR;
VALUE_ON_RESET = 0;
}
}
}

GENERAL_PURPOSE_REGISTERS {
DLL [8] @ 0 {
SW_AXS = RW;
DESCRIPTION = "DEVICE LATCH LEAST SIGNIFICANT BYTE";
FIELD DLL <0:7> {
SW_AXS = RW;
CLEARING_MODE = DC;
VALUE_ON_RESET = NA;
}
}

DLM [8] @ 1 {
SW_AXS = RW;
DESCRIPTION = "DEVICE LATCH MOST SIGNIFICANT BYTE";

Copyright © Vayavya Labs Pvt. Ltd. 38


Private and confidential
DPS Training manual

FIELD DLM <0:7> {


SW_AXS = RW;
CLEARING_MODE = DC;
VALUE_ON_RESET = NA;
}
}
}

Copyright © Vayavya Labs Pvt. Ltd. 39


Private and confidential
DPS Training manual

APPENDIX B – pc16550d.dps
This is the DPS file containing the remaining specifications other than the register
definitions of PC16550D – Universal Asynchronous Receiver/Transmitter.
device_spec {
device_name = pc16550d;
manufacturer_name = "National Semiconductors";
device_version = "Improved cersion of 16450";
device_class = serial;
device_input_clock = 0Hz - 24MHz ;
}

bus_spec {
reg_access_type = memory_mapped;
}

memory_spec {
type = fifo;
fifo xmitfifo {
type = HW_FIFO;
transfer_type = transmit;
max_depth = 16;
max_wordsize = 1;
access_mechanism = THR.THR;
}
fifo rcvfifo {
type = hw_fifo;
transfer_type = receive;
max_depth = 16;
max_wordsize = 1;
access_mechanism = RBR.RBR;
}
}

description="This function configures the different parameters for data transmission";


sequence configure_data_transmission
{
input word_length (0 - 3);
input stop_bit (0, 1) ;
input parity (0, 1);

LCR.WLS = word_length;
LCR.STB = stop_bit;
LCR.PEN = 0x1;
LCR.EPS = parity;
}

description = "This function configures the baud rate for data transmission and
reception";
sequence configure_baud_rate
{
input baud (50,75,110,9600,128000);
local unsigned int divisor;

divisor = DEVICE_INPUT_CLOCK / (baud * 16);


LCR.DLAB = TRUE;
DLL = divisor & 0x00ff;
DLM = (divisor >> 8) & 0x00ff;
LCR.DLAB = FALSE;
}

description = "This function reads the data from the receive FIFO";
sequence device_read {
output unsigned char buf[];
input unsigned int cnt;

Copyright © Vayavya Labs Pvt. Ltd. 40


Private and confidential
DPS Training manual

#poll as long as there is some data available in the fifo


poll until (LSR.DR == 1)
error (LSR.OE == 0x1 || LSR.PE == 0x1 || LSR.FE == 0x1 || LSR.BI == 0x1 );
buf = rcvfifo (cnt);
}

description = "This function write the data into the transmit FIFO";
sequence device_write {
input unsigned char buf[];
input unsigned int cnt;

if (LSR.THRE == 0x1) {
xmitfifo(cnt) = buf;
}
}

interrupt_spec {
interrupt_pending = IIR.INT_PEND(0x0) ;
uart {
tx_reg_empty {
status = IIR.INT_ID(1);
int_type = device_write ;
enable_field = IER.ETBEI(0x1) ;
disable_field = IER.ETBEI(0x0) ;
clear_field = auto_clear ;
interrupt_priority = 2;
}
time_out {
status = IIR.INT_ID (6);
int_type = error;
clear_field = auto_clear;
enable_field = IER.ERBFI (0x1);
disable_field = IER.ERBFI (0x0);
interrupt_priority = 1;
}
rx_data_av {
status = IIR.INT_ID (2);
int_type = device_read;
enable_field = IER.ERBFI (0x1);
disable_field = IER.ERBFI (0x0);
clear_field = auto_clear;
interrupt_priority = 1;
}
rx_line_stat {
status = IIR.INT_ID(3);
int_type = error;
enable_field = IER.ELSI (0x1);
disable_field = IER.ELSI (0x0);
clear_field = cor LSR;
interrupt_priority = 0;

parity_error {
status = LSR.PE (1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
overrun_error {
status = LSR.OE (1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
frame_error {
status = LSR.FE (1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;

Copyright © Vayavya Labs Pvt. Ltd. 41


Private and confidential
DPS Training manual

}
break_error {
status = LSR.BI (1);
int_type = error;
clear_field = cor LSR;
interrupt_priority = 0;
}
}
}
}

Copyright © Vayavya Labs Pvt. Ltd. 42


Private and confidential

You might also like