Vous êtes sur la page 1sur 129

EMBEDDED PROCESSORS LAB. MANUAL (T.E.

ELEX SEM-II)

ALL INDIA SHRI SHIVAJI MEMORIAL SOCIETYS


COLLEGE OF ENGINEERING, PUNE

Department of Electronics Engineering

LAB MANUAL
T.E. ELECTRONICS (SEMESTER-II)
Embedded Processors Lab
Subject Code: 304215

Teaching Scheme

Examination Scheme

Practical: 2Hrs/Week

Term Work: 50 Marks


Practical : 50 Marks

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

PREFACE

Lab Description: Embedded Processors Lab


Software Required: Windows OS, SPJIDE IDE, SCARM
Hardware Required: LPC2148 & LPC1768 Kits, Windows based PC,
DB-9 connectors and serial cable
Operating System: Windows 7 / Windows XP
Learning Objectives: To get hands on experience of embedded C
programming of LPC2148 & LPC1768 and its interfacing with
different ICs/Peripherals.

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

TABLE OF CONTENTS
Sr. No.
1
1.1

Topic
Introduction
SCARM Installation

Department Of Electronics Engineering| AISSMSCOE,Pune

Page No.
4

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Introduction to LPC2148 & LPC1768 Programming

Embedded C
Embedded C is a set of language extensions for the C Programming language
by the C Standards committee to address commonality issues that exist between
C extensions for different embedded systems. Historically, embedded C
programming requires nonstandard extensions to the C language in order to
support exotic features such as fixed-point arithmetic, multiple distinct memory
banks, and basic I/O operations.
In 2008, the C Standards Committee extended the C language to address these
issues by providing a common standard for all implementations to adhere to. It
includes a number of features not available in normal C, such as, fixed-point
arithmetic, named address spaces, and basic I/O hardware addressing.
Embedded C uses most of the syntax and semantics of standard C, e.g., main()
function, variable definition, datatype declaration, conditional statements (if,
switch, case), loops (while, for), functions, arrays and strings, structures and
union, bit operations, macros, etc.

Advantages
It is small and reasonably simpler to learn, understand, program and
debug.
Compared to assembly language, C code written is more reliable and
scalable, more portable between different platforms.
C compilers are available for almost all embedded devices in use today,
and there is a large pool of experienced C programmers.
Unlike assembly, C has advantage of processor-independence and is not
specific to any particular microprocessor/microcontroller or any system.
This makes it convenient for a user to develop programs that can run on
most of the systems.
As C combines functionality of assembly language and features of high
level languages, C is treated as a middle-level computer language or
high level assembly language.
It is fairly efficient.
It supports access to I/O and provides ease of management of large
embedded projects.
Java also used in many embedded systems but Java programs require
Java Virtual Machine (JVM), which consume lot of resources. Hence it is
not used for smaller embedded devices.

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Difference between C and Embedded C
Though C and embedded C appear different and are used in different contexts,
they have more similarities than the differences. Most of the constructs are
same; the difference lies in their applications.
C is used for desktop computers, while embedded C is for
microcontroller based applications.
C takes more resources of a desktop PC like memory, OS, etc while
programming on desktop systems what embedded C cannot. Embedded C
has to use the limited resources (RAM, ROM, I/Os) on an embedded
processor. Thus, program code must fit into the available program
memory. If code exceeds the limit, the system is likely to crash.

Compilers for C (ANSI C) typically generate OS dependent executable


files. Embedded C requires compilers to create files to be downloaded to
the microcontrollers/microprocessors where it needs to run. Embedded
compilers give access to all resources which is not provided in compilers
for desktop computer applications.

1.

Embedded systems often have the real-time constraints, which is usually


not there with desktop computer applications.

Embedded systems often do not have a console, which is available in


case of desktop applications.

SPJ tools Installation Instructions:


1.1. SCARM Installation:
1.1.1. As a part of the SCARM software package, you should have received
a CD. Please insert it into the CD-ROM drive. Open SPJTools (CD
drive), open the folder SCARM and run the SETUP.EXE
1.1.2. If it shows any error then click Ignore.
1.1.3. SCARM Setup window will open, click NEXT.
1.1.4. Accept the software license agreement by clicking YES.
1.1.5. Choose destination location where you want to install the SCARM
and click NEXT.
1.1.6. Click NEXT button and installation will start.
1.1.7. Click FINISH button to complete the Installation.
1.1.8. Now connect the SCARM SPJ Lock to USB port of the computer.
1.1.9. A pop-up will show Found New Hardware
1.1.10. Found New Hardware Wizard window will be open. Select No, not
this time option and click on Next.
5

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


1.1.11. Now select Install from a list or specific location (Advanced) and
click Next.
1.1.12. Browse for the folder drv from C:\SCARM\drv and click Next.
1.1.13. Now Hardware Installation window will open, click Continue
Anyway.
1.1.14. After completion of installation, a message will come. The wizard
has finished installing the software for SPJ Lock, now click on
Finish.
1.1.15. Again you will see Found New Hardware window, therefore
repeat the same procedure from step no.9.
1.1.16. After this you can start using SCARM (Start > All Programs > SPJSCARM > SIDE_ARM).
1.1.17. However, we recommend going through this users manual before you
actually start using it.
SCARM is C Compiler for ARM. It includes an IDE and other tools like
Debugger, Visual Code Generator (VCG) and Terminal Emulation Utility
(SPJTerm).
About Project:
What is a project?
A project is a file in which SIDEARM stores all information related to an
application. E.g. it stores the name of C and/or Assembler source file, memory
size to be used and other options for compiler, assembler and linker.
Opening a project:
To open an existing project file, select Project / Open Project from the menu.
Creating a new project:
To create a new project, select Project / New Project from the menu.
Changing project settings:
To change the project settings (such as adding or removing C and/or
Assembler source file(s), changing memory settings etc.), select Project /
Settings from the menu.
2.1 Quick start to create assembly language applications:
1. Start the SIDE_ARM program (i.e. the Integrated Development
Environment) from start\Programs\SPJ-SCARM\SIDE_ARM.
2. From Project menu, select Close project (if any project is open).
6

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


3. From Project menu, select New Project. The Open dialog window will be
displayed. Select the desired path where you wish to create this new project.
(For example, C:\SPJ). CAUTION: The path and filename must not contain
space or other special characters such as tab, comma, semicolon etc. In the File
name field, type the name of the project, without any extension. For example,
you may type PROG1. Then click on the Open button.
4. The action in the previous step will display the Project Settings dialog
window. This dialog window has 3 different parts named Compiler Options,
Linker Options, and Source Files. Any of these 3 parts can be displayed
by clicking on the corresponding name near the top of this dialog window.
Currently, the Compiler Options will be automatically displayed. If the
target micro-controller (must be a member of ARM family) is known, you may
select the appropriate Manufacturer from the list; and then select the appropriate
micro-controller from the device list. If the target micro-controller is not known
or if you cannot find it in the list, then you may simply select Philips as the
manufacturer and LPC2148 as the micro-controller.
5. Click on Linker Options to display that part of the dialog window. In this
window, you will see a list of 8 Memory Banks, with names such as
Memory #1, Memory #2 and so on. In your target hardware, there may be
none or 1 or more number of contiguous memory blocks connected to the ARM
micro-controller. Check the appropriate number of memory banks to reflect the
targets memory blocks. For each checked memory bank, specify memory start
address (in Hexadecimal) and memory block size (in decimal). Size maybe
specified either in number of Kilobytes (KB) or Megabytes (MB). Some of the
memory blocks maybe read-only (e.g. flash or conventional EPROM).
Accordingly, you may check or uncheck the Read only box. Based on this
information about memory banks, the IDE will automatically create the Linker
Script. This auto-generated script is adequate for most users. However, if you
wish to use your own script file instead of this autogenerated script, you may
check the Use different linker script box and further click on the browse
button (marked ) and select appropriate linker script file.
6. Click on Source Files to display that part of the dialog window. This
window will indicate that IDE has automatically added 2 files in this new
project: PROG1.c and startup.asm. The startup.asm file is automatically
created by the IDE and is required for all assembly and C projects. To write
program in assembly language remove PROG1.c. To remove PROG1.c, click
on it and then click Remove File button. Now the project contains only
startup.asm, click OK button to create this new project. IDE will be opened
and it will show startup.asm file. To write new assembly language program go
7

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


to File option and select New File. Write the assembly language program in this
file. For example:
.global main
.p2align 2
.text
main:
-----------write program here ----------forever:
-----------write program here ----------b forever @ branch unconditionally to label
.end-main
7. To save this file go to File option and click on Save. Save this file at the
same location (C:\SPJ). Give the file name same as project name with .asm
extension means PROG1.asm and select All Files (*.*) in the Save as type
option. Now to add this PROG1.asm in the project go to Project >Settings >
Source files. Click on Add File button and select PROG1.asm. It will be
added in the project. Click on OK button. If you wish to add more files in this
project, then click on the Add file button, select the desired filename and then
click on Open button. Now the Project Settings dialog will indicate that
selected file has been added into the project. When all necessary files have been
added to the project, click OK button to create this new project.
8. From the Compile menu, select Build. This will invoke the assembler to
assemble the file PROG1.asm; and further (assuming no errors) invoke the
linker to create the .hex file. If there are any errors or warnings during the
process of assembling or linking, then those will be displayed in the output
window (below the editor window). If there are errors, then you may correct
those by making appropriate changes to the program; select Save from File
menu to save the changes and then again select Build from Compile menu.
Repeat this until there are no errors.
9. You may inspect contents of the folder where your project files reside. When
there are no errors and build has completed successfully and then you will see a
filename with same name as the project name and extension .HEX (in above
example, PROG1.hex). This is the file that you will need to use to program
your micro-controller.

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


2.2 Quick start to create C language applications:
1. Start the SIDE_ARM program (i.e. the Integrated Development
Environment) from start\Programs\SPJ-SCARM.
2. From Project menu, select Close project (if any project is open).
3. From Project menu, select New Project. The Open dialog window will be
displayed. Select the desired path where you wish to create this new project.
(For example, C:\SPJ). CAUTION: The path and filename must not contain
space or other special characters such as tab, comma, semicolon etc. In the File
name field, type the name of the project, without any extension. For example,
you may type PROG1. Then click on the Open button.
4. The action in the previous step will display the Project Settings dialog
window. This dialog window has 3 different parts named Compiler Options,
Linker Options, and Source Files. Any of these 3 parts can be displayed
by clicking on the corresponding name near the top of this dialog window.
Currently, the Compiler Options will be automatically displayed. If the
target micro-controller (must be a member of ARM family) is known, you may
select the appropriate
Manufacturer from the list; and then select the appropriate micro-controller
from the device list. If the target micro-controller is not known or if you cannot
find it in the list, then you may simply select Philips as the manufacturer and
LPC2148 as the micro-controller.
5. Click on Linker Options to display that part of the dialog window. In this
window, you will see a list of 8 Memory Banks, with names such as
Memory #1, Memory #2 and so on. In your target hardware, there may be
none or 1 or more number of contiguous memory blocks connected to the ARM
micro-controller. Check the appropriate number of memory banks to reflect the
targets memory blocks. For each checked memory bank, specify memory start
address (in Hexadecimal) and memory block size (in decimal). Size maybe
specified either in number of Kilobytes (KB) or Megabytes (MB). Some of the
memory blocks maybe read-only (e.g. flash or conventional EPROM).
Accordingly, you may check or uncheck the Read only box. Based on this
information about memory banks, the IDE will automatically create the Linker
Script. This auto-generated script is adequate for most users. However, if you
wish to use your own script file instead of this autogenerated script, you may
check the Use different linker script box and further click on the browse
button (marked ) and select appropriate linker script file.

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


6. Click on Source Files to display that part of the dialog window. This
window will indicate that IDE has automatically added 2 files in this new
project: PROG1.C and STARTUP.ASM. The STARTUP.ASM file is
automatically created by the IDE and is required for all C projects. Similarly,
the IDE has automatically created an empty C file (PROG1.C). If the file
PROG1.C already exists in the same path, then IDE would neither
create/overwrite it nor modify it; but it will anyway add it to the project
automatically. If you wish to add more files in this project, then click on the
Add file button, select the desired filename and then click on Open button.
Now the Project
Settings dialog will indicate that selected file has been added into the project.
When all necessary files have been added to the project, click OK button to
create this new project.
7. The PROG1.C file created by the IDE will be an empty file containing only
the frame of main function. You may write the desired program statements in
this file (or other files that you may have added to the project). When done,
select Save from File menu. If you have modified more than one source files,
then select Save All from File menu.
8. From the Compile menu, select Build. This will invoke the Compiler to
compile the file PROG1.C; and further (assuming no errors) invoke the linker to
create the .HEX file. If there are any errors or warnings during the process of
compiling, assembling or linking, then those will be displayed in the output
window (below the editor window). If there are errors, then you may correct
those by making appropriate changes to the program; select Save from File
menu to save the changes and then again select Build from Compile menu.
Repeat this until there are no errors.
9. You may inspect contents of the folder where your project files reside. When
there are no errors and build has completed successfully and then you will see a
filename with same name as the project name and extension .HEX (in above
example, PROG1.HEX). This is the file that you will need to use to program
your micro-controller.

10

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


3. Hardware Description
3.1 STK-2148:
Unpacking:
You will find following items in the package:
STK-2148 board
Serial communication cable (Straight 9-Pin)
Power adapter with cable
SPJETs CD-ROM
Power Supply Requirements:
The power adapter works with 230Volts AC. It produces approximately 9 Volts
DC, and the STK-2148 uses on-board regulators to provide 5 Volts and 3.3
Volts DC to all components on the board.
Connecting the system:
The serial communication cable supplied with the board should be used to
connect the board to a PC running Windows95/98/NT/ ME/2000/XP/Vista
Operating System. Connect one end of the serial cable to UART0 of STK-2148
board and other end to PCs serial port.
Powering ON:
After connecting the serial communication cable as described above, you may
insert the power adapter output jack into the on-board power socket. Plug the
power adapter into 230VAC mains outlet and turn it on. Now press on-board
power switch, power-on indication Green LED will turn on.
CAUTION: Please do not connect or disconnect the serial communication
cable while the board is powered ON. Doing so can damage the serial port of
the STK-2148 board and/or PC.
4. Connector Details, Jumper and Switch Settings
4.1 STK-2148 Block Diagram:
Below figure shows the locations of different components on the STK-2148
board.

11

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

12

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


4.2 Connector Details, DIP Switch, Push Button Switch Settings
DIP Switches Details:
S1:
Turn ON this switch to connect UART1 connector to UART1 lines (TxD1/P0.8
and RxD1/P0.9) of LPC2148.
S2:
Mode selection switch. The LPC21xx micro-controllers include on-chip flash
for storing user program and non-volatile data. The LPC2148 have 512KBytes
flash. This flash is In-System-Programmable (ISP). The LPC21xx microcontrollers have a built-in boot-load program. Upon power-on, this boot-load
program takes control; it passes control to the user program if pin P0.14 is
HIGH and some other conditions are satisfied. Please refer to the LPC21xx
data-sheet for further details.
On the STK-2148 board, the P0.14 pin is made available on this S3 switch.
Turn ON this switch to control the Mode (ISP mode or Run mode) by Flash
Magic.
S3:
Turn ON this switch to connect USB device connector to USB lines of
LPC2148.
S4.1:
Turn ON this switch to connect POT (R20) to ADC0.1/P0.28 of LPC2148.
S4.2:
Turn ON this switch to connect LM35 to ADC0.2/P0.29 of LPC2148.
S5:
Turn ON this switch to connect I2C peripherals (Seven Segments, RTC
(DS1307) and EEPROM (AT24C512)) to I2C lines (SCL0/P0.2 and
SDA0/P0.3) of LPC2148.
S6.1:
Turn ON this switch to connect Buzzer to P0.25 of LPC2148.
S6.2:
Turn ON this switch to connect DAC/TP7 to DACOut/P0.25 of LPC2148.

13

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


S6.3:
Turn ON this switch to connect switch SW25 to EINT0/P0.16 of LPC2148.
P0.16 is External Interrupt 0 pin of LPC2148.
S7:
Turn ON this switch to connect SPI EEPROM (AT25256) to SPI lines
(SCK0/P0.4, MISO0/P0.5, MOSI0/P0.6 and CS/P0.7) of LPC2148.
S11:
Turn ON this switch to connect Stepper Motor to P0.10, P0.11, P0.12 and P0.13
of LPC2148.
S12.1:
Turn ON this switch to connect Relay 1 to P0.18 of LPC2148.
S12.2:
Turn ON this switch to connect Relay 2 to P0.19 of LPC2148.
S13.1:
Turn ON this switch to enable 128x64 Graphics LCD.
S13.2:
Turn ON this switch to enable 8 LEDs connected to P0.10 (D9), P0.11 (D10),
P0.12 (D11), P0.13 (D12), P0.18 (D13), P0.19 (D14), P0.20 (D15) and P0.21
(D16) of LPC2148.
S14:
Turn ON this switch to enable RS485 communication protocol over LPC2148.
For RS485 communication MAX485 IC is used.
S14.1:
Turn ON this switch to connect DI of MAX485 to P0.8/TXD1 of LPC2148.
S14.2:
Turn ON this switch to connect RO of MAX485 to P0.9/RXD1 of LPC2148.
S14.3:
Turn ON this switch to connect DE of MAX485 to P0.25/GPIO of LPC2148.
4.3 Push-Button Switches Details:
When pressed, the switches are grounded. When Idle, they are pulled high.
Push-Button - Signal Name
14

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


RST/RESET- Reset to LPC2148
SW1 P1.16
SW2 P1.17
SW3 P1.18
SW4 P1.19
SW5 P1.20
SW6 P1.21
SW7 P1.22
SW8 P1.23
SW25 P0.16/ EINT0
SW9 to SW24: Matrix Keypad P1.16 to P1.23
4.4 LEDs and Buzzer Details:
All the LEDs are connected by common anode method. That means the positive
leg of each LED is connected to Vcc and negative leg to the port pins of the
microcontroller. A logic 0 on the port pin will make LED ON and logic 1 will
make it OFF.
LED Signal Name
D1/ P.ON +5V Power ON/OFF
D9 P0.10
D10 P0.11
D11 P0.12
D12 P0.13
D13 P0.18
D14 P0.19
D15 P0.20
D16 P0.21/PWM5
D21 SW25
D25 P0.7/PWM2
Buzzer P0.25
4.5 Connector Details:
UART0:
This is a DB9 female connector, used for RS232 serial communication with the
PC:
Pin 4 = RS232 DTR
Pin 5 = Ground
15

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Pin 7 = RS232 RTS
All other pins of J1/UART0 are unused.
UART1:
This is a DB9 female connector, used for RS232 serial communication with the
PC:
Pin 5 = Ground
Pin 7 = D+/A for RS485
Pin 8 = D-/B for RS485
16x2 LCD:
This is a 16 pin, single line connector, designed for connection to standard, text
LCD modules. Thepin/signal correspondence is designed to be matching with
that required by such LCD modules.
Pin 1 = GND
Pin 2 = +5V
Pin 3 = Vlcd
Pin 4 = P1.25 (Used as RS of LCD)
Pin 5 = GND
Pin 6 = P1.24 (Used as EN of LCD)
Pin 7 to 10 = No Connection/GND
Pin 11 = P0.15 (Used as D4 of LCD)
Pin 12 = P0.17 (Used as D5 of LCD)
Pin 13 = P0.22 (Used as D6 of LCD)
Pin 14 = P0.30 (Used as D7 of LCD)
Pin 15 = Back lighting
Pin 16 = GND
I2C Connector:
This standard 4 pin I2C connector provides support for interfacing of I2C based
peripherals to LPC21xx.
This connector is mounted on middle-bottom side of the board as shown in
figure1.
4 pin straight cable can be used to connect LPC21xx to the board having I2C
based peripheral devices.
The pin-out of I2C Connector is given below:
Pin Signal name
16

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


1 P0.2 (SCL0)
2 P0.3 (SDA0)
3 +5V
4 DGND
SPI Connector:
This standard 10 pin connector provides support for interfacing more SPI based
peripheral devices to LPC21xx. This connector is mounted on top side of the
board.
10 pin straight cable can be connected to this connector, while other end of the
cable can be connected to board having SPI based peripherals, respectively.
The pin-out of SPI Connector is given below:
Pin Signal name
1 P0.16
2 P0.23
3 P0.25
4 P0.31
5 P0.5 (MISO)
6 P0.6 (MOSI)
7 P0.7 (NCS)
8 P0.4 (SCKO)
9 +5V
10 GND
JTAG Connector:
This standard 20 pin JTAG connector provides debugging support for the
LPC21xx. This connector is mounted on top side of the board as shown in
figure1. JTAG cables like SJT-S or SJT-U can be connected to this connector,
while other end of the cable can be connected to PC COM port or USB port,
respectively.
Debugger software (like the debugger built into SCARM) allows JTAG based
debugging. It is also possible to use third party JTAG based emulators
/debuggers. The pin-out of JTAG Connector is given below:
Pin
1
3
5
7

Signal name
3.3V
P1.31/NTRST
P1.28/TDI
P1.30/TMS
17

2
4
6
8

Pin Signal name


3.3V
GND
GND
GND

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


9
11
13
15
17
19

P1.29/TCK
P1.26/RTCK
P1.27/TDO
NRST
GND
GND

10
14
18
20

GND
12
GND
GND
16
GND
GND
GND

J6:
This is 26 pin dual line headers. It brings out I/O and most of the pins of the
LPC21xx micro-controller.
Further, 5V and GND are also made available on these connectors. These
connectors are intended for use to connect external peripherals.
The pin/signal details of J6 are as below:
Pin
1
3
5
7
9
11
13
15
17
19
21
23
25

Signal name
P1.16
2
P1.18
4
P0.28
6
P0.30
8
P0.10
10
P0.12
12
P0.14
14
P0.16
16
P1.18
18
P1.25
20
P1.23
22
P1.21
24
+ 5V
26

Pin Signal name


P1.17
P1.19
P0.29
P0.31
P0.11
P0.13
P0.15
P0.17
P1.19
P1.24
P1.22
P1.20
GND

5. Downloading and Running User Programs


The LPC21xx micro-controllers include on-chip flash for storing user program
and non-volatile data.
LPC2148 on STK-2148 have 512KBytes flash. This flash is In-SystemProgrammable (ISP). Therefore it is possible to download user program into onchip flash of LPC2148, through serial port connected to PC. For doing so, a
certain position of S2 switch is required. S2 Switch should be continuously
ON.
18

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


This section describes how to use the software Flash Magic to download
program into LPC2148.
5.1 How to install Flash Magic:
The CD you have received with this board contains SCARM, C Compiler for
ARM. Install it. After installation go to folder C:\SCARM\Utilities. This folder
contains 5 zip files. Install Flash Magic from FlashMagic3.71.zip. Extract the
FlashMagic3.71.zip and then run FlashMagic.exe from the extracted files. (If
you have wrong version of Flash Magic already installed, then please uninstall
it first and then install new version).
5.2 Download and Run program using Flash Magic into LPC2148:
After installation of Flash Magic, open it.
In Flash Magic go to Options -> Advanced Options-> Communications.
Check High Speed and keep Maximum Baud Rate as 19200. Click on OK.
Again in Flash Magic go to Options -> Advanced Options-> Hardware
Config. Use DTR and RTS to control RST and P0.14 option should be
checked. Click on OK.
(After doing above mentioned settings, Flash Magic stores it means for the next
time just verify if these setting are proper or not. If they are proper then you can
directly follow below mentioned procedure)
1. Connect the J2/UART0 connector of STK-2148 board to COM1 or COM2
of a PC, using the serial communication cable (supplied with the board).
2. Keep S2 switch in ON position. (You can keep S2 switch continuously ON)
Switch ON power to the STK-2148.
3. Do proper settings in Flash Magic (COM Port: COM1 (if other choose it),
Baud Rate: 38400, Device: LPC2148, Interface: None (ISP), Enable Erase
blocks used by Hex File, Browse the file which you want to download) and
click on Start button.
4. Flash Magic will download the program. Wait till Finished comes.
5. After downloading Flash Magic automatically resets the STK-2148 board
and program executes. You can see output according to the program.
6. If again you want to Reset the board then press RST switch on SM2148
board. You can see output according to the program.
6. JTAG Cable for Debugging
6.1 Type:
SJT-S: Serial JTAG Cable.
19

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

6.2 Contents:
The JTAG Cable consists of following parts:
Dongle (a small box with connectors on both ends).
Cable.
The dongle consists of some electronic circuit for interfacing the JTAG port
of target processor to the host computer. The cable is a bunch of wires to
connect the dongle with the JTAG port of target.
6.3 Power Supply Requirements:
The JTAG cable draws power from the target board. Thus it does not require a
separate power source.
6.4 Connecting JTAG Cable:
SJT-S:
There is a DB9 female connector on one end of the dongle. This directly mates
with the PC COM port which has a DB9 male connector (or you can connect
yellow color serial cable, supplied with SJT-S or STK-2148 board, between
DB9 female connector on one end of the dongle and PC COM port which has
a DB9 male connector). The other end of the dongle has DB25 female
connector. There is a DB25 male connector on one end of the cable. These
DB25 female and DB25 male connectors are designed to mate with each other
directly. The other end of the cable has a 20-pin header. This should be
connected to the JTAG connector of the target board.
CAUTION:
The JTAG Cable must not be connected or dis-connected when power is
applied to the target board.
Turn off power to the target board, connect the JTAG Cable and then you may
turn on power to the target board.
Connecting the JTAG Cable with incorrect polarity / orientation may
permanently damage the STK- 2148 board and/or the JTAG Cable. It will also
make the warranty void for both the products.
6.5 Verifying correct cable connection:
When the JTAG Cable is correctly connected to PC as well as the target board,
it serves as a link between the JTAG port of target processor and the PC. This
link is used by SPJ - SCARM software
Tools (e.g. Debugger for ARM microcontrollers).
20

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


This software tool, Debugger will work correctly only when the JTAG Cable is
connected correctly.
For SJT-S:
There is a crude test to verify SJT-S JTAG Cable connection. You may please
follow these steps:
1. Connect JTAG Cable between PC COM port and JTAG connector on STK2148, as per instructions in this manual.
2. Turn ON power to the target board.
3. On the PC, run SPJTerminal software.
4. In the Port Settings, select appropriate COM port (to which the JTAG cable
is connected). Select 115200 baud, no parity, 8 bits per char, 1 stop bit and no
flow control.
5. Open the COM Port connection.
6. Type character V in the terminal window. i.e. send the character V to the
PC COM port.
7. If the JTAG Cable connection is correct, it will send version of JTAG cable.
As a result, you will see that version appearing in the terminal window. This
indicates that JTAG Cable connection is OK.
8. If you dont see any character in the terminal window, probably the JTAG
Cable is not connected appropriately.
6.6 How to Debug Program:
1. Connect SJT-S as mentioned above.
2. Open project in SIDEARM. Rebuild it.
3. Download the same code in the target board.
4. In SIDEARM go to Tools -> Debugger.
5. In Debugger go to Run -> Click on Not connected to target (click here to
connect).
6. Device ID starting from 0x4........ will be displayed and program will run.
7. To stop program go to Run -> Stop. Now you can insert break-point and say
Run.
8. You can use all the functions visible in Run option.
9. In variable watch window you can see only global variables.
10. If you have declared any global variables then find their addresses from
map file.
11. Insert these addresses in variable watch window and you can see global
variables also.

21

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

22

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Assignment 1

AIM: Interfacing LPC2148 to LCD


Apparatus: STK-2148 kit, PC.
Block Diagram:

Connections:
Keep S6.1 switch in ON position.
Keep S13.1 switch in ON position.
Keep S12 switch in ON position.

Procedure:
To Edit / Compile/ Generate Hex file.
To download and run this program.

Output:
You can see the message Welcome to AISSMSCOE on LCD. If required Reset
the board.
Conclusion:

23

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1.

LCD.C

/* LCD connections:
P1.25 P1.24 P0.30 P0.22 P0.17 P0.15
RS
EN
D7
D6
4 bit interface is used.

D5

*/
#include <Philips\LPC2148.h>
#include "LCD.h"
void SmallDelay (void)
{
int i;
for(i=0;i<100;i++);
}
void LcdCmd1 (unsigned char cmd)
{
// send command on on data lines (D4 to D7)
if (cmd & 0x01)
IO0SET = (1<<15);
else
IO0CLR = (1<<15);
if (cmd & 0x02)
IO0SET = (1<<17);
else
IO0CLR = (1<<17);
if (cmd & 0x04)
IO0SET = (1<<22);
else
IO0CLR = (1<<22);
if (cmd & 0x08)
IO0SET = (1<<30);
else
IO0CLR = (1<<30);
IO1CLR = 0x03000000
SmallDelay() ;

// CLEAR(0) RS and EN

IO1SET = 0x01000000

// SET(1) EN

SmallDelay() ;
24

Department Of Electronics Engineering| AISSMSCOE,Pune

D4

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


IO1CLR = 0x01000000

// CLEAR(0) EN

SmallDelay() ;
}
void LcdDat1 (unsigned char dat)
{
// send data on on data lines (D4 to D7)
if (dat & 0x01)
IO0SET = (1<<15);
else
IO0CLR = (1<<15);
if (dat & 0x02)
IO0SET = (1<<17);
else
IO0CLR = (1<<17);
if (dat & 0x04)
IO0SET = (1<<22);
else
IO0CLR = (1<<22);
if (dat & 0x08)
IO0SET = (1<<30);
else
IO0CLR = (1<<30);
IO1SET = 0x02000000

// SET(1) RS

// CLEAR(0) EN

// SET(1) EN

// CLEAR(0) EN

SmallDelay() ;
IO1CLR = 0x01000000
SmallDelay() ;
IO1SET = 0x01000000
SmallDelay() ;
IO1CLR = 0x01000000

SmallDelay() ;
}
void Delay250 (void)
{
int k,j ;
j =200 ;
for(k = 0 ; k < 100 ; k ++)
{
25

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


j-- ;
}
}
void DelayMs (int n)
{
int k ;
for(k = 0 ; k < n ; k ++)
{
Delay250() ;
Delay250() ;
}
}
void LcdCmd (unsigned char cmd)
{
LcdCmd1(cmd >> 4) ;
LcdCmd1(cmd) ;
Delay250() ;
Delay250() ;
}
void LcdDat (unsigned char dat)
{
LcdDat1(dat >> 4) ;
LcdDat1(dat) ;
Delay250() ;
Delay250() ;
}
void LcdInit (void)
{
IO1DIR = 0x03000000 ;
P1.25(RS) as Output
IO1CLR = 0x03000000 ;
P1.25(RS)

// Configure P1.24(EN) and


// CLEAR(0) P1.24(EN) and

IO0DIR = 0x40428000 ;
// Configure P0.15(D4),
P0.17(D5), P0.22(D6) and P0.30(D7) as Output
IO0CLR = 0x40428000 ;
// CLEAR(0) P0.15(D4),
P0.17(D5), P0.22(D6) and P0.30(D7)
DelayMs(6) ;
LcdCmd1(0x03) ;
DelayMs(6) ;
LcdCmd1(0x03) ;
Delay250() ;
LcdCmd1(0x03) ;
Delay250() ;
LcdCmd1(0x02) ;
Delay250() ;
LcdCmd(0x28) ;
LcdCmd(0x08) ;
LcdCmd(0x0c) ;
26

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


LcdCmd(0x06) ;
}
void DisplayRow (int row, char *str)
{
/*
pass pointer to 16 character string
displayes the message on line1 or line2 of LCD, depending on
whether row is 1 or 2.
*/
int k ;
if (row == 1)
LcdCmd(0x80) ;
else
LcdCmd(0xc0) ;
for(k = 0 ; k < 16 ; k ++)
{
if (str[k])
LcdDat(str[k]) ;
else
break ;
}
while(k < 16)
{
LcdDat(' ') ;
k ++ ;
}
}

27

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)

2.

HELLOLCD.C

#include <Philips\LPC2148.h>
#include "lcd.h"
void main ()
{
LcdInit();
LCD

// Initialize

DisplayRow (1,"
DisplayRow (2,"

WELCOME TO
AISSMS COE

");
");

while(1)
{}
}

3.

LCD.H

#ifndef LCD_H
#define LCD_H
void LcdInit (void);
void DisplayRow (int row, char *str);
#endif /* LCH_H */

28

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Assignment 2
AIM: Interfacing LPC2148 for internal ADC on interrupt basis (ADC 0, Channel
1, P0.28).
Connections:
To give analog input from Potentiometer R20 present in Analog Input region
on STK-2148 keep S4.1 in ON position. To give external analog input, keep S4.1
in OFF position and connect external analog input to pin 1 of AIN_EXT
connector. Analog input range is from 0 to 3.3V.
Block Diagram:

Procedure:
To Edit / Compile/ Generate Hex file.
To download and run this program.

Output:
You can see the digital values on the LCD. If required reset the board.
Note: Keep S4.1 switch in OFF position, after execution of program.

Conclusion:

29

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1.

LCD.C

/* LCD connections:
P1.25 P1.24 P0.30 P0.22 P0.17 P0.15
RS
EN
D7
D6
4 bit interface is used.

D5

*/
#include <Philips\LPC2148.h>
#include "LCD.h"
void SmallDelay (void)
{
int i;
for(i=0;i<100;i++);
}
void LcdCmd1 (unsigned char cmd)
{
// send command on on data lines (D4 to D7)
if (cmd & 0x01)
IO0SET = (1<<15);
else
IO0CLR = (1<<15);
if (cmd & 0x02)
IO0SET = (1<<17);
else
IO0CLR = (1<<17);
if (cmd & 0x04)
IO0SET = (1<<22);
else
IO0CLR = (1<<22);
if (cmd & 0x08)
IO0SET = (1<<30);
else
IO0CLR = (1<<30);
IO1CLR = 0x03000000
SmallDelay() ;

// CLEAR(0) RS and EN

IO1SET = 0x01000000

// SET(1) EN

SmallDelay() ;
30

Department Of Electronics Engineering| AISSMSCOE,Pune

D4

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


IO1CLR = 0x01000000

// CLEAR(0) EN

SmallDelay() ;
}
void LcdDat1 (unsigned char dat)
{
// send data on on data lines (D4 to D7)
if (dat & 0x01)
IO0SET = (1<<15);
else
IO0CLR = (1<<15);
if (dat & 0x02)
IO0SET = (1<<17);
else
IO0CLR = (1<<17);
if (dat & 0x04)
IO0SET = (1<<22);
else
IO0CLR = (1<<22);
if (dat & 0x08)
IO0SET = (1<<30);
else
IO0CLR = (1<<30);
IO1SET = 0x02000000

// SET(1) RS

// CLEAR(0) EN

// SET(1) EN

// CLEAR(0) EN

SmallDelay() ;
IO1CLR = 0x01000000
SmallDelay() ;
IO1SET = 0x01000000
SmallDelay() ;
IO1CLR = 0x01000000

SmallDelay() ;
}
void Delay250 (void)
{
int k,j ;
j =200 ;
for(k = 0 ; k < 100 ; k ++)
{
31

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


j-- ;
}
}
void DelayMs (int n)
{
int k ;
for(k = 0 ; k < n ; k ++)
{
Delay250() ;
Delay250() ;
}
}
void LcdCmd (unsigned char cmd)
{
LcdCmd1(cmd >> 4) ;
LcdCmd1(cmd) ;
Delay250() ;
Delay250() ;
}
void LcdDat (unsigned char dat)
{
LcdDat1(dat >> 4) ;
LcdDat1(dat) ;
Delay250() ;
Delay250() ;
}
void LcdInit (void)
{
IO1DIR = 0x03000000 ;
P1.25(RS) as Output
IO1CLR = 0x03000000 ;
P1.25(RS)

// Configure P1.24(EN) and


// CLEAR(0) P1.24(EN) and

IO0DIR = 0x40428000 ;
// Configure P0.15(D4),
P0.17(D5), P0.22(D6) and P0.30(D7) as Output
IO0CLR = 0x40428000 ;
// CLEAR(0) P0.15(D4),
P0.17(D5), P0.22(D6) and P0.30(D7)
DelayMs(6) ;
LcdCmd1(0x03) ;
DelayMs(6) ;
LcdCmd1(0x03) ;
Delay250() ;
LcdCmd1(0x03) ;
Delay250() ;
LcdCmd1(0x02) ;
Delay250() ;
LcdCmd(0x28) ;
LcdCmd(0x08) ;
LcdCmd(0x0c) ;
32

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


LcdCmd(0x06) ;
}
void DisplayRow (int row, char *str)
{
/*
pass pointer to 16 character string
displayes the message on line1 or line2 of LCD, depending on
whether row is 1 or 2.
*/
int k ;
if (row == 1)
LcdCmd(0x80) ;
else
LcdCmd(0xc0) ;
for(k = 0 ; k < 16 ; k ++)
{
if (str[k])
LcdDat(str[k]) ;
else
break ;
}
while(k < 16)
{
LcdDat(' ') ;
k ++ ;
}
}

2.

ADC.C

/*******************************************************************
********************
# Project Code : MA-Exp
#
# TESTADC C file
#
# ------# History
# ------# Date
|Release|Author| Changes
# DD-MM-YYYY |
|
|
# -----------------------------------------------------------------------------------# 08.03.2007 | 0.1 | NSG | Initial Version.
#
|
|
|
#
|
|
|
#
|
|
|
********************************************************************
********************/
#include <Philips\LPC2148.h>
33

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#include <stdio.h>
#include "LCD.h"
char adcreading[16] ;
void ADC_Init (void)
{
PINSEL1 = 0x01000000 ;
P0.28,AD0.1
}

//

unsigned int ADC_GetAdcReading ()


{
unsigned int adcdata;
ADCR = 0x01200302 ;
//
Select AD0.1, Select clock for ADC, Start of conversion,
while(!((adcdata = ADGDR) & 0x80000000))
// Check end
of conversion (Done bit) and read result
{
}
return((adcdata >> 6) & 0x3ff) ;
// Return 10
bit result
}
int main (void)
{
unsigned int delay, adc;
ADC_Init() ;
LcdInit();
DisplayRow(1,"ADC Test");
while(1)
{
adc = ADC_GetAdcReading();
// Read
AD0.1 reading
sprintf(adcreading,"ADC0 CH1= 0x%03X",adc); // Convert
result into ASCII to display it on LCD
DisplayRow(2,adcreading) ;
//
Display result on LCD
for(delay=0;delay<60000;delay++);
}
}

34

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 3

AIM: Interfacing SD card to LPC2148

BLOCK DIAGRAM:

CONNECTIONS:

PROCEDURE:
To Edit / Compile/ Generate Hex file.
To download and run this program.

OUTPUT:

CONCLUSION:

35

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


PROGRAM:

36

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 4
AIM: Interfacing EEPROM to LPC2148 using I2C protocol
BLOCK DIAGRAM:

CONNECTIONS:
Keep S5 switch (present in I2C Peripherals region) in ON position.

PROCEDURE:
To Edit / Compile/ Generate Hex file.
To download and run this program.

OUTPUT:
You can see output on SPJTerminal. Therefore Open SPJTerminal. Go to Port ->
Settings. Do proper settings (Baud Rate: 19200, Data Bits: 8, Stop Bits: 1, Echo: Off,
Parity: None, Com Port: Com 1 (if other choose it)). Click on OK. Go to Port ->
Open. If required Reset the STK-2148 board. First data will be written in EEPROM
and then it will be read from EEPROM. The same data (0, 1, 2 and 3) will be
displayed on SPJTerminal. It will transmit the message "Hello world!.
Note: Keep S5 switch in OFF position, after execution of program.

CONCLUSION:

37

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


PROGRAM:
1. I2C.C
#include
#include
#include
#include

<Philips\LPC2138.h>
<Stdio.h>
"I2C.h"
"TIMER.h"

/***************************************************
Contains all EEPROM related functions.
Writing to and reading from the EEPROM fuctions.
All the user data, settings and logged data
will goes into EEPROM.
I2C0 is used for interfacing.
****************************************************
*/
/*
Initialises the I2C protocol and port pins.
*/
void I2C_Init (void)
{
// Power on I2C0 peripheral
PCONP |= 0x00000080;
// Define port pin as SDA and SCL
PINSEL0
|= 0x00000050 ;
I2C0CONCLR = 0x6C;
I2C0CONSET = 0x40;

// clear all I2C config bits


// set I2EN

// I2C Clock Duty Cycle (high and low)


I2C0SCLH
=
PERIFERAL_OPERATING_FREQUENCY_IN_HZ/(2*EEPROM_OPERATING_FREQUENCY_IN_HZ)
;
I2C0SCLL
=
PERIFERAL_OPERATING_FREQUENCY_IN_HZ/(2*EEPROM_OPERATING_FREQUENCY_IN_HZ)
;
}
/*
Waits until given status occured.
Return: True on status occured and
False on time out
*/
unsigned char I2C_WaitStatus (unsigned char u8status)
{
TIMER0_RESET();
TIMER0_ENABLE();
while (T0TC < EEPROM_WAIT_TIME_OUT)
38

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


{
if (I2C0CONSET & 8) // poll SI bit
{
if (I2C0STAT == u8status)
{
TIMER0_DISABLE();
return TRUE;
}
}
}
TIMER0_DISABLE();
return FALSE;
}
/*
Reads data from EEPROM.
Return: True on valid data and
False on time out or any error with device
*/
unsigned char I2C_ReadFromEEPROM (unsigned int u32startAddr, unsigned
char *u8ptr2arr, unsigned int u32len)
{
unsigned int
u32i;
// Check for upper limit
if (u32startAddr + u32len > EEPROM_SIZE)
return FALSE;
for (u32i=0;u32i<u32len;u32i++)
{
I2C0CONSET = 0x20;
// Start set
if (!I2C_WaitStatus(0x08))
// 0x08: ready for device
address
return FALSE;
I2C0DAT
= EEPROM_DEVADDR;// addr[0]=0 means I2C write
I2C0CONCLR = 0x2C;
// clear all except I2EN
if (!I2C_WaitStatus(0x18))
// 0x18: ready for data byte
return FALSE;
// Transmit start address - Dummy byte write
I2C0DAT
= (u32startAddr & 0x000000FF) ;
#ifndef EEPROM_24C02
I2C0CONCLR = 0x2C;
// clear all except I2EN
if (!I2C_WaitStatus(0x28))
// 0x28: ACK has been received
return FALSE;
I2C0CONCLR = 0x08;
// clear SI flag
I2C0DAT
= ((u32startAddr & 0x0000FF00)>>8) &0xFF;
#endif
I2C0CONCLR = 0x2C;
// clear all except I2EN
if (!I2C_WaitStatus(0x28))
// 0x28: ACK has been received
return FALSE;
I2C0CONCLR = 0x08;
// clear SI flag
I2C0CONSET = 0x10;
// generate stop condition

39

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// Read data - Sequential mode.
I2C0CONSET = 0x20;
if (!I2C_WaitStatus(0x08))

// Start set
// 0x08: ready for device

address
return FALSE;
I2C0DAT
= EEPROM_DEVADDR|0x01;// addr[0]=1 means I2C read
I2C0CONCLR = 0x28;
// clear all except I2EN and AA
if (!I2C_WaitStatus(0x40))
// 0x40: ready for data byte
return FALSE;
I2C0CONCLR = 0x2C;
if (!I2C_WaitStatus(0x58))
return ACK
return FALSE;

// clear all except I2EN


// 0x58: data byte received

u8ptr2arr[u32i] = (unsigned char)I2C0DAT ;


u32startAddr++;
I2C0CONSET = 0x10;
// generate stop condition
I2C0CONCLR = 0x2C;
}
return TRUE;
}
/*
Writes data to EEPROM.
Return: True on successful write and
False on time out or any error with device
*/
unsigned char I2C_WriteToEEPROM (unsigned int u32startAddr, unsigned
char *u8ptr2arr, unsigned int u32len)
{
unsigned int
u32i,u32j;
// Check for upper limit
if (u32startAddr + u32len > EEPROM_SIZE)
return FALSE;
// write data byte wise
for (u32i = 0; u32i < u32len; u32i++)
{
I2C0CONSET = 0x20;
// Start set
if (!I2C_WaitStatus(0x08))
// 0x08: ready for device
address
return FALSE;
I2C0DAT
= EEPROM_DEVADDR;// addr[0]=0 means I2C write
I2C0CONCLR = 0x2C;
// clear all except I2EN
if (!I2C_WaitStatus(0x18))
// 0x18: ready for data byte
return FALSE;
// Transmit start address
40

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


I2C0DAT
= (u32startAddr & 0x000000FF);
#ifndef EEPROM_24C02
I2C0CONCLR = 0x2C;
// clear all except I2EN
if (!I2C_WaitStatus(0x28))
// 0x28: ACK has been received
return FALSE;
//I2C0CONCLR
I2C0DAT

= 0x08;
// clear SI flag
= ((u32startAddr & 0x0000FF00)>>8) &0xFF;

#endif
I2C0CONCLR = 0x2C;
if (!I2C_WaitStatus(0x28))
return FALSE;
I2C0DAT

// clear all except I2EN


// 0x28: ACK has been received

= (u8ptr2arr[u32i])&0x000000FF;

u32startAddr++;
I2C0CONCLR = 0x2C;
if (!I2C_WaitStatus(0x28))
return FALSE;
I2C0CONSET = 0x10;
I2C0CONCLR = 0x2C;

// clear all except I2EN


// 0x28: ACK has been received

// generate stop condition

// Poll for write done


for (u32j=20;u32j>0;u32j--)
{
I2C0CONSET = 0x20;
// Start set
if (!I2C_WaitStatus(0x08)) // 0x08: ready for device
address
return FALSE;
I2C0DAT

= EEPROM_DEVADDR;// addr[0]=0 means I2C

write
I2C0CONCLR = 0x2C;
if (I2C_WaitStatus(0x18))
break;
else
{
I2C0CONCLR = 0x2C;
I2C0CONSET = 0x10;
I2C0CONCLR = 0x2C;
}
}
I2C0CONSET = 0x10;
I2C0CONCLR = 0x2C;

// clear all except I2EN


// 0x18: ready for data byte

// generate stop condition

// generate stop condition

}
return TRUE;
}

41

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


2. I2C.H
#ifndef
#define
#ifndef
#define
#endif
#ifndef
#define
#endif
#ifndef
#define
#endif

I2C_H
I2C_H
NULL
NULL

(0)

FALSE
FALSE

(0)

TRUE
TRUE

(1)

/* Settings */
#define
PERIFERAL_OPERATING_FREQUENCY_IN_HZ
12000000
#define
EEPROM_OPERATING_FREQUENCY_IN_HZ 50000
#define EEPROM_DEVADDR
0xA0
#define
EEPROM_24C512
1
// EEPROM IC used
#define
EEPROM_SIZE
0xFFFF
// Size
#define
EEPROM_WAIT_TIME_OUT
5000 // 1msec
//EEPROM_24C02
//EEPROM_24C04
//EEPROM_24C08
//EEPROM_24C16
//EEPROM_24C32
//EEPROM_24C64
//EEPROM_24C128
//EEPROM_24C256
//EEPROM_24C512

size
size
size
size
size
size
size
size
size

0x0000FF
0x0001FF
0x0003FF
0x0007FF
0x000FFF
0x001FFF
0x003FFF
0x007FFF
0x00FFFF

/* Function Definations */
extern
void I2C_Init (void);
extern
unsigned char
I2C_WaitStatus (unsigned char u8status);
extern
unsigned char
I2C_WriteToEEPROM (unsigned int
u32startAddr, unsigned char *u8ptr2arr, unsigned int u32len);
extern
unsigned char
I2C_ReadFromEEPROM (unsigned int
u32startAddr, unsigned char *u8ptr2arr, unsigned int u32len);
#endif //I2C_H

3. TIMER.C
/*******************************************************************
********************
# Project Code : MA-Exp
#
# TIMER C file
#
# ------# History
# ------# Date
|Release|Author| Changes
42

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


# DD-MM-YYYY |
|
|
# -----------------------------------------------------------------------------------# 08.03.2007 | 0.1 | NSG | Initial Version.
#
|
|
|
#
|
|
|
#
|
|
|
********************************************************************
********************/
#include <Philips\LPC2148.h>
#include "Timer.h"
/**************************************************
Timer0 is used for delay in micro sec
Timer1 is used for time out delay
Timer is initialized to simply count at a specified
frequency(Configuration.h).
Count can be read from register TC.
***************************************************
*/
/*
Initialises the timers
*/
void TIMER_Init (void)
{
// Power ON timer peripheral
PCONP |= 0x00000006;
// TPC: Timer Prescaler counter
// the counter is incremented once every TPC+1 cycles of PCLK
T0PR = PRESCALER0;
//T1PR
= PRESCALER1;
// TCR: Timer Control Register
// 2: reset counters (both timer and prescaler)
// 1: enable counting
T0TCR=2;
//T1TCR=2;
}
/*
waits for next tick in timer
*/
void TIMER_WaitForNextTick (void)
{
unsigned int start=T0TC;

43

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


while (T0TC==start) {}
changes, then leave
}

// wait until timer counter

4. TIMER.H
/*
Timer.h
*/
#ifndef TIMER_H
#define TIMER_H
/* Prescaler */
#define PERIFERAL_OPERATING_FREQUENCY_IN_HZ 12000000
#define DESIRED_COUNT_FREQ0
1000000

//1MHz

#define PRESCALER0
((PERIFERAL_OPERATING_FREQUENCY_IN_HZ/DESIRED_COUNT_FREQ0)-1)
//#define PRESCALER1
((PERIFERAL_OPERATING_FREQUENCY_IN_HZ/DESIRED_COUNT_FREQ1)-1)
#define
#define
#define

TIMER0_RESET()
TIMER0_ENABLE()
TIMER0_DISABLE()

T0TCR=2
T0TCR=1
T0TCR=0

/* Function declrations */
extern void TIMER_Init (void);
extern void TIMER_WaitForNextTick (void);
#endif /* TIMER_H */

5. MAIN.C
#include
#include
#include
#include
#include

<Philips\LPC2148.h>
<Stdio.h>
"UART0.h"
"I2C.h"
"TIMER.h"

/***************************************************
Main function.
****************************************************
*/
unsigned
unsigned
unsigned
unsigned

44

char
char
char
char

*MAIN_u8buffer1;
MAIN_u8buffer2[20] ;
MAIN_u8temp = 0;
MAIN_u8temp12[2][2]={0,1,2,3};

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


void main(void)
{
PINSEL0 |= 0x00000005 ;
UART0_Init();
I2C_Init();
TIMER_Init();
MAIN_u8temp=MAIN_u8temp12[0][0];
MAIN_u8buffer1 = (unsigned char*)MAIN_u8temp12;
while(1)
{
if (!I2C_WriteToEEPROM(0, MAIN_u8buffer1, 4))
printf("\nMemory write error..");
if (!I2C_ReadFromEEPROM(0, MAIN_u8buffer2, 4))
printf("\nMemory Read error..");
//

printf("\n%s",*MAIN_u8buffer2);
printf("\n%x",MAIN_u8buffer2[0]);
printf("\n%x",MAIN_u8buffer2[1]);
printf("\n%x",MAIN_u8buffer2[2]);
printf("\n%x",MAIN_u8buffer2[3]);
while(1);

}
}

45

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 5

AIM: Interfacing LPC1768 to Seven Segment / RGB LED

CONNECTIONS:
Connect the power supply to board i.e.9V & 500MA.
Connect the one terminal i.e. male connector to board at UART0 & other
terminal to our PC.

PROCEDURE:
To Edit / Compile/ Generate Hex file.
To download and run this program.

OUTPUT:
Seven Segment Display starts displaying from 0 to 9 nos.

CONCLUSION:

46

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1. SevenSeg.c
/*******************************************************************
********************
# Project Code : MA-Exp
#
# MAIN C file
# ------# History
# ------# Date
|Release|Author| Changes
# DD-MM-YYYY |
|
|
# -----------------------------------------------------------------------------------#
| 0.1 | NSG | Initial Version.
#
|
|
|
#
|
|
|
#
|
|
|
********************************************************************
********************/
#include "LPC17xx.h"
#include <Stdio.h>
#include "sevenseg.h"
/*
Initialises the I2C protocol and port pins.
*/
void I2C_Init (void)
{
// Power on I2C1 peripheral
PCONP |= 0x00080000;
// Define port pin as SDA and SCL
PINSEL0
|= 0x0000000F ;
I2C1CONCLR = 0x6C;
I2C1CONSET = 0x40;

// clear all I2C config bits


// set I2EN

// I2C Clock Duty Cycle (high and low), Bit freq.= 100KHz
I2C1SCLH
= 60;
I2C1SCLL
= 60;
}
/*
Waits until given status occured.
Return:
True on status occured and
False on time out
*/
/***************************************************
Main function.
****************************************************
47

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


*/
void SevenSeg(unsigned char dis1, unsigned char dis2);
void SevenSeg(unsigned char dis1, unsigned char dis2)
{
unsigned int i;
I2C1CONSET = 0x20;

// Start set

I2C1CONCLR = 0x2C;
// clear all except I2EN
I2C1DAT
= I2CEXPANDER_ADDR;// addr[0]=0 means
I2C write
for(i=0;i<300;i++);
I2C1CONCLR = 0x2C;

// clear all except I2EN

I2C1DAT
= dis1 ;
for(i=0;i<300;i++);
I2C1CONCLR = 0x2C;

// Data on DIS1
// clear all except I2EN

I2C1DAT
= dis2 ;
for(i=0;i<300;i++);
I2C1CONCLR = 0x2C;

// Data on DIS2
// clear all except I2EN

I2C1CONSET = 0x10;

// generate stop

condition
for(i=0;i<300;i++);
I2C1CONCLR = 0x2C;
}
void SmallDelay()
{
unsigned int i,j ;
for( i = 0 ; i < 3000000 ; i++)
{
j++ ;
j--;
}
}
void main(void)
{
TargetResetInit();
I2C_Init();
while(1)
{
SevenSeg(DISPLAY_0,
SmallDelay();
SevenSeg(DISPLAY_2,
SmallDelay();
SevenSeg(DISPLAY_4,
SmallDelay();
SevenSeg(DISPLAY_6,
SmallDelay();
SevenSeg(DISPLAY_8,
48

DISPLAY_1);
DISPLAY_3);
DISPLAY_5);
DISPLAY_7);
DISPLAY_9);

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


SmallDelay();
SevenSeg(DISPLAY_A, DISPLAY_B);
SmallDelay();
SevenSeg(DISPLAY_C, DISPLAY_D);
SmallDelay();
}
}

2. SevenSeg.h
#ifndef SEVENSEG_H
#define SEVENSEG_H
void I2C_Init (void);
#define I2CEXPANDER_ADDR 0x40
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

DISPLAY_0
DISPLAY_1
DISPLAY_2
DISPLAY_3
DISPLAY_4
DISPLAY_5
DISPLAY_6
DISPLAY_7
DISPLAY_8
DISPLAY_9
DISPLAY_A
DISPLAY_B
DISPLAY_C
DISPLAY_D
DISPLAY_E
DISPLAY_F

0xC0
0xf9
0xA4
0xB0
0x99
0x92
0x82
0xf8
0x80
0x90
0xA0
0x83
0xC6
0xA1
0x84
0x8E

#endif /* SEVENSEG_H*/

49

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 6
AIM: Generation of PWM signal for motor control using LPC1768

CONNECTIONS:
Connect the power supply to board i.e.9V & 500MA.
Connect the one terminal i.e. male connector to board at UART0 & other
terminal to our PC.
Connect the Board to STWS-DCM_V1.0 with 10-Pin Relimate Connector.
Switch Position
SW3.1 ON
SW3.2 ON
SW5.1 ON
SW5.2 ON
PROCEDURE:
To Edit / Compile/ Generate Hex file.
To download and run this program.

OUTPUT:
DC Motor speed varies continuously.

CONCLUSION:

50

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1. PLL.C
/*
====================================================================
====================================
Name
: PLL.c
Description : This file contains the functions Related PLL Setup
====================================================================
====================================
*/
#include "LPC17xx.h"
#include "PLL.h"
/*
* PLL Frequency Calculation
*
*
Parameter Description
*
FIN
the frequency of PLLCLKIN from the Clock
Source Selection Multiplexer.
FCCO
the frequency of the PLLCLK (output of the PLL
Current Controlled Oscillator)
N
PLL0 Pre-divider value from the NSEL0 bits in
the PLL0CFG register (PLL0CFG NSEL0 field + 1).
N is an integer from 1 through 32.
M
PLL0 Multiplier value from the MSEL0 bits in
the PLL0CFG register (PLL0CFG MSEL0 field + 1).
Not all potential values are supported. See
below.
The PLL0 output frequency (when PLL0 is both active and
connected) is given by:
FCCO= (2 M FIN) / N
PLL inputs and settings must meet the following:
FIN is in the range of 32 kHz to 50 MHz.
FCCO is in the range of 275 MHz to 550 MHz.
The equation can be solved for other PLL parameters:
M
= (FCCO N) / (2 FIN)
N
= (2 M FIN) / FCCO
FIN = (FCCO N) / (2 M)
Allowed values for M:
At higher oscillator frequencies, in the MHz range, values of
M from 6 through 512 are
allowed. This supports the entire useful range of both the
main oscillator and the IRC.
* */
/*
* Procedure for determining PLL0 settings
51

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


*
PLL0 parameter determination can be simplified by using a
spreadsheet available from
NXP. To determine PLL0 parameters by hand, the following
general procedure may be
used:
1.
Determine if the application requires use of the USB
interface, and whether it will be
clocked from PLL0. The USB requires a 50% duty cycle
clock of 48 MHz within a very
small tolerance, which means that FCCOmust be an even
integer multiple of 48 MHz
(i.e. an integer multiple of 96 MHz), within a very small
tolerance.
2. Choose the desired processor operating frequency (CCLK).
This may be based on
processor throughput requirements, need to support a
specific set of UART baud
rates, etc. Bear in mind that peripheral devices may be
running from a lower clock
frequency than that of the processor.Find a value for
FCCOthat is close to a
multiple of the desired CCLK frequency, bearing in mind
the requirement for USB
support in [1] above, and that lower values of FCCOresult
in lower power dissipation.
3. Choose a value for the PLL input frequency (FIN). This can
be a clock obtained from
the main oscillator, the RTC oscillator, or the on-chip
RC oscillator. For USB support,
the main oscillator should be used. Bear in mind that if
PLL1 rather than PLL0 is used
to clock the USB subsystem, this affects the choice of
the mainoscillator frequency.
4. Calculate values for M and N to produce a sufficiently
accurate FCCOfrequency. The
desired M value -1 will be written to the MSEL0 field in
PLL0CFG. The desired N value-1
will be written to the NSEL0 field in PLL0CFG.
In general, it is better to use a smaller value for N, to
reduce the level of multiplication that
must be accomplished by the CCO.
*
* */
void ConfigureClock()
{
/* *****************************************************************
* Inputs : NA
* Output :
NA
* Description:
* This function sets the operating frequency of the MCU to 120MHz
* which is the highest operating frequency MCU can be operated
*
52

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


* Peripheral clock for all the peripheral is selected as system
clock
*
*****************************************************************/
/*PLLCON description
* bit0 =>
PLLE0 PLL0 Enable. When one, and after a valid
PLL0 feed, this bit will activate
PLL0 and allow it to lock to the requested
frequency.
* bit1 => PLLC0 PLL0 Connect. Setting PLLC0 to one after PLL0
has been enabled and locked, then followed by a valid PLL0 feed
sequence causes PLL0 to become the clock source for the CPU, AHB
peripherals, and used to derive the clocks for APB peripherals. The
PLL0 output may potentially be used to clock the USB subsystem if
the frequency is 48 MHz
* bit 2:31 Reserved
*
* PLL0 Modes
* PLLC0 PLLE0
PLL Function
0
0
PLL0 is turned off and disconnected.
PLL0 outputs the unmodified clock input.
0
1
PLL0 is active, but not yet connected.
PLL0 can be connected after PLOCK0 is
asserted.
1
0
Same as 00 combination. This prevents
the possibility of PLL0 being connected
without also being enabled.
1
1
PLL0 is active and has been connected as the
system clock source.
* */
/*
* PLLSTAT Description
* bits14:0 => MSEL0 Read-back for the PLL0 Multiplier value.
This is the value currently
used by PLL0, and is one less than the
actual multiplier.
bit15 to reserved bits.

Reserved, user software should not write ones


The value read from a reserved bit is

not defined.
bits23:16=> NSEL0 Read-back for the PLL0 Pre-Divider
value. This is the value
currently used by PLL0, and is one less
than the actual divider.
bit24 =>
PLLE0_STAT Read-back for the PLL0 Enable bit.
This bit reflects the state of the

53

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


PLEC0 bit in PLL0CON after a valid PLL0
feed.
When one, PLL0 is currently enabled.
When zero, PLL0 is turned
off. This bit is automatically cleared
when Power-down mode is
entered.
bit25 =>
PLLC0_STAT Read-back for the PLL0 Connect bit.
This bit reflects the state of
the PLLC0 bit in PLL0CON after a valid
PLL0 feed.
When PLLC0 and PLLE0 are both one, PLL0
is connected as the
clock source for the CPU. When either
PLLC0 or PLLE0 is zero,
PLL0 is bypassed. This bit is
automatically cleared when
Power-down mode is entered.
bit26 =>
PLOCK0 Reflects the PLL0 Lock status. When
zero, PLL0 is not locked.
When one, PLL0 is locked onto the
requested frequency.
bits27:31

Reserved

* */
/*IF OUTPUT OF PLL IS ALREADY CONNECTED TO ADV PERIPHERAL BUS
(APB) THEN DISCONNECT PLL*/
if(LPC_SC->PLL0STAT & (1<<25)) // CHECK PLLC0 BIT IN PLL0CON
{
LPC_SC->PLL0CON
= 1;
LPC_SC->PLL0FEED = 0XAA;
LPC_SC->PLL0FEED = 0X55;
}
/*DISABLE PLL*/
LPC_SC->PLL0CON
= 0;
LPC_SC->PLL0FEED = 0XAA;
LPC_SC->PLL0FEED = 0X55;
/*
* CCLKCFG Description
* bits7:0
CCLKSEL Selects the divide value for creating
the CPU clock (CCLK)
from the PLL0 output.
0
the CPU clock. This setting is

pllclk is divided by 1 to produce


not allowed when the PLL0 is

connected, because the rate


would always be greater than the
maximum allowed CPU
clock.
54

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


1
the CPU clock. This setting is

pllclk is divided by 2 to produce


not allowed when the PLL0 is

connected, because the rate


would always be greater than the
maximum allowed CPU
2

clock.
pllclk is divided by 3 to produce

pllclk is divided by 4 to produce

pllclk is divided by 5 to produce

the CPU clock.


the CPU clock.
the CPU clock.
:
:
255 pllclk is divided by 256 to produce
the CPU clock.
bits31:8 Reserved
* */
LPC_SC->CCLKCFG
= CCLKDIV-1;
0. Now we set to 1 - pllclk/2

//By default it is

/* select All peripheral clocks same as CCLK*/


LPC_SC->PCLKSEL0
= 0X55555555;
LPC_SC->PCLKSEL1
= 0X55555555;
LPC_SC->CLKSRCSEL
CLOCK Source - 6 MHz

= MainOsc; //SELECT MAIN OSCILATOR AS

/*
* PLL0CFG Description
* bits14:0
MSEL0 PLL0 Multiplier value. Supplies the
value "M" in PLL0 frequency
calculations. The value stored here is M
- 1. Supported values for M
are 6 through 512 and those listed in
Table 21.
Note:Not all values of M are needed, and
therefore some are not
supported by hardware.
bit15
Reserved, user software should not write
ones to reserved bits. The
value read from a reserved bit is not
defined.
bits23:16 NSEL0 PLL0 Pre-Divider value. Supplies the
value "N" in PLL0 frequency
calculations. The value stored here is N
- 1. Supported values for N are
1 through 32.
bits 24:31
Reserved
* */
LPC_SC->PLL0CFG
55

|= (PLL0_MVALUE-1) | ((PLL0_NVALUE-1)<<16);

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


LPC_SC->PLL0FEED = 0XAA;// write divider setting to PLL0CFG(M1,N-1)
LPC_SC->PLL0FEED = 0X55;
LPC_SC->PLL0CON
= ENABLEPLL0; // ENABLE PLL0
LPC_SC->PLL0FEED = 0XAA;
LPC_SC->PLL0FEED = 0X55;
while(!(LPC_SC->PLL0STAT & (1<<26))); //CHECK for PLL LOCK
LPC_SC->PLL0CON
= ENCONNECTPLL0; //ENABLE PLL0 AND
CONNECT
LPC_SC->PLL0FEED = 0XAA;
LPC_SC->PLL0FEED = 0X55;
while((LPC_SC->PLL0STAT & ((1<<25)| (1<<24))) == 0 ); // WAIT
FOR ENABLE AND CONNECT
return;
}

2. PLL.H
/*
* PLL.h
*
* Created on: Sep 3, 2013
*
Author: Amar
*/
#ifndef PLL_H_
#define PLL_H_
/*PLL SETTINGS FOR CCLK =117/100/48MHZ WITH 6MHZ CRYSTAL
*
* 117 => m=39,n=1,clkdiv = 4
* 100 => m=21,n=1,clkdiv = 5
* 48 => m=20,n=1,clkdiv = 10
* 120 => m=20,n=1,clkdiv = 2
* 12 => m=20,n=1,clkdiv = 40
* */
#define FIN
12000000
#define MainOsc
1
#define ENABLEPLL0
1
#define ENCONNECTPLL0 3
#define PLL0_MVALUE
20
#define PLL0_NVALUE
1
#define CCLKDIV
40
//Controller Clock
Divider
#define CCLK
(((2*PLL0_MVALUE*FIN)/PLL0_NVALUE)/CCLKDIV)
/*END PLL SETTINGS*/
void ConfigureClock();
56

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#endif /* PLL_H_ */

3. MAIN.C
/*
====================================================================
===========
Name
: main.c
Description : main definition
====================================================================
===========
*/
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include
#include
#include
#include

<cr_section_macros.h>
<NXP/crp.h>
<stdio.h>
"PLL.h"

// Variable to store CRP value in. Will be placed automatically


// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
// TODO: insert other include files here
// TODO: insert other definitions and declarations here
unsigned int i;
unsigned char flag=0,flag1;
//Frequency=387HZ
void PWM_Init(void)
{
LPC_SC->PCONP
= 0x00000040;
//PWM1 Power UP
LPC_PWM1->PR = 0x00000000;
//PRESCALER
/*
for selecting PWM channels from 1 to 6 in single edge
controlled mode select the PWMPCR as following
PWM 1 o/p PWMPCR =0x00000200;
PWM 2 o/p PWMPCR =0x00000400;
PWM 3 o/p PWMPCR =0x00000800;
PWM 4 o/p PWMPCR =0x00001000;
PWM 5 o/p PWMPCR =0x00002000;
PWM 6 o/p PWMPCR =0x00004000;
*/
LPC_PWM1->PCR = 0x00000200;
PWM1 enabled
57

//select PWM1 single edge and

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


LPC_PWM1->MCR = 0x00000003;
//PWM'S are free running, no
interrupts
LPC_PWM1->MR0 = 30000;
//setup match register 0
count[Peiod]
/*
for selecting PWM channels from 1 to 6 in single edge
controlled mode select the MATCH REGISTER PWMMR as following
PWM 1 o/p select PWMMR1
PWM 2 o/p select PWMMR2
PWM 3 o/p select PWMMR3
PWM 4 o/p select PWMMR4
PWM 5 o/p select PWMMR5
PWM 6 o/p select PWMMR6 */
LPC_PWM1->MR1 = 0x00000100;
//setup match register 1
count for PWM channel 1
LPC_PWM1->LER = 0x000000FF;
//enable shadow copy register
LPC_PWM1->TCR = 0x00000002;
//RESET COUNTER AND PRESCALER
LPC_PWM1->TCR = 0x00000009;
//enable PWM and counter
}
int main(void) {
// TODO: insert code here
// Enter an infinite loop, just incrementing a counter
ConfigureClock();
LPC_PINCON->PINSEL4 = 0x00000001 ;
selected,
LPC_GPIO2->FIODIR2 |= 0x00000002;
LPC_GPIO2->FIOSET2 |= 0x00000002;

//PWM1 channel 1

is

//P2.1 as GPIO
//P2.1 as High

PWM_Init();
while(1)
{
for(i=0;i<=3000;i++);
// delay for Stability of
Change in Width
if(flag == 0x00)
{
LPC_PWM1->MR1 = LPC_PWM1->MR1+100;
LPC_PWM1->LER = 0x000000FF;
//Reset
PWM1 Match Registers
if(LPC_PWM1->MR1 >= 27000)
{
flag1 = 0xff;
flag = 0xff;
LPC_PWM1->LER = 0x000000FF; //Reset PWM1
Match Registers
}
}
else if(flag1 == 0xff)
{
LPC_PWM1->MR1 = LPC_PWM1->MR1-100;
LPC_PWM1->LER = 0x000000FF;

58

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


if(LPC_PWM1->MR1 <= 0x500)
{
flag = 0x00;
flag1 = 0x00;
LPC_PWM1->LER = 0x000000FF; //Reset PWM1
Match Registers
}
}
}//end of while
return 0 ;
}

59

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 7
AIM: Implementing CAN protocol using LPC1768

CONNECTIONS:
Connect the power supply to board i.e.9V & 500MA.
Connect the one terminal i.e. male connector to board at UART0 & other
terminal to our PC.
Connect the J1 & J2 (LPC1768EtherCan_V1.0) Connect with DB-9 Connector
(Male- Male).
Switch Position
SW3.1 ON
SW3.2 ON
S3.1 ON
S3.2 ON
S3.3 ON
S3.4 ON
PROCEDURE:
To Edit / Compile/ Generate Hex file.
OUTPUT:
On HyperTerminal/SPJ Terminal [Setting=> Baud Rate: 19200, No Parity, No
Echo, 8-Bits Data, 1-StopBit].
1st time Press any Key=>CAN1 Transmit with id and Data, CAN2 Receive with
id and Data,
2nd time Press any key =>CAN2 Transmit with id and Data, CAN1 Receive
with id and Data.

CONCLUSION:

60

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1. CAN.C
#include
#include
#include
#include

<stdio.h>
"LPC17xx.h"
"UART0.h"
"CAN.h"

/*******************************************************************
*******
GLOBAL VARIABLES
********************************************************************
*******/
CAN_TX_CONF CAN_CanTxConf[CAN_MAX_TX_MSG]=
{
CAN_TX_400, 8, CAN_CHANNEL1, 00, (CAN_29BIT | CAN_NO_RTR),
0x400,
CAN_TX_420, 8, CAN_CHANNEL1, 00, (CAN_29BIT | CAN_NO_RTR),
0x420,
CAN_TX_DEAD, 8, CAN_CHANNEL2, 00, (CAN_29BIT | CAN_NO_RTR),
0xDEAD,
CAN_TX_ADDED, 8, CAN_CHANNEL2, 00, (CAN_29BIT | CAN_NO_RTR),
0xADDED
};
CAN_CHANNEL_CONF CAN_CanChannelConf[MAX_CANPORTS]=
{
CAN_CHANNEL1, 0, 0, CAN_BAUD_125K,
CAN_CHANNEL2, 1, 0, CAN_BAUD_125K
};
CAN_RX_CONF CAN_CanRxConf[CAN_MAX_RX_MSG]=
{
CAN_RX_400,
0x400,
CAN_RX_420,
0x420,
CAN_RX_DEAD,
0xDEAD,
CAN_RX_ADDED,
0xADDED
};
CAN_RX_FRAME
unsigned int
unsigned int
unsigned int

CAN_CanRxBuffer[CAN_MAX_RX_MSG];
CAN_u32CANStatus;
CAN_u32CAN1RxCount = 0, CAN_u32CAN2RxCount = 0;
CAN_u32CAN1ErrCount = 0, CAN_ulCAN2ErrCount = 0;

/*******************************************************************
*************************************
*
* Function Name
CAN_SetACCFLookup
* Description :
Set Acceptance Filter Look up Table
* Arguments
none
* returns
function doesn't return
********************************************************************
************************************/
void CAN_SetACCFLookup( void )
{
61

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


unsigned int u32address = 0;
unsigned int u32i;
unsigned int u32ID_high, u32ID_low;
// Set explicit standard Frame
LPC_CANAF->SFF_sa = u32address;
for ( u32i = 0; u32i < ACCF_IDEN_NUM; u32i += 2 )
{
u32ID_low = (u32i << 29) | (EXP_STD_ID << 16);
u32ID_high = ((u32i+1) << 13) | (EXP_STD_ID << 0);
*((unsigned int *)(CAN_MEM_BASE + u32address)) =
u32ID_low | u32ID_high;
u32address += 4;
}
// Set group standard Frame
LPC_CANAF->SFF_GRP_sa = u32address;
for ( u32i = 0; u32i < ACCF_IDEN_NUM; u32i += 2 )
{
u32ID_low = (u32i << 29) | (GRP_STD_ID << 16);
u32ID_high = ((u32i+1) << 13) | (GRP_STD_ID << 0);
*((unsigned int *)(CAN_MEM_BASE + u32address)) =
u32ID_low | u32ID_high;
u32address += 4;
}
// Set explicit extended Frame
LPC_CANAF->EFF_sa = u32address;
for ( u32i = 0; u32i < ACCF_IDEN_NUM; u32i++ )
{
u32ID_low = (u32i << 29) | (EXP_EXT_ID << 0);
*((unsigned int *)(CAN_MEM_BASE + u32address)) =
u32ID_low;
u32address += 4;
}
// Set group extended Frame
LPC_CANAF->EFF_GRP_sa = u32address;
for ( u32i = 0; u32i < ACCF_IDEN_NUM; u32i++ )
{
u32ID_low = (u32i << 29) | (GRP_EXT_ID << 0);
*((unsigned int *)(CAN_MEM_BASE + u32address)) =
u32ID_low;
u32address += 4;
}
// Set End of Table
LPC_CANAF->ENDofTable = u32address;
return;
}
/*******************************************************************
*************************************
*
* Function Name
CAN_SetACCFLookup
* Description :
Set acceptance filter and SRAM associated with
* Arguments
u32ACCFMode
* returns
function doesn't return

62

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


********************************************************************
************************************/
void CAN_SetACCF( unsigned int u32ACCFMode )
{
switch ( u32ACCFMode )
{
case ACCF_OFF:
LPC_CANAF->AFMR = u32ACCFMode;
LPC_CAN1->MOD = LPC_CAN2->MOD = 1;
// Reset CAN
LPC_CAN1->IER = LPC_CAN2->IER = 0;
// Disable Receive
Interrupt
LPC_CAN1->GSR = LPC_CAN2->GSR = 0;
// Reset error
counter when CANxMOD is in reset
break;
case ACCF_BYPASS:
LPC_CANAF->AFMR = u32ACCFMode;
break;
case ACCF_ON:
case ACCF_FULLCAN:
LPC_CANAF->AFMR = ACCF_OFF;
CAN_SetACCFLookup();
LPC_CANAF->AFMR = u32ACCFMode;
break;
default:
break;
}
return;
}
/*******************************************************************
*************************************
*
* Function Name
CAN_InitModule
* Description :
Initialize CAN Module
* Arguments
none
* returns
function doesn't return
********************************************************************
************************************/
void CAN_InitModule(void)
{
unsigned char u8Count;
LPC_SC->PCONP |= 0x00006000;
/* Turn On
CAN1 CAN2 PCLK */
LPC_PINCON->PINSEL0 |= 0x0000A00;
// Enable
P0.4,P0.5,CAN1 Tx,RX
LPC_PINCON->PINSEL1 |=
0x00003C00 ;
//Enable
P0.21 as CAN1 RX, P0.22 as CAN1 TX
LPC_SC->PCLKSEL0 |= 0x14000000 ;
/* set acceptance filter reg */
CAN_SetACCF(ACCF_BYPASS);
for(u8Count=0; u8Count < CAN_MAX_RX_MSG ; u8Count++)
{
63

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


CAN_CanRxBuffer[u8Count].u8RxFlag =0;
}
}
/*******************************************************************
*************************************
*
* Function Name
CAN_InitChannel
* Description :
Initialize CAN Channel
* Arguments
u8ChaNo (Channel Number)
* returns
1 - if Ok
0 - if not Ok
********************************************************************
************************************/
unsigned short int CAN_InitChannel (unsigned char u8ChaNo)
{
switch (u8ChaNo)
{
case CAN_CHANNEL1:
/* Go into Reset mode */
LPC_CAN1->MOD = 1; // Reset CAN
/* Disable All Interrupts */
LPC_CAN1->IER = 0;
/* Clear Status register */
LPC_CAN1->GSR = 0;
// Reset error counter when CANxMOD
is in reset
/* Set bit timing */
LPC_CAN1->BTR = CAN_CanChannelConf[u8ChaNo].u32BaudRate;
/* Enable Receive Interrupt */
LPC_CAN1->IER = 0x01;
/* Operating Mode */
LPC_CAN1->MOD = 0x0; // CAN in normal operation mode
break;
case CAN_CHANNEL2:
/* Go into Reset mode */
LPC_CAN2->MOD = 1;
// Reset CAN
/* Disable All Interrupts */
LPC_CAN2->IER = 0;
/* Clear Status register */
LPC_CAN2->GSR = 0;
// Reset error counter when CANxMOD
is in reset
/* Set bit timing */
LPC_CAN2->BTR = CAN_CanChannelConf[u8ChaNo].u32BaudRate;
/* Enable Receive Interrupt */
LPC_CAN2->IER = 0x01;
/* Operating Mode */
LPC_CAN2->MOD = 0x0; // CAN in normal operation mode
break;
default:
return 0; // illegal value used
}
return 1;
64

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
/*******************************************************************
*************************************
*
* Function Name
CAN_Init
* Description :
Initialize of complete CAN unit
*
*
*
* Arguments
u8ChaNo (Channel Number)
* returns
TRUE - if Ok
********************************************************************
************************************/
unsigned int CAN_Init(void)
{
/* Initialisation of CAN module */
CAN_InitModule();
/* init channel 0 */
CAN_InitChannel(CAN_CHANNEL1);
/* init channel 1 */
CAN_InitChannel(CAN_CHANNEL2);
NVIC_EnableIRQ(CAN_IRQn); //enable CAN interrupt
//
#ifdef DEBUG
//
printf("LPC_CAN1->BTR= %x,LPC_CAN1->IER = %x,LPC_CAN1>GSR = %x LPC_CAN1->MOD = %u \n",LPC_CAN1->BTR,LPC_CAN1>IER,LPC_CAN1->GSR,LPC_CAN1->MOD);
//
printf("LPC_CAN2->BTR= %x,LPC_CAN2->IER = %x,LPC_CAN2>GSR = %x LPC_CAN2->MOD = %x CAN_AFMR =%x\n",LPC_CAN2>BTR,LPC_CAN2->IER,LPC_CAN2->GSR,LPC_CAN2->MOD,CAN_AFMR);
//
#endif
return( TRUE );
}
/*******************************************************************
*************************************
*
* Function Name
CAN_TxMessage
* Description :
Sends the CAN message
*
*
*
* Arguments
u8Handle, pu8Buff
* returns
1 - if Ok
0 - if not Ok
********************************************************************
************************************/
unsigned short int CAN_TxMessage(unsigned char u8Handle,unsigned
char* pu8Buff)
{
if(CAN_CanTxConf[u8Handle].u8Channel == CAN_CHANNEL1)
{
if (!(LPC_CAN1->SR & 0x00000004L))
{ // Transmit Channel is not available
65

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


return 0; // No channel available
}
// Write DLC, RTR and FF
LPC_CAN1->TFI1 = ((((unsigned
int)CAN_CanTxConf[u8Handle].u8DLC)<<16) |
CAN_CanTxConf[u8Handle].u32IsRtrExtd) & 0xC00F0000L;
LPC_CAN1->TID1 = CAN_CanTxConf[u8Handle].u32CanId;
LPC_CAN1->TDA1 = *(unsigned int*)pu8Buff;
LPC_CAN1->TDB1 = *((unsigned int*)(pu8Buff+4));
LPC_CAN1->CMR = 0x21;
return 1;
}
else if(CAN_CanTxConf[u8Handle].u8Channel == CAN_CHANNEL2)
{
if (!(LPC_CAN2->SR & 0x00000004L))
{ // Transmit Channel is not available
return 0; // No channel available
}
// Write DLC, RTR and FF
LPC_CAN2->TFI1 = ((((unsigned
int)CAN_CanTxConf[u8Handle].u8DLC)<<16) |
CAN_CanTxConf[u8Handle].u32IsRtrExtd) & 0xC00F0000L;
LPC_CAN2->TID1 = CAN_CanTxConf[u8Handle].u32CanId;
LPC_CAN2->TDA1 = *(unsigned int*)pu8Buff;
LPC_CAN2->TDB1 = *((unsigned int*)(pu8Buff+4));
LPC_CAN2->CMR = 0x21;
return 1;
}
else
{
return (0);
}
}
/*******************************************************************
*************************************
*
* Function Name
CAN_IsrRx1
* Description :
CAN Rx1 interrupt handler
*
*
*
* Arguments
none
* returns
function doesn't return
********************************************************************
************************************/
void CAN_IsrRx1(void)
{
unsigned char u8Count;
//
//
//

#ifdef DEBUG
UART_PrintString("CAN_IsrRx1\n");
#endif

66

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


LPC_GPIO2->FIOPIN2 = 0x00000001;

/* turn off all the LEDs

*/
for(u8Count=0; u8Count < CAN_MAX_RX_MSG ; u8Count++)
{
if(CAN_CanRxConf[u8Count].u32Id == LPC_CAN1->RID)
{
CAN_CanRxBuffer[u8Count].u8Channel = CAN_CHANNEL1;
CAN_CanRxBuffer[u8Count].u8DLC = (LPC_CAN1->RFS &
0x000F0000)>>16;
*((unsigned
int*)&CAN_CanRxBuffer[u8Count].u8Data[0]) = LPC_CAN1->RDA;
*((unsigned
int*)&CAN_CanRxBuffer[u8Count].u8Data[4]) = LPC_CAN1->RDB;
CAN_CanRxBuffer[u8Count].u8RxFlag = 1;
break;
}
}
CAN_CanRxBuffer[u8Count].u8RxFlag = 1;
LPC_CAN1->CMR = 0x04; // release receive buffer
}
/*******************************************************************
*************************************
*
* Function Name
CAN_IsrRx2
* Description :
CAN Rx2 interrupt handler
*
*
*
* Arguments
none
* returns
function doesn't return
********************************************************************
************************************/
void CAN_IsrRx2(void)
{
unsigned char u8Count;
//
#ifdef DEBUG
//
UART_PrintString("CAN_IsrRx2\n");
//
#endif
LPC_GPIO2->FIOPIN2 = 0x00000002;

/* turn off all the LEDs

*/
for(u8Count=0; u8Count < CAN_MAX_RX_MSG ; u8Count++)
{
if(CAN_CanRxConf[u8Count].u32Id == LPC_CAN2->RID)
{
CAN_CanRxBuffer[u8Count].u8Channel = CAN_CHANNEL1;
CAN_CanRxBuffer[u8Count].u8DLC = (LPC_CAN2->RFS &
0x000F0000)>>16;
*((unsigned
int*)&CAN_CanRxBuffer[u8Count].u8Data[0]) = LPC_CAN2->RDA;
*((unsigned
int*)&CAN_CanRxBuffer[u8Count].u8Data[4]) = LPC_CAN2->RDB;
CAN_CanRxBuffer[u8Count].u8RxFlag = 1;
67

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


break;
}
}
CAN_CanRxBuffer[u8Count].u8RxFlag = 1;
LPC_CAN2->CMR = 0x04; // release receive buffer
}
/*******************************************************************
*************************************
*
* Function Name
CAN_ISR
* Description :
CAN interrupt handler
*
*
*
* Arguments
none
* returns
function doesn't return
********************************************************************
************************************/
void CAN_IRQHandler(void)
{
//
#ifdef DEBUG
//
printf("LPC_CAN1->BTR= %x,LPC_CAN1->IER = %x,LPC_CAN1>GSR = %x LPC_CAN1->ISR = %x\n",LPC_CAN1->BTR,LPC_CAN1>IER,LPC_CAN1->GSR,LPC_CAN1->ISR);
//
printf("LPC_CAN2->BTR= %x,LPC_CAN2->IER = %x,LPC_CAN2>GSR = %x LPC_CAN2->SR = %x\n",LPC_CAN2->BTR,LPC_CAN2->IER,LPC_CAN2>GSR,LPC_CAN2->SR);
//
#endif
if ( LPC_CANCR->CANRxSR & (1 << 8) )
{
CAN_u32CAN1RxCount++;
CAN_IsrRx1();
}
if ( LPC_CANCR->CANRxSR & (1 << 9) )
{
CAN_u32CAN2RxCount++;
CAN_IsrRx2();
}
if ( LPC_CAN1->GSR & (1 << 6 ) )
{
/* The error count includes both TX and RX */
CAN_u32CAN1ErrCount = (LPC_CAN1->GSR >> 16 );
}
if ( LPC_CAN2->GSR & (1 << 6 ) )
{
/* The error count includes both TX and RX */
CAN_ulCAN2ErrCount = (LPC_CAN2->GSR >> 16 );
}
}

68

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


2. CAN.H
#ifndef CAN_H
#define CAN_H
//#define DEBUG 1
/*******************************************************************
*******
USER DEFINABLE PARAMETERS
********************************************************************
*******/
#ifndef TRUE
#define TRUE
(1)
#endif
// The example code in "main" uses CAN ports 1 and 2 (MAX_CANPORTS
2)
#define MAX_CANPORTS 2
// Maximum number of messages kept in the receive queue
#define MAX_QUEUE 25
/*******************************************************************
*******
DO NOT CHANGE ANYTHING BELOW
********************************************************************
*******/
#define CAN_MEM_BASE
0xE0038000
/* Acceptance filter mode in AFMR register */
#define ACCF_OFF
0x01
#define ACCF_BYPASS
0x02
#define ACCF_ON
0x00
#define ACCF_FULLCAN
0x04
/* This number applies to all FULLCAN IDs, explicit STD IDs, group
STD IDs,
explicit EXT IDs, and group EXT IDs. */
#define ACCF_IDEN_NUM
4
/* Identifiers for FULLCAN, EXP STD, GRP STD, EXP EXT, GRP EXT */
#define FULLCAN_ID
0x100
#define EXP_STD_ID
0x100
#define GRP_STD_ID
0x200
#define EXP_EXT_ID
0x100000
#define GRP_EXT_ID
0x200000
// Define CAN SFR address bases
#define CAN_REG_BASE
#define ACCEPTANCE_FILTER_RAM_BASE
#define ACCEPTANCE_FILTER_REGISTER_BASE
#define CENTRAL_CAN_REGISTER_BASE
// Common CAN bit rates
#define
CANBitrate125k_12MHz
#define
CANBitrate250k_12MHz
#define CAN_CHANNEL1 0
69

(0xE0000000)
(CAN_REG_BASE + 0x00038000)
(CAN_REG_BASE + 0x0003C000)
(CAN_REG_BASE + 0x00040000)
0x001C001D
0x001C000E

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define CAN_CHANNEL2 1
#define CAN_11BIT
0x00000000
#define CAN_29BIT
0x80000000
#define CAN_RTR
0x40000000
#define CAN_NO_RTR
0x00000000
/*
(5F)H = (95)D
Baud Rate = (12 MHz)/(95+1) = 125 K
*/
#define CAN_BAUD_125K 0x001C005F
typedef enum
{
CAN_TX_400=0,
CAN_TX_420,
CAN_TX_DEAD,
CAN_TX_ADDED,
CAN_MAX_TX_MSG
}dd;
typedef enum
{
CAN_RX_400=0,
CAN_RX_420,
CAN_RX_DEAD,
CAN_RX_ADDED,
CAN_MAX_RX_MSG
}jjh;
// Type definition to hold a CAN message
typedef struct
{
unsigned char u8ChannelNo;
unsigned char u8IsrNo;
unsigned char u16Reserve;
unsigned int u32BaudRate;
}CAN_CHANNEL_CONF;
typedef struct
{
unsigned char u8TxHandle;
unsigned char u8DLC;
unsigned char u8Channel;
unsigned char u8Reserved;
unsigned int u32IsRtrExtd;
unsigned int u32CanId;
}CAN_TX_CONF;
typedef struct
{
unsigned char u8RxHandle;
unsigned int u32Id;
}CAN_RX_CONF;

70

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


typedef struct
{
unsigned char
unsigned char
unsigned char
unsigned char
unsigned char
}CAN_RX_FRAME;
extern
extern
extern
extern

u8RxHandle;
u8DLC;
u8Channel;
u8RxFlag;
u8Data[12];

CAN_RX_CONF CAN_CanRxConf[CAN_MAX_RX_MSG];
CAN_RX_FRAME CAN_CanRxBuffer[CAN_MAX_RX_MSG];
CAN_CHANNEL_CONF CAN_CanChannelConf[MAX_CANPORTS];
CAN_TX_CONF CAN_CanTxConf[CAN_MAX_TX_MSG];

extern unsigned int CAN_u32CANStatus;


extern unsigned int CAN_u32CAN1RxCount, CAN_u32CAN2RxCount;
extern unsigned int CAN_u32CAN1ErrCount, CAN_u32CAN2ErrCount;
unsigned int CAN_Init(void);
void CAN_SetACCF( unsigned int u32ACCFMode );
void CAN_SetACCFLookup( void );
void CAN_InitModule(void);
unsigned short int CAN_InitChannel (unsigned char u8ChaNo);
unsigned short int CAN_TxMessage(unsigned char u8Handle,unsigned
char* pu8Buff);
void CAN_IRQHandler(void);
void CAN_IsrRx1(void);
void CAN_IsrRx2(void);
void ShowStatus(void);
#endif

3. UART0.C
/*
====================================================================
====================================
Name
: UART0.c
Description : This file contains the functions related to UART0
communication
====================================================================
====================================
*/
#include "LPC17xx.h"
#include "PLL.h"
#include "UART0.h"
void InitUart0(void)
{
/*
*****************************************************************
* Inputs : NA
* Output :
NA
71

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


* Description:
* This function initializes the UART0 with the parameters
19200, 8-N-1 using the pclk for UART same as system clock
*
*****************************************************************/
uint16_t PCLKDIV =0,Divider=0;
uint32_t pclk=0;
LPC_SC->PCONP |= PCUART0; //Enable power For UART0
/*To Configure PORT PIN P0.2 as TXD0 write "01" at bits 4 & 5
of PINSEL0, similarly To Configure PORT PIN P0.3 as RXD0 write "01"
at bits 6 & 7 of PINSEL0 */
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & ~0xf0) | (1 << 4)
| (1 << 6); //p0.2 TXD0, p0.3 RXD0
/*
* LCR Register Description
*
* bits1:0
Word Length Select
character length 0

00

5-bit
01

6-bit

10

7-bit

11

8-bit

character length
character length
character length
bit2

Stop Bit Select 0

1 stop bit. 0
1

2 stop

bits (1.5 if UnLCR[1:0]=00).


bit3
Parity Enable
generation and checking. 0

Disable parity
1

Enable

parity generation and checking.


bits5:4
Parity Select
00
Odd parity. Number
of 1s in the transmitted character and the attached
parity
bit will be odd.
01
Even
Parity. Number of 1s in the transmitted character and the attached
parity
bit will be even.
10
Forced
"1" stick parity.
11
Forced
"0" stick parity.
bit6
transmission. 0

Break Control

Disable break

1
Enable
break transmission. Output pin UARTn TXD is forced to logic 0
72

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


when
UnLCR[6] is active high.
bit7
Divisor Latch
Access Bit (DLAB)
access to Divisor Latches. 0

Disable
1

Enable

access to Divisor Latches.


bits31:8
Reserved
* */
LPC_UART0->LCR = 0x83;
PCLKDIV = (LPC_SC->PCLKSEL0 >>6) & 0x03; // to read pclk
selected for UART0
/*depending on the status of the PCLKSEL0 select the CCLK for
UART0*/
switch(PCLKDIV)
{
case 0x00:
pclk = CCLK/4;
break;
case 0x01:
default:
pclk = CCLK;
break;
case 0x02:
pclk = CCLK/2;
break;
case 0x03:
pclk = CCLK/8;
break;
}
/*
***************************************************************
* Calculate the Divider count for the desired Baudrate
* Make DLAB =1 before accessing the DLL and DLM.
*
****************************************************************/
Divider = (pclk/16) / BAUDRATE;
LPC_UART0->DLL = Divider & 0xFF;
LPC_UART0->DLM = (Divider >>8) & 0xFF;
LPC_UART0->LCR = 0X03; // SET DLAB =0
LPC_UART0->FCR = 0x07;// ENABLE TX AND RX FIFO'S
return;
}
/*
*
* This function
* */

can be used if a character is to be sent on uart0

char UART0putchar(char ch)


{

73

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


/*
***************************************************************
* Inputs :
Character to be sent to UART
* Outputs :
Received Character
* Description:
* This function is used to send character to the UART0
*
****************************************************************/
/*LSR Register Description
*
* bit0
Receiver Data Ready (RDR) UnLSR0 is set when
the UnRBR holds an unread character and is cleared when
the UARTn RBR FIFO is empty.
0
The UARTn receiver FIFO is empty.
1
The UARTn receiver FIFO is not empty.
bit1
Overrun Error(OE)
The overrun
error condition is set as soon as it occurs. An UnLSR read clears
UnLSR1. UnLSR1 is set when UARTn RSR has a new character
assembled and
the UARTn RBR FIFO is full. In this case, the UARTn RBR FIFO
will not be
overwritten and the character in the UARTn RSR will be lost.
0
Overrun error status is inactive.
1
Overrun error status is active.
bit2
Parity Error (PE)
When the
parity bit of a received character is in the wrong state, a parity
error
occurs. An UnLSR read clears UnLSR[2]. Time of parity error
detection is
dependent on UnFCR[0].
Note:A parity error is associated with the character at the
top of the UARTn RBR FIFO.
0
Parity error status is inactive.
1
Parity error status is active.
bit3
Framing Error(FE)
When the stop
bit of a received character is a logic 0, a framing error occurs. An
74

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


UnLSR read clears UnLSR[3]. The time of the framing error
detection is
dependent on UnFCR0. Upon detection of a framing error, the Rx
will attempt to
resynchronize to the data and assume that the bad stop bit is
actually an early
start bit. However, it cannot be assumed that the next
received byte will be correct
even if there is no Framing Error.
Note:A framing error is associated with the character at the
top of the UARTn
RBR FIFO.
0
Framing error status is inactive.
1
Framing error status is active.
bit4
Break Interrupt(BI)
When RXDn is
held in the spacing state (all zeroes) for one full character
transmission (start, data, parity, stop), a break interrupt
occurs. Once the break
condition has been detected, the receiver goes idle until RXDn
goes to marking
state (all ones). An UnLSR read clears this status bit. The
time of break detection
is
dependent on UnFCR[0].
Note:The break interrupt is associated with the character at
the top of the UARTn RBR FIFO.
0
Break interrupt status is inactive.
1
Break interrupt status is active.
bit5
Transmitter Holding
Register Empty (THRE))
THRE is
set immediately upon detection of an empty UARTn THR and is cleared
on
a UnTHR write.
0
UnTHR contains valid data.

75

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


1
UnTHR is empty.
bit6
Transmitter Empty (TEMT)
TEMT is set when
both UnTHR and UnTSR are empty; TEMT is cleared when
either the UnTSR or the UnTHR contain valid data.
0
UnTHR and/or the UnTSR contains valid data.
1
UnTHR and the UnTSR are empty.
bit7
Error in RX FIFO(RXFE)
UnLSR[7] is
set when a character with a Rx error such as framing error, parity
error or break interrupt, is loaded into the UnRBR. This bit
is cleared when the
UnLSR register is read and there are no subsequent errors in
the UARTn FIFO.
0
UnRBR contains no UARTn RX errors or UnFCR[0]=0.
1
UARTn RBR contains at least one UARTn RX error.
bits31:8 Reserved, the value read from a reserved bit is
not defined.
* */
if (ch=='\n')
{
//wait until Transmit Holding Register is empty
while (!(LPC_UART0->LSR & LSR_THRE)) {}
//then store to Transmit Holding Register
LPC_UART0->THR ='\r';
}
//wait until Transmit Holding Register is empty
while (!(LPC_UART0->LSR & LSR_THRE)) {}
//then store to Transmit Holding Register
LPC_UART0->THR=ch;
return ch;
}
char UART0getchar(void)
{
/*
***************************************************************
* Inputs :
NA
* Outputs :
Received Character from UART0
* Description:
* This function is used to read character received to the
UART0

76

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


*
****************************************************************/
uint8_t ch;
//wait until there's a character to be read
while (!(LPC_UART0->LSR & LSR_RDR)) {}
//then read from the Receiver Buffer Register
ch=LPC_UART0->RBR;
return ch;
}
void UART0Puts(char *pcString)
{
/*
********************************************************************
******
* Inputs :
Character string
* Outputs :
NA
* Description:
* This function is used to send character string to UART0
using UART0putchar
*
********************************************************************
******/
// loop through until reach string's zero terminator
while (*pcString != 0)
{
UART0putchar(*pcString++); // print each character
}
}

4. UART0.H
/*
* UART0.h
*
* Created on: Sep 3, 2013
*
Author: Amar
*/
#ifndef UART0_H_
#define UART0_H_
#define
#define
#define
#define
#define
void
char
char
void

LSR_RDR
1
LSR_THRE 0x20
PCUART0
(1<<3)
PCLK_UART0
01
BAUDRATE 19200

//POWER CONTROL UART1


// PCLK=CCLK

InitUart0(void);
UART0putchar(char);
UART0getchar(void);
UART0Puts(char *pcString);

77

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#endif /* UART0_H_ */

5. MAIN.C
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include
#include
#include
#include
#include
#include

<cr_section_macros.h>
<NXP/crp.h>
<stdio.h>
"PLL.h"
"UART0.h"
"CAN.h"

// Variable to store CRP value in. Will be placed automatically


// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
// TODO: insert other include files here
// TODO: insert other definitions and declarations here
const unsigned char MAIN_i8Source1[]= "TxOnCAN2";
const unsigned char MAIN_i8Source2[]= "TxOnCAN1";
int main(void)
{
// TODO: insert code here
char a,b;
ConfigureClock();
InitUart0();
printf("CAN1,2 Test\n");
CAN_Init();
while (1)
{
/*
send one message from CAN2(TX) and verify received
message on CAN1(RX)
*/
CAN_TxMessage(CAN_TX_ADDED,(unsigned
char*)&MAIN_i8Source1);
UART0Puts("\nPlease press any key :");
a = UART0getchar();
UART0putchar(a);
if(CAN_CanRxBuffer[CAN_TX_ADDED].u8RxFlag)
{
UART0Puts("\nYou have pressed : ");
UART0putchar(a);
UART0Puts("\nCAN2 TX Complete");
UART0Puts("\nMessage received on CAN1 id:");
printf("0x%x\n",*((unsigned
int*)&CAN_CanRxConf[CAN_TX_ADDED].u32Id));
printf("Data:0x%x\n",&CAN_CanRxBuffer[CAN_TX_ADDED].u8Data);
CAN_CanRxBuffer[CAN_TX_ADDED].u8RxFlag =0;
78

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
/*
send one message from CAN1(TX) and verify received
message on CAN2(RX)
*/
CAN_TxMessage(CAN_TX_420,(unsigned
char*)&MAIN_i8Source2);
printf("\nPlease press any key :");
b = UART0getchar();
UART0putchar(b);
if(CAN_CanRxBuffer[CAN_TX_420].u8RxFlag)
{
UART0Puts("\nYou have pressed : ");
UART0putchar(b);
printf("\nCAN1 TX complete");
printf("\nMessage received on CAN2 id:");
printf("0x%x\n",*((unsigned
int*)&CAN_CanRxConf[CAN_TX_420].u32Id));
printf("Data:0x%x\n",&CAN_CanRxBuffer[CAN_TX_420].u8Data);
CAN_CanRxBuffer[CAN_TX_420].u8RxFlag =0;
}
else
{
printf("Please connect F-F serial cable\r\n");
}
} // while(1)
return 0 ;
}

79

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


ASSIGNMENT 8
AIM: Implementing ETHERNET protocol using LPC1768
CONNECTIONS:
Connect the power supply to board i.e.9V & 500MA.
To connect the board to our PC we are using serial cable i.e.10-Pin Relimate
connector.
Connect the one terminal i.e. male connector to board at UART0 & other
terminal to our PC.
To Connect the Board with Ethernet Cable (RJ-45) Coming from PC.
Switch Position
SW3.1 ON
SW3.2 ON
SW6.1 ON
SW6.2 ON
SW6.3 ON

SW6.4 ON
SW7.1 ON
SW7.2 ON
SW7.3 ON
SW7.4 ON

PROCEDURE:
To Edit / Compile/ Generate Hex file.
To download and run this program.

OUTPUT:
On PC, Any Internet Browser -> 192.168.1.150

CONCLUSION:

80

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


Program:
1. ETHMAC.C
#include "ethmac.h"
// CodeRed - add additional includes
#include "tcpip.h"
#include "LPC17xx.h"
// CodeRed - new static pointers for receive and transmit
static unsigned short *rxptr;
static unsigned short *txptr;
// CodeRed - function added to write to external ethernet PHY chip
void WriteToPHY (int reg, int writeval)
{
unsigned int loop;
// Set up address to access in MII Mgmt Address Register
LPC_EMAC->MADR = DP83848C_DEF_ADR | reg;
// Write value into MII Mgmt Write Data Register
LPC_EMAC->MWTD = writeval;
// Loop whilst write to PHY completes
for (loop = 0; loop < MII_WR_TOUT; loop++) {
if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { break; }
}
}
// CodeRed - function added to read from external ethernet PHY chip
unsigned short ReadFromPHY (unsigned char reg)
{
unsigned int loop;
// Set up address to access in MII Mgmt Address Register
LPC_EMAC->MADR = DP83848C_DEF_ADR | reg;
// Trigger a PHY read via MII Mgmt Command Register
LPC_EMAC->MCMD = MCMD_READ;
// Loop whilst read from PHY completes
for (loop = 0; loop < MII_RD_TOUT; loop++) {
if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { break; }
}
LPC_EMAC->MCMD = 0; // Cancel read
// Returned value is in MII Mgmt Read Data Register
return (LPC_EMAC->MRDD);
}
// Ethernet power/clock control bit in PCONP register
#define PCENET 0x40000000
// Ethernet configuration for PINSEL2, as per user guide section 5.3
#define ENET_PINSEL2_CONFIG 0x50150105
// Ethernet configuration for PINSEL3, as per user guide section 5.4
#define ENET_PINSEL3_CONFIG 0x00000005
// Only bottom byte of PINSEL3 relevant to Ethernet
#define ENET_PINSEL3_MASK 0x0000000F
void Init_EthMAC(void)
{
unsigned int value, phyid1, phyid2;
volatile unsigned int loop;
81

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


unsigned phy_in_use = 0;
unsigned phy_linkstatus_reg;
unsigned phy_linkstatus_mask;
// Set Ethernet power/clock control bit
LPC_SC->PCONP |= PCENET;
//Enable Ethernet pins through PINSEL registers
LPC_PINCON->PINSEL2 = ENET_PINSEL2_CONFIG;
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~(ENET_PINSEL3_MASK))
| ENET_PINSEL3_CONFIG;
// Set up MAC Configuration Register 1
LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
MAC1_RES_MCS_RX |MAC1_SIM_RES | MAC1_SOFT_RES;
// Set up MAC Command Register
LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES |
CR_PASS_RUNT_FRM;
// Short delay
for (loop = 100; loop; loop--);
// Set up MAC Configuration Register 1 to pass all receive frames
LPC_EMAC->MAC1 = MAC1_PASS_ALL;
// Set up MAC Configuration Register 2 to append CRC and pad out
frames
LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
// Set Ethernet Maximum Frame Register
LPC_EMAC->MAXF = ETH_MAX_FLEN;
// Set Collision Window / Retry Register
LPC_EMAC->CLRT = CLRT_DEF;
// Set Non Back-to-Back Inter-Packet-Gap Register
LPC_EMAC->IPGR = IPGR_DEF;
/* Enable Reduced MII interface. */
LPC_EMAC->MCFG = MCFG_CLK_DIV64 | MCFG_RES_MII;
for (loop = 100; loop; loop--);
LPC_EMAC->MCFG = MCFG_CLK_DIV64;
// Set MAC Command Register to enable Reduced MII interface
// and prevent runt frames being filtered out
LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
// Put DP83848C PHY into reset mode
WriteToPHY (PHY_REG_BMCR, 0x8000);
// Loop until hardware reset completes
for (loop = 0; loop < 0x100000; loop++) {
value = ReadFromPHY (PHY_REG_BMCR);
if (!(value & 0x8000)) {
// Reset has completed
break;
}
82

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
// Just check this actually is a DP83848C PHY
phyid1 = ReadFromPHY (PHY_REG_IDR1);
phyid2 = ReadFromPHY (PHY_REG_IDR2);
if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == DP83848C_ID) {
phy_in_use = DP83848C_ID;
}
else if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == LAN8720_ID) {
phy_in_use = LAN8720_ID;
}
if (phy_in_use != 0) {
// Safe to configure the PHY device
// Set PHY to autonegotiation link speed
WriteToPHY (PHY_REG_BMCR, PHY_AUTO_NEG);
// loop until autonegotiation completes
for (loop = 0; loop < 0x100000; loop++) {
value = ReadFromPHY (PHY_REG_BMSR);
if (value & 0x0020) {
// Autonegotiation has completed
break;
}
}
}
phy_linkstatus_reg = PHY_REG_STS;
phy_linkstatus_mask = 0x0001;

// Default to DP83848C

if (phy_in_use == LAN8720_ID) {
phy_linkstatus_reg = PHY_REG_BMSR;
phy_linkstatus_mask = 0x0004;
}
// Now check the link status
for (loop = 0; loop < 0x10000; loop++) {
value = ReadFromPHY (phy_linkstatus_reg);
if (value & phy_linkstatus_mask) {
// The link is on
break;
}
}
// Now configure for full/half duplex mode
if (value & 0x0004) {
// We are in full duplex is enabled mode
LPC_EMAC->MAC2
|= MAC2_FULL_DUP;
LPC_EMAC->Command |= CR_FULL_DUP;
LPC_EMAC->IPGT
= IPGT_FULL_DUP;
}
else {
// Otherwise we are in half duplex mode
LPC_EMAC->IPGT = IPGT_HALF_DUP;
83

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
// Now configure 100MBit or 10MBit mode
if (value & 0x0002) {
// 10MBit mode
LPC_EMAC->SUPP = 0;
}
else {
// 100MBit mode
LPC_EMAC->SUPP = SUPP_SPEED;
}
// Now set the Ethernet MAC Address registers
// NOTE - MAC address must be unique on the network!
LPC_EMAC->SA0 = (MYMAC_1 << 8) | MYMAC_2; // Station address 0 Reg
LPC_EMAC->SA1 = (MYMAC_3 << 8) | MYMAC_4; // Station address 1 Reg
LPC_EMAC->SA2 = (MYMAC_5 << 8) | MYMAC_6; // Station address 2 Reg
// Now initialise the Rx descriptors
for (loop = 0; loop < NUM_RX_FRAG; loop++) {
RX_DESC_PACKET(loop) = RX_BUF(loop);
RX_DESC_CTRL(loop)
= RCTRL_INT | (ETH_FRAG_SIZE-1);
RX_STAT_INFO(loop)
= 0;
RX_STAT_HASHCRC(loop) = 0;
}
// Set up the Receive Descriptor Base address register
LPC_EMAC->RxDescriptor
= RX_DESC_BASE;
// Set up the Receive Status Base address register
LPC_EMAC->RxStatus
= RX_STAT_BASE;
// Setup the Receive Number of Descriptor register
LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
// Set Receive Consume Index register to 0
LPC_EMAC->RxConsumeIndex = 0;
// Now initialise the Tx descriptors
for (loop = 0; loop < NUM_TX_FRAG; loop++) {
TX_DESC_PACKET(loop) = TX_BUF(loop);
TX_DESC_CTRL(loop)
= 0;
TX_STAT_INFO(loop)
= 0;
}
// Set up the Transmit Descriptor Base address register
LPC_EMAC->TxDescriptor
= TX_DESC_BASE;
// Set up the Transmit Status Base address register
LPC_EMAC->TxStatus
= TX_STAT_BASE;
// Setup the Transmit Number of Descriptor register
LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
// Set Transmit Consume Index register to 0
LPC_EMAC->TxProduceIndex = 0;
// Receive Broadcast and Perfect Match Packets
LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN;

84

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// Enable interrupts MAC Module Control Interrupt Enable Register
LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
// Reset all ethernet interrupts in MAC module
LPC_EMAC->IntClear = 0xFFFF;
// Finally enable receive and transmit mode in ethernet core
LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN);
LPC_EMAC->MAC1
|= MAC1_REC_EN;
}
// writes a word in little-endian byte order to TX_BUFFER
void WriteFrame_EthMAC(unsigned short Data)
{
*txptr++ = Data;
}
void CopyToFrame_EthMAC(void *Source, unsigned int Size)
{
unsigned int index;
unsigned short *pSource;
pSource = Source;
Size = (Size + 1) & 0xFFFE;
// round up Size to next even
number
while (Size > 0) {
WriteFrame_EthMAC(*pSource++);
Size -= 2;
}
index = LPC_EMAC->TxProduceIndex;
if (++index == NUM_TX_FRAG)
index = 0;
LPC_EMAC->TxProduceIndex = index;
}
// reads a word in little-endian byte order from RX_BUFFER
unsigned short ReadFrame_EthMAC(void)
{
return (*rxptr++);
}
unsigned short ReadFrameBE_EthMAC(void)
{
unsigned short ReturnValue;
ReturnValue = SwapBytes (*rxptr++);
return (ReturnValue);
}
void CopyFromFrame_EthMAC(void *Dest, unsigned short Size)
{
unsigned short *pDest;

85

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


pDest = Dest;
while (Size > 1) {
*pDest++ = ReadFrame_EthMAC();
Size -= 2;
}
if (Size) {
// check for
leftover byte...
*(unsigned char *)pDest = (char)ReadFrame_EthMAC();// the LANController will return 0
}
// for the
highbyte
}

// does a dummy read on frame-I/O-port


// NOTE: only an even number of bytes is read!
void DummyReadFrame_EthMAC(unsigned short Size)
EVEN number of bytes
{
while (Size > 1) {
// Code Red - updated for LPC1776
//
ReadFrame8900();
ReadFrame_EthMAC();
Size -= 2;
}
}

// discards an
// from RX-fifo

void RequestSend(unsigned short FrameSize)


{
unsigned int index;
index = LPC_EMAC->TxProduceIndex;
txptr = (unsigned short *)TX_DESC_PACKET(index);
TX_DESC_CTRL(index) = FrameSize | TCTRL_LAST;
}
// frame we want to send
unsigned int Rdy4Tx(void)
{
// Code Red - updated for LPC1768
// Write8900(ADD_PORT, PP_BusST);
// return (Read8900(DATA_PORT) & READY_FOR_TX_NOW);
// One the LPC the ethernet controller transmits
// much faster than the CPU can load its buffers
// so will always be ready to accept frame
return (1);
//
}
// CodeRed - New function
// Reads length of received ethernet frame and checks
// if destination address is a broadcast message or not.
86

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// Then returns the frame length
unsigned short StartReadingFrame(void)
{
unsigned short ReceiveLength;
unsigned int index;
index = LPC_EMAC->RxConsumeIndex;
ReceiveLength = (RX_STAT_INFO(index) & RINFO_SIZE) - 3;
rxptr = (unsigned short *)RX_DESC_PACKET(index);
return(ReceiveLength);
}
// CodeRed - new function
void StopReadingFrame(void)
{
unsigned int index;
index = LPC_EMAC->RxConsumeIndex;
if (++index == NUM_RX_FRAG) index = 0;
LPC_EMAC->RxConsumeIndex = index;
}
// CodeRed - new function to check if frame has been received
unsigned int CheckIfFrameReceived(void)
{
if (LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex)
return(1); // Yes, packet received
else
return(0);
}

2. ETHMAC.H
#ifndef __ETHMAC_H
#define __ETHMAC_H
#define
address
#define
#define
#define
#define
#define

MYMAC_1

// our ethernet (MAC)

MYMAC_2
MYMAC_3
MYMAC_4
MYMAC_5
MYMAC_6

2
3
4
5
6

// (MUST be unique in LAN!)

/* EMAC
#define
4*1536=
#define
3*1536=
#define
Bytes

Memory Buffer configuration for 16K Ethernet RAM. */


NUM_RX_FRAG
4
/* Num.of RX Fragments
6.0kB */
NUM_TX_FRAG
2
/* Num.of TX Fragments
4.6kB */
ETH_FRAG_SIZE
1536
/* Packet Fragment size 1536
*/

#define ETH_MAX_FLEN
*/
87

1536

/* Max. Ethernet Frame Size

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


/* EMAC variables located in AHB SRAM bank 1*/
// Below is base address for first silicon
//#define RX_DESC_BASE
0x20004000
// Below is base address for production silicon
#define RX_DESC_BASE
0x2007c000
#define RX_STAT_BASE
(RX_DESC_BASE + NUM_RX_FRAG*8)
#define TX_DESC_BASE
(RX_STAT_BASE + NUM_RX_FRAG*8)
#define TX_STAT_BASE
(TX_DESC_BASE + NUM_TX_FRAG*8)
#define RX_BUF_BASE
(TX_STAT_BASE + NUM_TX_FRAG*4)
#define TX_BUF_BASE
(RX_BUF_BASE +
NUM_RX_FRAG*ETH_FRAG_SIZE)
/* RX and TX descriptor and
#define RX_DESC_PACKET(i)
8*i))
#define RX_DESC_CTRL(i)
8*i))
#define RX_STAT_INFO(i)
8*i))
#define RX_STAT_HASHCRC(i)
8*i))
#define TX_DESC_PACKET(i)
8*i))
#define TX_DESC_CTRL(i)
8*i))
#define TX_STAT_INFO(i)
4*i))
#define RX_BUF(i)
#define TX_BUF(i)

status definitions. */
(*(unsigned int *)(RX_DESC_BASE

(*(unsigned int *)(RX_DESC_BASE+4 +


(*(unsigned int *)(RX_STAT_BASE

(*(unsigned int *)(RX_STAT_BASE+4 +


(*(unsigned int *)(TX_DESC_BASE

(*(unsigned int *)(TX_DESC_BASE+4 +


(*(unsigned int *)(TX_STAT_BASE

(RX_BUF_BASE + ETH_FRAG_SIZE*i)
(TX_BUF_BASE + ETH_FRAG_SIZE*i)

/* MAC Configuration Register 1 */


#define MAC1_REC_EN
0x00000001
*/
#define MAC1_PASS_ALL
0x00000002
*/
#define MAC1_RX_FLOWC
0x00000004
*/
#define MAC1_TX_FLOWC
0x00000008
*/
#define MAC1_LOOPB
0x00000010
*/
#define MAC1_RES_TX
0x00000100
*/
#define MAC1_RES_MCS_TX
0x00000200
Sublayer
*/
#define MAC1_RES_RX
0x00000400
*/
#define MAC1_RES_MCS_RX
0x00000800
Sublayer
*/
#define MAC1_SIM_RES
0x00004000
*/
#define MAC1_SOFT_RES
0x00008000
*/

/* Receive Enable
/* Pass All Receive Frames
/* RX Flow Control
/* TX Flow Control
/* Loop Back Mode
/* Reset TX Logic
/* Reset MAC TX Control
/* Reset RX Logic
/* Reset MAC RX Control
/* Simulation Reset
/* Soft Reset MAC

/* MAC Configuration Register 2 */


88

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
Backoff
#define
*/

MAC2_FULL_DUP

0x00000001

/* Full Duplex Mode

MAC2_FRM_LEN_CHK

0x00000002

/* Frame Length Checking

MAC2_HUGE_FRM_EN

0x00000004

/* Huge Frame Enable

MAC2_DLY_CRC

0x00000008

/* Delayed CRC Mode

MAC2_CRC_EN

0x00000010

/* Append CRC to every Frame

MAC2_PAD_EN

0x00000020

/* Pad all Short Frames

MAC2_VLAN_PAD_EN

0x00000040

/* VLAN Pad Enable

MAC2_ADET_PAD_EN

0x00000080

/* Auto Detect Pad Enable

MAC2_PPREAM_ENF

0x00000100

/* Pure Preamble Enforcement

MAC2_LPREAM_ENF

0x00000200

/* Long Preamble Enforcement

MAC2_NO_BACKOFF

0x00001000

/* No Backoff Algorithm

MAC2_BACK_PRESSURE
*/
MAC2_EXCESS_DEF

0x00002000

/* Backoff Presurre / No

0x00004000

/* Excess Defer

/* Back-to-Back Inter-Packet-Gap Register */


#define IPGT_FULL_DUP
0x00000015 /* Recommended value for
Full Duplex */
#define IPGT_HALF_DUP
0x00000012 /* Recommended value for
Half Duplex */
/* Non Back-to-Back Inter-Packet-Gap Register */
#define IPGR_DEF
0x00000012 /* Recommended value
*/
/* Collision Window/Retry Register */
#define CLRT_DEF
0x0000370F
*/

/* Default value

/* PHY Support Register */


#define SUPP_SPEED
Speed
*/

0x00000100

/* Reduced MII Logic Current

Register */
TEST_SHCUT_PQUANTA

0x00000001

/* Shortcut Pause Quanta

TEST_TST_PAUSE

0x00000002

/* Test Pause

TEST_TST_BACKP

0x00000004

/* Test Back Pressure

/* Test
#define
*/
#define
*/
#define
*/

/* MII Management Configuration Register */

89

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define MCFG_SCAN_INC
Address
*/
#define MCFG_SUPP_PREAM
*/
#define MCFG_CLK_SEL
*/
#define MCFG_RES_MII
Hardware
*/

0x00000001

/* Scan Increment PHY

0x00000002

/* Suppress Preamble

0x0000001C

/* Clock Select Mask

0x00008000

/* Reset MII Management

#define MCFG_CLK_DIV28
#define MCFG_CLK_DIV36
#define MCFG_CLK_DIV64

0x0000001C /* MDC = hclk / 28 */


0x00000020
0x0000003c

/* MII Management Command Register */


#define MCMD_READ
0x00000001
*/
#define MCMD_SCAN
0x00000002
*/
#define MII_WR_TOUT
*/
#define MII_RD_TOUT
*/

/* MII Read
/* MII Scan continuously

0x00050000

/* MII Write timeout count

0x00050000

/* MII Read timeout count

/* MII Management Address Register */


#define MADR_REG_ADR
0x0000001F
*/
#define MADR_PHY_ADR
0x00001F00
*/

/* MII Register Address Mask


/* PHY Address Mask

/* MII Management Indicators Register */


#define MIND_BUSY
0x00000001 /*
*/
#define MIND_SCAN
0x00000002 /*
*/
#define MIND_NOT_VAL
0x00000004 /*
*/
#define MIND_MII_LINK_FAIL 0x00000008 /*
*/
/* Command Register */
#define CR_RX_EN
*/
#define CR_TX_EN
*/
#define CR_REG_RES
*/
#define CR_TX_RES
*/
#define CR_RX_RES
*/
#define CR_PASS_RUNT_FRM
*/
#define CR_PASS_RX_FILT
*/
90

MII is Busy
MII Scanning in Progress
MII Read Data not valid
MII Link Failed

0x00000001

/* Enable Receive

0x00000002

/* Enable Transmit

0x00000008

/* Reset Host Registers

0x00000010

/* Reset Transmit Datapath

0x00000020

/* Reset Receive Datapath

0x00000040

/* Pass Runt Frames

0x00000080

/* Pass RX Filter

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define CR_TX_FLOW_CTRL
*/
#define CR_RMII
*/
#define CR_FULL_DUP
*/
/* Status Register */
#define SR_RX_EN
*/
#define SR_TX_EN
*/

0x00000100

/* TX Flow Control

0x00000200

/* Reduced MII Interface

0x00000400

/* Full Duplex

0x00000001

/* Enable Receive

0x00000002

/* Enable Transmit

/* Transmit Status Vector 0 Register */


#define TSV0_CRC_ERR
0x00000001
*/
#define TSV0_LEN_CHKERR
0x00000002
*/
#define TSV0_LEN_OUTRNG
0x00000004
*/
#define TSV0_DONE
0x00000008
*/
#define TSV0_MCAST
0x00000010
*/
#define TSV0_BCAST
0x00000020
*/
#define TSV0_PKT_DEFER
0x00000040
*/
#define TSV0_EXC_DEFER
0x00000080
*/
#define TSV0_EXC_COLL
0x00000100
*/
#define TSV0_LATE_COLL
0x00000200
*/
#define TSV0_GIANT
0x00000400
*/
#define TSV0_UNDERRUN
0x00000800
*/
#define TSV0_BYTES
0x0FFFF000
*/
#define TSV0_CTRL_FRAME
0x10000000
*/
#define TSV0_PAUSE
0x20000000
*/
#define TSV0_BACK_PRESS
0x40000000
Applied
*/
#define TSV0_VLAN
0x80000000
*/

/* CRC error
/* Length Check Error
/* Length Out of Range
/* Tramsmission Completed
/* Multicast Destination
/* Broadcast Destination
/* Packet Deferred
/* Excessive Packet Deferral
/* Excessive Collision
/* Late Collision Occured
/* Giant Frame
/* Buffer Underrun
/* Total Bytes Transferred
/* Control Frame
/* Pause Frame
/* Backpressure Method
/* VLAN Frame

/* Transmit Status Vector 1 Register */


#define TSV1_BYTE_CNT
0x0000FFFF /* Transmit Byte Count
*/
#define TSV1_COLL_CNT
0x000F0000 /* Transmit Collision Count
*/

91

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


/* Receive Status Vector Register */
#define RSV_BYTE_CNT
0x0000FFFF
*/
#define RSV_PKT_IGNORED
0x00010000
*/
#define RSV_RXDV_SEEN
0x00020000
Seen
*/
#define RSV_CARR_SEEN
0x00040000
Seen
*/
#define RSV_REC_CODEV
0x00080000
*/
#define RSV_CRC_ERR
0x00100000
*/
#define RSV_LEN_CHKERR
0x00200000
*/
#define RSV_LEN_OUTRNG
0x00400000
*/
#define RSV_REC_OK
0x00800000
*/
#define RSV_MCAST
0x01000000
*/
#define RSV_BCAST
0x02000000
*/
#define RSV_DRIB_NIBB
0x04000000
*/
#define RSV_CTRL_FRAME
0x08000000
*/
#define RSV_PAUSE
0x10000000
*/
#define RSV_UNSUPP_OPC
0x20000000
*/
#define RSV_VLAN
0x40000000
*/
/* Flow Control Counter Register */
#define FCC_MIRR_CNT
0x0000FFFF
*/
#define FCC_PAUSE_TIM
0xFFFF0000
*/
/* Flow Control Status Register */
#define FCS_MIRR_CNT
0x0000FFFF
*/
/* Receive Filter Control Register */
#define RFC_UCAST_EN
0x00000001
Enable
*/
#define RFC_BCAST_EN
0x00000002
Enable
*/
#define RFC_MCAST_EN
0x00000004
Enable
*/
#define RFC_UCAST_HASH_EN
0x00000008
Filter Frames */
#define RFC_MCAST_HASH_EN
0x00000010
Filter Fram.*/
92

/* Receive Byte Count


/* Packet Previously Ignored
/* RXDV Event Previously
/* Carrier Event Previously
/* Receive Code Violation
/* CRC Error
/* Length Check Error
/* Length Out of Range
/* Frame Received OK
/* Multicast Frame
/* Broadcast Frame
/* Dribble Nibble
/* Control Frame
/* Pause Frame
/* Unsupported Opcode
/* VLAN Frame

/* Mirror Counter
/* Pause Timer

/* Mirror Counter Current

/* Accept Unicast Frames


/* Accept Broadcast Frames
/* Accept Multicast Frames
/* Accept Unicast Hash
/* Accept Multicast Hash

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define RFC_PERFECT_EN
Enable
*/
#define RFC_MAGP_WOL_EN
Enable
*/
#define RFC_PFILT_WOL_EN
*/

0x00000020

/* Accept Perfect Match

0x00001000

/* Magic Packet Filter WoL

0x00002000

/* Perfect Filter WoL Enable

/* Receive Filter WoL Status/Clear Registers */


#define WOL_UCAST
0x00000001 /* Unicast Frame caused WoL
*/
#define WOL_BCAST
0x00000002 /* Broadcast Frame caused
WoL
*/
#define WOL_MCAST
0x00000004 /* Multicast Frame caused
WoL
*/
#define WOL_UCAST_HASH
0x00000008 /* Unicast Hash Filter Frame
WoL
*/
#define WOL_MCAST_HASH
0x00000010 /* Multicast Hash Filter
Frame WoL
*/
#define WOL_PERFECT
0x00000020 /* Perfect Filter WoL
*/
#define WOL_RX_FILTER
0x00000080 /* RX Filter caused WoL
*/
#define WOL_MAG_PACKET
0x00000100 /* Magic Packet Filter
caused WoL
*/
/* Interrupt Status/Enable/Clear/Set Registers */
#define INT_RX_OVERRUN
0x00000001 /* Overrun Error in RX Queue
*/
#define INT_RX_ERR
0x00000002 /* Receive Error
*/
#define INT_RX_FIN
0x00000004 /* RX Finished Process
Descriptors
*/
#define INT_RX_DONE
0x00000008 /* Receive Done
*/
#define INT_TX_UNDERRUN
0x00000010 /* Transmit Underrun
*/
#define INT_TX_ERR
0x00000020 /* Transmit Error
*/
#define INT_TX_FIN
0x00000040 /* TX Finished Process
Descriptors
*/
#define INT_TX_DONE
0x00000080 /* Transmit Done
*/
#define INT_SOFT_INT
0x00001000 /* Software Triggered
Interrupt
*/
#define INT_WAKEUP
0x00002000 /* Wakeup Event Interrupt
*/
/* Power Down Register */
#define PD_POWER_DOWN
*/

0x80000000

/* RX Descriptor Control Word */


#define RCTRL_SIZE
0x000007FF
*/

93

/* Power Down MAC

/* Buffer size mask

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define RCTRL_INT
*/

0x80000000

/* RX Status Hash CRC Word */


#define RHASH_SA
0x000001FF
Address
*/
#define RHASH_DA
0x001FF000
Address */
/* RX Status Information Word */
#define RINFO_SIZE
0x000007FF
*/
#define RINFO_CTRL_FRAME
0x00040000
*/
#define RINFO_VLAN
0x00080000
*/
#define RINFO_FAIL_FILT
0x00100000
*/
#define RINFO_MCAST
0x00200000
*/
#define RINFO_BCAST
0x00400000
*/
#define RINFO_CRC_ERR
0x00800000
*/
#define RINFO_SYM_ERR
0x01000000
*/
#define RINFO_LEN_ERR
0x02000000
*/
#define RINFO_RANGE_ERR
0x04000000
max. size) */
#define RINFO_ALIGN_ERR
0x08000000
*/
#define RINFO_OVERRUN
0x10000000
*/
#define RINFO_NO_DESCR
0x20000000
available
*/
#define RINFO_LAST_FLAG
0x40000000
*/
#define RINFO_ERR
0x80000000
errors) */
#define RINFO_ERR_MASK
RINFO_SYM_ERR | \

/* Generate RxDone Interrupt

/* Hash CRC for Source


/* Hash CRC for Destination

/* Data size in bytes


/* Control Frame
/* VLAN Frame
/* RX Filter Failed
/* Multicast Frame
/* Broadcast Frame
/* CRC Error in Frame
/* Symbol Error from PHY
/* Length Error
/* Range Error (exceeded
/* Alignment Error
/* Receive overrun
/* No new Descriptor
/* Last Fragment in Frame
/* Error Occured (OR of all

(RINFO_FAIL_FILT | RINFO_CRC_ERR
RINFO_LEN_ERR

| RINFO_ALIGN_ERR |

RINFO_OVERRUN)
/* TX Descriptor Control Word */
#define TCTRL_SIZE
0x000007FF
bytes
*/
#define TCTRL_OVERRIDE
0x04000000
Registers
*/
#define TCTRL_HUGE
0x08000000
*/
#define TCTRL_PAD
0x10000000
bytes
*/
94

/* Size of data buffer in


/* Override Default MAC
/* Enable Huge Frame
/* Pad short Frames to 64

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define TCTRL_CRC
Frame
*/
#define TCTRL_LAST
Frame
*/
#define TCTRL_INT
*/

0x20000000

/* Append a hardware CRC to

0x40000000

/* Last Descriptor for TX

0x80000000

/* Generate TxDone Interrupt

/* TX Status Information Word */


#define TINFO_COL_CNT
0x01E00000
*/
#define TINFO_DEFER
0x02000000
error)
*/
#define TINFO_EXCESS_DEF
0x04000000
*/
#define TINFO_EXCESS_COL
0x08000000
*/
#define TINFO_LATE_COL
0x10000000
*/
#define TINFO_UNDERRUN
0x20000000
*/
#define TINFO_NO_DESCR
0x40000000
available
*/
#define TINFO_ERR
0x80000000
errors) */
/* ENET Device Revision ID */
#define OLD_EMAC_MODULE_ID 0x39022000
*/
/* DP83848C PHY Registers */
#define PHY_REG_BMCR
0x00
Register
*/
#define PHY_REG_BMSR
0x01
Register
*/
#define PHY_REG_IDR1
0x02
*/
#define PHY_REG_IDR2
0x03
*/
#define PHY_REG_ANAR
0x04
Advertisement
*/
#define PHY_REG_ANLPAR
0x05
Abitily
*/
#define PHY_REG_ANER
0x06
Register
*/
#define PHY_REG_ANNPTR
0x07
*/
/* PHY Extended Registers */
#define PHY_REG_STS
0x10
*/
#define PHY_REG_MICR
0x11
Register
*/
#define PHY_REG_MISR
0x12
Register
*/

95

/* Collision Count
/* Packet Deferred (not an
/* Excessive Deferral
/* Excessive Collision
/* Late Collision Occured
/* Transmit Underrun
/* No new Descriptor
/* Error Occured (OR of all

/* Rev. ID for first rev '-'

/* Basic Mode Control


/* Basic Mode Status
/* PHY Identifier 1
/* PHY Identifier 2
/* Auto-Negotiation
/* Auto-Neg. Link Partner
/* Auto-Neg. Expansion
/* Auto-Neg. Next Page TX

/* Status Register
/* MII Interrupt Control
/* MII Interrupt Status

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define PHY_REG_FCSCR
Counter
*/
#define PHY_REG_RECR
*/
#define PHY_REG_PCSR
Status
*/
#define PHY_REG_RBR
*/
#define PHY_REG_LEDCR
Register
*/
#define PHY_REG_PHYCR
*/
#define PHY_REG_10BTSCR
Register */
#define PHY_REG_CDCTRL1
Extens. */
#define PHY_REG_EDCR
Register
*/
#define
*/
#define
*/
#define
*/
#define
*/
#define
*/

0x14

/* False Carrier Sense

0x15

/* Receive Error Counter

0x16

/* PCS Sublayer Config. and

0x17

/* RMII and Bypass Register

0x18

/* LED Direct Control

0x19

/* PHY Control Register

0x1A

/* 10Base-T Status/Control

0x1B

/* CD Test Control and BIST

0x1D

/* Energy Detect Control

PHY_FULLD_100M

0x2100

/* Full Duplex 100Mbit

PHY_HALFD_100M

0x2000

/* Half Duplex 100Mbit

PHY_FULLD_10M

0x0100

/* Full Duplex 10Mbit

PHY_HALFD_10M

0x0000

/* Half Duplex 10MBit

PHY_AUTO_NEG

0x3000

/* Select Auto Negotiation

0x0100

/* Default PHY device

0x20005C90

/* PHY Identifier

#define DP83848C_DEF_ADR
address
*/
#define DP83848C_ID
*/

/*************************************************
* CodeRed - PHY definitions for RDB1768 rev 2
* which uses SMSC LAN8720 PHY instead of DP83848C
*************************************************/
#define LAN8720_ID
0x0007C0F0 /* PHY Identifier
*/
void Init_EthMAC(void);
unsigned short ReadFrameBE_EthMAC(void);
void CopyToFrame_EthMAC(void *Source, unsigned int Size);
void CopyFromFrame_EthMAC(void *Dest, unsigned short Size);
void DummyReadFrame_EthMAC(unsigned short Size);
void RequestSend(unsigned short FrameSize);
unsigned int Rdy4Tx(void);
unsigned short StartReadingFrame(void);
void StopReadingFrame(void);
unsigned int CheckIfFrameReceived(void);
#endif

96

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


3. TCPIP.C
#include "tcpip.h"
//CodeRed - added header for LPC ethernet controller
#include "ethmac.h"
// CodeRed - added library string handling header
#include <string.h>
// CodeRed - added NXP LPC register definitions header
#include "LPC17xx.h"
void Start_SysTick10ms(void);
const unsigned char MyMAC[6] =
{
MYMAC_6, MYMAC_5, MYMAC_4,
MYMAC_3, MYMAC_2, MYMAC_1
};

// "M1-M2-M3-M4-M5-M6"

// easyWEB-API function
// initalizes the LAN-controller, reset flags, starts timer-ISR
void TCPLowLevelInit(void)
{
LPC_GPIO1->FIODIR = 1 << 25;
// P1.25 defined as
Output (LED)
Start_SysTick10ms();
// Start SysTick timer running (10ms
ticks)
Init_EthMAC();
TransmitControl = 0;
TCPFlags = 0;
TCPStateMachine = CLOSED;
SocketStatus = 0;
}
// easyWEB-API function
// does a passive open (listen on 'MyIP:TCPLocalPort' for an
incoming
// connection)
void TCPPassiveOpen(void)
{
if (TCPStateMachine == CLOSED)
{
TCPFlags &= ~TCP_ACTIVE_OPEN;
passive open!
TCPStateMachine = LISTENING;
SocketStatus = SOCK_ACTIVE;
now active
}
}

// let's do a
// reset, socket

// easyWEB-API function
// does an active open (tries to establish a connection between
// 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')
void TCPActiveOpen(void)
97

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


{
if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING))
{
TCPFlags |= TCP_ACTIVE_OPEN;
// let's do an
active open!
TCPFlags &= ~IP_ADDR_RESOLVED;
// we haven't
opponents MAC yet
PrepareARP_REQUEST();
sending a broadcast
LastFrameSent = ARP_REQUEST;
TCPStartRetryTimer();
SocketStatus = SOCK_ACTIVE;
now active
}
}

// ask for MAC by

// reset, socket

// easyWEB-API function
// closes an open connection
void TCPClose(void)
{
switch (TCPStateMachine)
{
case LISTENING :
case SYN_SENT :
{
TCPStateMachine = CLOSED;
TCPFlags = 0;
SocketStatus = 0;
break;
}
case SYN_RECD :
case ESTABLISHED :
{
TCPFlags |= TCP_CLOSE_REQUESTED;
break;
}
}
}
// easyWEB-API function
// releases the receive-buffer and allows easyWEB to store new data
// NOTE: rx-buffer MUST be released periodically, else the other TCP
//
get no ACKs for the data it sent
void TCPReleaseRxBuffer(void)
{
SocketStatus &= ~SOCK_DATA_AVAILABLE;
}
// easyWEB-API function
// transmitts data stored in 'TCP_TX_BUF'
// NOTE: * number of bytes to transmit must have been written to
'TCPTxDataCount'
98

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


//

* data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'

void TCPTransmitTxBuffer(void)
{
if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine ==
CLOSE_WAIT))
if (SocketStatus & SOCK_TX_BUF_RELEASED)
{
SocketStatus &= ~SOCK_TX_BUF_RELEASED;
// occupy
tx-buffer
TCPUNASeqNr += TCPTxDataCount;
//
advance UNA
TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE +
TCP_HEADER_SIZE + TCPTxDataCount;
TransmitControl |= SEND_FRAME1;
LastFrameSent = TCP_DATA_FRAME;
TCPStartRetryTimer();
}
}
// CodeRed - New function to check if received frame
// was a broadcast message
// Reads the length of the received ethernet frame and checks if the
// destination address is a broadcast message or not
unsigned int BroadcastMessage(void)
{
unsigned short FrameDestination[3]; // to hold 48 bit MAC address
RecdFrameLength = StartReadingFrame();
// Read destination address
CopyFromFrame_EthMAC(&FrameDestination,
// Save it for reply
CopyFromFrame_EthMAC(&RecdFrameMAC, 6);

6);

if ((FrameDestination[0] == 0xFFFF) &&


(FrameDestination[1] == 0xFFFF) &&
(FrameDestination[2] == 0xFFFF)) {
return(1); // Broadcast message
} else {
return (0);
}
}
// easyWEB's 'main()'-function
// must be called from user program periodically (the often - the
better)
// handles network, TCP/IP-stack and user events
void DoNetworkStuff(void)
{
99

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// Check to see if packet received
if (CheckIfFrameReceived())
{
// Was it a broadcast message?
if (BroadcastMessage()) {
ProcessEthBroadcastFrame();
}
else {
ProcessEthIAFrame();
}
// now release ethernet controller buffer
StopReadingFrame();
}
// CodeRed - now back to original code
if (TCPFlags & TCP_TIMER_RUNNING)
if (TCPFlags & TIMER_TYPE_RETRY)
{
if (TCPTimer > RETRY_TIMEOUT)
{
TCPRestartTimer();
timeout
if (RetryCounter)
{
TCPHandleRetransmission();

// set a new

// resend last

frame
RetryCounter--;
}
else
{
TCPStopTimer();
TCPHandleTimeout();
}
}
}
else if (TCPTimer > FIN_TIMEOUT)
{
TCPStateMachine = CLOSED;
TCPFlags = 0;
stop retransmission...
SocketStatus &= SOCK_DATA_AVAILABLE;
but data available
}

// reset all flags,


// clear all flags

switch (TCPStateMachine)
{
case CLOSED :
case LISTENING :
{
if (TCPFlags & TCP_ACTIVE_OPEN)
// stack has to
open a connection?
if (TCPFlags & IP_ADDR_RESOLVED)
// IP resolved?
if (!(TransmitControl & SEND_FRAME2)) // buffer free?
{
// CodeRed - change TAR -> TOTC to use LPC1768 clock
100

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


//
TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; //
set local ISN
TCPSeqNr = ((unsigned long)ISNGenHigh << 16) |
(LPC_TIM0->TC & 0xFFFF); // set local ISN
TCPUNASeqNr = TCPSeqNr;
TCPAckNr = 0;
//
we don't know what to ACK!
TCPUNASeqNr++;
//
count SYN as a byte
PrepareTCP_FRAME(TCP_CODE_SYN);
//
send SYN frame
LastFrameSent = TCP_SYN_FRAME;
TCPStartRetryTimer();
//
we NEED a retry-timeout
TCPStateMachine = SYN_SENT;
}
break;
}
case SYN_RECD :
case ESTABLISHED :
{
if (TCPFlags & TCP_CLOSE_REQUESTED)
// user
has user initated a close?
if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))
//
buffers free?
if (TCPSeqNr == TCPUNASeqNr)
//
all data ACKed?
{
TCPUNASeqNr++;
PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
LastFrameSent = TCP_FIN_FRAME;
TCPStartRetryTimer();
TCPStateMachine = FIN_WAIT_1;
}
break;
}
case CLOSE_WAIT :
{
if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))
//
buffers free?
if (TCPSeqNr == TCPUNASeqNr)
//
all data ACKed?
{
TCPUNASeqNr++;
//
count FIN as a byte
PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
//
we NEED a retry-timeout
LastFrameSent = TCP_FIN_FRAME;
//
time to say goodbye...
TCPStartRetryTimer();
TCPStateMachine = LAST_ACK;
}
break;
}
}
101

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


if (TransmitControl & SEND_FRAME2)
{
RequestSend(TxFrame2Size);
if (Rdy4Tx())
a very fast MCU, maybe
SendFrame2();
ready yet, include
else {
or counter here
TCPStateMachine = CLOSED;
SocketStatus = SOCK_ERR_ETHERNET;
error to user
TCPFlags = 0;
stop timers etc.
}
TransmitControl &= ~SEND_FRAME2;

// NOTE: when using


// the CS8900 isn't
// a kind of timer
// indicate an
// clear all flags,

// clear tx-flag

}
if (TransmitControl & SEND_FRAME1)
{
PrepareTCP_DATA_FRAME();
actual SEQ, ACK....
RequestSend(TxFrame1Size);
if (Rdy4Tx())
accept our frame?
SendFrame1();
else {
TCPStateMachine = CLOSED;
SocketStatus = SOCK_ERR_ETHERNET;
error to user
TCPFlags = 0;
stop timers etc.
}
TransmitControl &= ~SEND_FRAME1;

// build frame w/

// CS8900 ready to
// (see note above)
// indicate an
// clear all flags,

// clear tx-flag

}
}
// easyWEB internal function
// handles an incoming broadcast frame
void ProcessEthBroadcastFrame(void)
{
unsigned short TargetIP[2];
if (ReadFrameBE_EthMAC() == FRAME_ARP)
type, check for ARP
if (ReadFrameBE_EthMAC() == HARDW_ETH10)
frame
if (ReadFrameBE_EthMAC() == FRAME_IP)
protocol
if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN)
PLEN
102

Department Of Electronics Engineering| AISSMSCOE,Pune

// get frame
// Ethernet
// check
// check HLEN,

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


if (ReadFrameBE_EthMAC() == OP_ARP_REQUEST)
{
DummyReadFrame_EthMAC(6);
// ignore
sender's hardware address
CopyFromFrame_EthMAC(&RecdFrameIP, 4); // read sender's
protocol address
DummyReadFrame_EthMAC(6);
// ignore
target's hardware address
CopyFromFrame_EthMAC(&TargetIP, 4);
// read target's
protocol address
if (!memcmp(&MyIP, &TargetIP, 4))
// is it for us?
PrepareARP_ANSWER();
// yes->create
ARP_ANSWER frame
}
}
// easyWEB internal function
// handles an incoming frame that passed CS8900's address filter
// (individual addressed = IA)
void ProcessEthIAFrame(void)
{
// CodeRed - change from int to short
//unsigned int TargetIP[2];
unsigned short TargetIP[2];
unsigned char ProtocolType;
switch (ReadFrameBE_EthMAC())
// get frame
type
{
case FRAME_ARP :
// check for ARP
{
if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) ==
TCP_ACTIVE_OPEN)
if (ReadFrameBE_EthMAC() == HARDW_ETH10)
// check
for the right prot. etc.
if (ReadFrameBE_EthMAC() == FRAME_IP)
if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN)
if (ReadFrameBE_EthMAC() == OP_ARP_ANSWER)
{
TCPStopTimer();
// OK, now
we've the MAC we wanted ;-)
CopyFromFrame_EthMAC(&RemoteMAC, 6);
// extract
opponents MAC
TCPFlags |= IP_ADDR_RESOLVED;
}
break;
}
case FRAME_IP :
// check
for IP-type
{
if ((ReadFrameBE_EthMAC() & 0xFF00 ) == IP_VER_IHL)
//
IPv4, IHL=5 (20 Bytes Header)
{
// ignore
Type Of Service

103

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


RecdIPFrameLength = ReadFrameBE_EthMAC();
IP frame's length
ReadFrameBE_EthMAC();
ignore identification

// get
//

if (!(ReadFrameBE_EthMAC() & (IP_FLAG_MOREFRAG |


IP_FRAGOFS_MASK))) // only unfragm. frames
{
// CodeRed - add mask
//
ProtocolType = ReadFrameBE_EthMAC() ;
get protocol, ignore TTL
ProtocolType = ReadFrameBE_EthMAC() & 0xFF ;
// get protocol, ignore TTL
ReadFrameBE_EthMAC();
ignore checksum
CopyFromFrame_EthMAC(&RecdFrameIP, 4);
source IP
CopyFromFrame_EthMAC(&TargetIP, 4);
destination IP
if (!memcmp(&MyIP, &TargetIP, 4))

//

//
// get
// get
// is it

for us?
switch
case
case
case
implemented!
}
}
}
break;
}
}
}

(ProtocolType) {
PROT_ICMP : { ProcessICMPFrame(); break; }
PROT_TCP : { ProcessTCPFrame(); break; }
PROT_UDP : break;
// not

// easyWEB internal function


// we've just rec'd an ICMP-frame (Internet Control Message
Protocol)
// check what to do and branch to the appropriate sub-function
void ProcessICMPFrame(void)
{
unsigned short ICMPTypeAndCode;
ICMPTypeAndCode = ReadFrameBE_EthMAC();
Type and Code
ReadFrameBE_EthMAC();
checksum
switch (ICMPTypeAndCode >> 8) {
case ICMP_ECHO :
{
PrepareICMP_ECHO_REPLY();
we can...
break;
104

Department Of Electronics Engineering| AISSMSCOE,Pune

// get Message
// ignore ICMP
// check type
// is echo request?
// echo as much as

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
}
}
//
//
//
to

easyWEB internal function


we've just rec'd an TCP-frame (Transmission Control Protocol)
this function mainly implements the TCP state machine according
RFC793

void ProcessTCPFrame(void)
{
unsigned short TCPSegSourcePort;
source port
unsigned short TCPSegDestPort;
destination port
unsigned long TCPSegSeq;
sequence number
unsigned long TCPSegAck;
acknowledge number
unsigned short TCPCode;
header length
unsigned char TCPHeaderSize;
length
unsigned short NrOfDataBytes;
data

// segment's
// segment's
// segment's
// segment's
// TCP code and
// real TCP header
// real number of

TCPSegSourcePort = ReadFrameBE_EthMAC();
ports
TCPSegDestPort = ReadFrameBE_EthMAC();
if (TCPSegDestPort != TCPLocalPort) return;
segment if port doesn't match

// get

// drop

TCPSegSeq = (unsigned long)ReadFrameBE_EthMAC() << 16;


segment sequence nr.
TCPSegSeq |= ReadFrameBE_EthMAC();

// get

TCPSegAck = (unsigned long)ReadFrameBE_EthMAC() << 16;


segment acknowledge nr.
TCPSegAck |= ReadFrameBE_EthMAC();

// get

TCPCode = ReadFrameBE_EthMAC();
control bits, header length...

// get

TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10;


length in bytes
NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE TCPHeaderSize;
// seg. text length

// header

if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return;


too large for us :...-(

// packet

105

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


if (TCPHeaderSize > TCP_HEADER_SIZE)
// ignore
options if any
DummyReadFrame_EthMAC(TCPHeaderSize - TCP_HEADER_SIZE);
switch (TCPStateMachine)
implement the TCP state machine
{
case CLOSED :
{
if (!(TCPCode & TCP_CODE_RST))
{
TCPRemotePort = TCPSegSourcePort;
memcpy(&RemoteMAC, &RecdFrameMAC, 6);
opponents MAC and IP
memcpy(&RemoteIP, &RecdFrameIP, 4);
later use

//

// save
// for

if (TCPCode & TCP_CODE_ACK)


// make
the reset sequence
{
//
acceptable to the other
TCPSeqNr = TCPSegAck;
// TCP
PrepareTCP_FRAME(TCP_CODE_RST);
}
else
{
TCPSeqNr = 0;
TCPAckNr = TCPSegSeq + NrOfDataBytes;
if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
PrepareTCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK);
}
}
break;
}
case LISTENING :
{
if (!(TCPCode & TCP_CODE_RST))
// ignore
segment containing RST
{
TCPRemotePort = TCPSegSourcePort;
memcpy(&RemoteMAC, &RecdFrameMAC, 6);
// save
opponents MAC and IP
memcpy(&RemoteIP, &RecdFrameIP, 4);
// for
later use
if (TCPCode & TCP_CODE_ACK)

// reset

a bad
{
acknowledgement
TCPSeqNr = TCPSegAck;
PrepareTCP_FRAME(TCP_CODE_RST);
}
else if (TCPCode & TCP_CODE_SYN)
{

106

Department Of Electronics Engineering| AISSMSCOE,Pune

//

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


TCPAckNr = TCPSegSeq + 1;
remote ISN, next byte we expect
// CodeRed - change TAR -> TOTC to use LPC1768 clock
//
TCPSeqNr = ((unsigned long)ISNGenHigh << 16)
set local ISN
TCPSeqNr = ((unsigned long)ISNGenHigh << 16) |
>TC & 0xFFFF); // set local ISN
TCPUNASeqNr = TCPSeqNr + 1;
byte out -> increase by one
PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
LastFrameSent = TCP_SYN_ACK_FRAME;
TCPStartRetryTimer();
TCPStateMachine = SYN_RECD;
}
}
break;
}
case SYN_SENT :
{
if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; //
segment if its IP doesn't belong
//
session
if (TCPSegSourcePort != TCPRemotePort) break;
segment if port doesn't match
if (TCPCode & TCP_CODE_ACK)
significant?
if (TCPSegAck != TCPUNASeqNr)
ACKed?
{
if (!(TCPCode & TCP_CODE_RST))
{
TCPSeqNr = TCPSegAck;
PrepareTCP_FRAME(TCP_CODE_RST);
}
break;
}
if (TCPCode & TCP_CODE_RST)
{
if (TCPCode & TCP_CODE_ACK)
acceptable, reset
{
TCPStateMachine = CLOSED;
TCPFlags = 0;
stop retransmission...
SocketStatus = SOCK_ERR_CONN_RESET;
}
break;
}
if (TCPCode & TCP_CODE_SYN)
{
107

Department Of Electronics Engineering| AISSMSCOE,Pune

// get
| TAR; //
(LPC_TIM0// one

drop
to current

// drop

// ACK field
// is our ISN

// drop segment
// RST??
// if ACK was
// connection
// reset all flags,

// drop segment
// SYN??

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


TCPAckNr = TCPSegSeq;

// get opponents

TCPAckNr++;

// inc. by one...

ISN
if (TCPCode & TCP_CODE_ACK)
{
TCPStopTimer();
retransmission, other TCP got our SYN
TCPSeqNr = TCPUNASeqNr;
sequence number

// stop
// advance our

PrepareTCP_FRAME(TCP_CODE_ACK);
// ACK this ISN
TCPStateMachine = ESTABLISHED;
SocketStatus |= SOCK_CONNECTED;
SocketStatus |= SOCK_TX_BUF_RELEASED; // user may send
data now :-)
}
else
{
TCPStopTimer();
PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
// our
SYN isn't ACKed yet,
LastFrameSent = TCP_SYN_ACK_FRAME;
// now
continue with sending
TCPStartRetryTimer();
//
SYN_ACK frames
TCPStateMachine = SYN_RECD;
}
}
break;
}
default :
{
if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop
segment if IP doesn't belong
// to current
session
if (TCPSegSourcePort != TCPRemotePort) break;
segment if port doesn't match

// drop

if (TCPSegSeq != TCPAckNr) break;


it's not the segment we expect

// drop if

if (TCPCode & TCP_CODE_RST)


{
TCPStateMachine = CLOSED;
machine
TCPFlags = 0;
stop retransmission...
SocketStatus = SOCK_ERR_CONN_RESET;
error to user
break;
}

108

Department Of Electronics Engineering| AISSMSCOE,Pune

// RST??
// close the state
// reset all flags,
// indicate an

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


if (TCPCode & TCP_CODE_SYN)
{
PrepareTCP_FRAME(TCP_CODE_RST);
here! send a reset,
TCPStateMachine = CLOSED;
connection...
TCPFlags = 0;
stop retransmission...
SocketStatus = SOCK_ERR_REMOTE;
break;
frame
}

// SYN??
// is NOT allowed
// close
// reset all flags,
// fatal error!
// ...and drop the

if (!(TCPCode & TCP_CODE_ACK)) break;


the ACK bit is off

// drop segment if

if (TCPSegAck == TCPUNASeqNr)
sent ACKed?
{
TCPStopTimer();
retransmission
TCPSeqNr = TCPUNASeqNr;
sequence number

// is our last data


// stop
// advance our

switch (TCPStateMachine)
// change state if
necessary
{
case SYN_RECD :
// ACK of our SYN?
{
TCPStateMachine = ESTABLISHED;
// user may send
data now :-)
SocketStatus |= SOCK_CONNECTED;
break;
}
case FIN_WAIT_1 : { TCPStateMachine = FIN_WAIT_2; break; }
// ACK of our FIN?
case CLOSING :
{ TCPStateMachine = TIME_WAIT; break; }
// ACK of our FIN?
case LAST_ACK :
// ACK of our FIN?
{
TCPStateMachine = CLOSED;
TCPFlags = 0;
// reset all flags,
stop retransmission...
SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags
but data available
break;
}
case TIME_WAIT :
{
PrepareTCP_FRAME(TCP_CODE_ACK);
// ACK a
retransmission of remote FIN
TCPRestartTimer();
// restart
TIME_WAIT timeout
break;
109

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
}
if (TCPStateMachine == ESTABLISHED)
the frame buffer back
SocketStatus |= SOCK_TX_BUF_RELEASED;
}

// if true, give
// to user

if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine ==


FIN_WAIT_1) || (TCPStateMachine == FIN_WAIT_2))
if (NrOfDataBytes)
// data
available?
if (!(SocketStatus & SOCK_DATA_AVAILABLE))
// rx
data-buffer empty?
{
DummyReadFrame_EthMAC(6);
//
ignore window, checksum, urgent pointer
CopyFromFrame_EthMAC(RxTCPBuffer, NrOfDataBytes);//
fetch data and
TCPRxDataCount = NrOfDataBytes;
...tell the user...
SocketStatus |= SOCK_DATA_AVAILABLE;
indicate the new data to user
TCPAckNr += NrOfDataBytes;
PrepareTCP_FRAME(TCP_CODE_ACK);
rec'd data
}
if (TCPCode & TCP_CODE_FIN)
{
switch (TCPStateMachine)
{
case SYN_RECD :
case ESTABLISHED :
{
TCPStateMachine = CLOSE_WAIT;
break;
}
case FIN_WAIT_1 :
{
ACKed, we automatically
TCPStateMachine = CLOSING;
(look above) and therefore
SocketStatus &= ~SOCK_CONNECTED;
break;
}
case FIN_WAIT_2 :
{
TCPStartTimeWaitTimer();
TCPStateMachine = TIME_WAIT;
SocketStatus &= ~SOCK_CONNECTED;
break;
}
case TIME_WAIT :
110

Department Of Electronics Engineering| AISSMSCOE,Pune

//
//
// ACK

// FIN??

// if our FIN was


// enter FIN_WAIT_2
// TIME_WAIT

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


{
TCPRestartTimer();
break;
}
}
TCPAckNr++;

// ACK remote's FIN

flag
PrepareTCP_FRAME(TCP_CODE_ACK);
}
}
}
}
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ARP-request
void PrepareARP_REQUEST(void)
{
// Ethernet
memset(&TxFrame2[ETH_DA_OFS], (char)0xFF, 6);
//
we don't know opposites MAC!
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
// ARP
*(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
*(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
*(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] =
SWAPB(IP_HLEN_PLEN);
*(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] =
SWAPB(OP_ARP_REQUEST);
memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
memset(&TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6);
don't know opposites MAC!

// we

if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) || ((RemoteIP[1] ^


MyIP[1]) & SubnetMask[1]))
memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &GatewayIP, 4);
// IP not
in subnet, use gateway
else
memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4);
// other
IP is next to us...
TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TransmitControl |= SEND_FRAME2;
}
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ARP-answer (reply)
void PrepareARP_ANSWER(void)
{
// Ethernet
111

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
// CodeRed - int-> short
// *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
// ARP
*(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
*(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
*(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] =
SWAPB(IP_HLEN_PLEN);
*(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] =
SWAPB(OP_ARP_ANSWER);
memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6);
memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4);
TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TransmitControl |= SEND_FRAME2;
}
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ICMP-echo-reply
void PrepareICMP_ECHO_REPLY(void)
{
unsigned short ICMPDataCount;
if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE)
// don't overload TX-buffer
ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE ICMP_HEADER_SIZE;
else
ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE ICMP_HEADER_SIZE;
// Ethernet
memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] =
SWAPB(IP_VER_IHL);
WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE +
ICMP_HEADER_SIZE + ICMPDataCount);
*(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL
<< 8) | PROT_ICMP);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
112

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] =
CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
// ICMP
*(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] =
SWAPB(ICMP_ECHO_REPLY << 8);
*(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;
// initialize checksum field
CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);
// get data to echo...
*(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] =
CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount +
ICMP_HEADER_SIZE, 0);
TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE
+ ICMPDataCount;
TransmitControl |= SEND_FRAME2;
}
// easyWEB internal function
// prepares the TxFrame2-buffer to send a general TCP frame
// the TCPCode-field is passed as an argument
void PrepareTCP_FRAME(unsigned short TCPCode)
{
// Ethernet
memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] =
SWAPB(IP_VER_IHL | IP_TOS_D);
if (TCPCode & TCP_CODE_SYN)
// if SYN, we want
to use the MSS option
*(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] =
SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
else
*(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] =
SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
*(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL
<< 8) | PROT_TCP);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] =
CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
// TCP
WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort);
113

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort);
WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr);
WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr);
*(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] =
SWAPB(MAX_TCP_RX_DATA_SIZE);
// data bytes to accept
*(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0;
initalize checksum
*(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0;

//

if (TCPCode & TCP_CODE_SYN)


// if SYN, we want
to use the MSS option
{
*(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 |
TCPCode);
// TCP header length = 24
*(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS);
// MSS option
*(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] =
SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
*(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] =
CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE +
TCP_OPT_MSS_SIZE, 1);
TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE +
TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
}
else
{
*(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 |
TCPCode);
// TCP header length = 20
*(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] =
CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE +
TCP_HEADER_SIZE;
}
TransmitControl |= SEND_FRAME2;
}
// easyWEB internal function
// prepares the TxFrame1-buffer to send a payload-packet
void PrepareTCP_DATA_FRAME(void)
{
// Ethernet
memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&TxFrame1[IP_VER_IHL_TOS_OFS] =
SWAPB(IP_VER_IHL | IP_TOS_D);
WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE +
TCP_HEADER_SIZE + TCPTxDataCount);
*(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
114

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


*(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL
<< 8) | PROT_TCP);
*(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
*(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] =
CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
// TCP
WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort);
WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort);
WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr);
WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr);
*(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 |
TCP_CODE_ACK);
// TCP header length = 20
*(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] =
SWAPB(MAX_TCP_RX_DATA_SIZE);
// data bytes to accept
*(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0;
*(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0;
*(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] =
CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE +
TCPTxDataCount, 1);
}
// easyWEB internal function
// calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudoheader
// will be included.
unsigned short CalcChecksum(void *Start, unsigned short Count,
unsigned char IsTCP)
{
// Code Red - added pStart
unsigned short *pStart;
unsigned long Sum = 0;
if (IsTCP) {
frame...
Sum += MyIP[0];
pseudo-header
Sum += MyIP[1];
Sum += RemoteIP[0];
Sum += RemoteIP[1];
Sum += SwapBytes(Count);
length plus data length
Sum += SWAPB(PROT_TCP);
}
pStart = Start;
while (Count > 1) {
Sum += *pStart++;
Count -= 2;
115

Department Of Electronics Engineering| AISSMSCOE,Pune

// if we've a TCP
// ...include TCP

// TCP header

// sum words

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


}
if (Count)
byte, if any
Sum += *(unsigned char *)pStart;

// add left-over

while (Sum >> 16)


to 16 bits
Sum = (Sum & 0xFFFF) + (Sum >> 16);

// fold 32-bit sum

return ~Sum;
}
// easyWEB internal function
// starts the timer as a retry-timer (used for retransmissiontimeout)
void TCPStartRetryTimer(void)
{
TCPTimer = 0;
RetryCounter = MAX_RETRYS;
TCPFlags |= TCP_TIMER_RUNNING;
TCPFlags |= TIMER_TYPE_RETRY;
}
// easyWEB internal function
// starts the timer as a 'TIME_WAIT'-timer (used to finish a TCPsession)
void TCPStartTimeWaitTimer(void)
{
TCPTimer = 0;
TCPFlags |= TCP_TIMER_RUNNING;
TCPFlags &= ~TIMER_TYPE_RETRY;
}
// easyWEB internal function
// restarts the timer
void TCPRestartTimer(void)
{
TCPTimer = 0;
}
// easyWEB internal function
// stopps the timer
void TCPStopTimer(void)
{
TCPFlags &= ~TCP_TIMER_RUNNING;
}
// easyWEB internal function
// if a retransmission-timeout occured, check which packet
116

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// to resend.
void TCPHandleRetransmission(void)
{
switch (LastFrameSent)
{
case ARP_REQUEST :
{ PrepareARP_REQUEST(); break; }
case TCP_SYN_FRAME :
{ PrepareTCP_FRAME(TCP_CODE_SYN);
break; }
case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN |
TCP_CODE_ACK); break; }
case TCP_FIN_FRAME :
{ PrepareTCP_FRAME(TCP_CODE_FIN |
TCP_CODE_ACK); break; }
case TCP_DATA_FRAME :
{ TransmitControl |= SEND_FRAME1;
break; }
}
}
// easyWEB internal function
// if all retransmissions failed, close connection and indicate an
error
void TCPHandleTimeout(void)
{
TCPStateMachine = CLOSED;
if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) ==
TCP_ACTIVE_OPEN)
SocketStatus = SOCK_ERR_ARP_TIMEOUT;
// indicate an
error to user
else
SocketStatus = SOCK_ERR_TCP_TIMEOUT;
TCPFlags = 0;
// clear all flags
}
// easyWEB internal function
// function executed every 0.210s by the MCU. used for the
// inital sequence number generator (ISN) and the TCP-timer
void TCPClockHandler(void)
{
ISNGenHigh++;
// upper 16 bits of
initial sequence number
TCPTimer++;
// timer for
retransmissions
}
// easyWEB internal function
// transfers the contents of 'TxFrame1'-Buffer to the CS8900A
void SendFrame1(void)
{
CopyToFrame_EthMAC(TxFrame1, TxFrame1Size);
}
// easyWEB internal function
// transfers the contents of 'TxFrame2'-Buffer to the CS8900A
117

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


void SendFrame2(void)
{
CopyToFrame_EthMAC(TxFrame2, TxFrame2Size);
}
// easyWEB internal function
// help function to write a WORD in big-endian byte-order
// to MCU-memory
void WriteWBE(unsigned char *Add, unsigned short Data)
{
*Add++ = Data >> 8;
*Add = (char)Data;
}
// easyWEB internal function
// help function to write a DWORD in big-endian byte-order
// to MCU-memory
void WriteDWBE(unsigned char *Add, unsigned long Data)
{
*Add++ = Data >> 24;
*Add++ = Data >> 16;
*Add++ = Data >> 8;
*Add = Data;
}
// easyWEB internal function
// help function to swap the byte order of a WORD
unsigned short SwapBytes(unsigned short Data)
{
return (Data >> 8) | (Data << 8);
}

4. TCPIP.H
// Modifications by Code Red Technologies for NXP LPC1776
#ifndef __TCPIP_H
#define __TCPIP_H
// easyWEB-stack definitions
#define MYIP_1
protocol (IP) address
#define MYIP_2
#define MYIP_3
#define MYIP_4
#define
#define
#define
#define

118

SUBMASK_1
SUBMASK_2
SUBMASK_3
SUBMASK_4

192

// our internet

168
1
150
255
255
255
0

Department Of Electronics Engineering| AISSMSCOE,Pune

// subnet mask

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define GWIP_1
(used if remote
#define GWIP_2
our subnet)
#define GWIP_3
#define GWIP_4

192

// standard gateway

168

// IP is no part of

1
10

#define RETRY_TIMEOUT
8
262ms for an ACK (about 2 sec.)
#define FIN_TIMEOUT
2
wait for an ACK of a FIN

// wait max. 8 x
// max. time to
// before closing

TCP state-machine (about 0.5 s)


#define MAX_RETRYS
4
resendings before reset conn.

// nr. of
// total nr. of

transmissions = MAX_RETRYS + 1
#define MAX_TCP_TX_DATA_SIZE 512
TCP data size (even!)
#define MAX_TCP_RX_DATA_SIZE 256
TCP data size (even!)

// max. outgoing
// max. incoming
// (increasing the

buffer-size dramatically
// increases the
transfer-speed!)
#define MAX_ETH_TX_DATA_SIZE 60
for ARP, ICMP, TCP (even!)

// 2nd buffer, used


// enough to echo

32 byte via ICMP


#define DEFAULT_TTL
sent with packets

64

// Ethernet network layer definitions


#define ETH_DA_OFS
0
address (48 Bit)
#define ETH_SA_OFS
6
address (48 Bit)
#define ETH_TYPE_OFS
12
Bit)
#define ETH_DATA_OFS
14
#define ETH_HEADER_SIZE
14
#define FRAME_ARP
0x0806
(stored in Type/Length field)
#define FRAME_IP
0x0800
// IPv4
#define
Length,
#define
Length

119

layer definitions
IP_VER_IHL_TOS_OFS
Type of Service
IP_TOTAL_LENGTH_OFS

// Time To Live

// Destination MAC
// Source MAC
// Type field (16
// Frame Data
// frame types

ETH_DATA_OFS + 0

// Version, Header

ETH_DATA_OFS + 2

// IP Frame's Total

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define IP_IDENT_OFS
Value
#define IP_FLAGS_FRAG_OFS
Fragment Offset
#define IP_TTL_PROT_OFS
Live, Protocol
#define IP_HEAD_CHKSUM_OFS
Header Checksum
#define IP_SOURCE_OFS
(32 Bit)
#define IP_DESTINATION_OFS
Address (32 Bit)
#define IP_DATA_OFS
no options)
#define IP_HEADER_SIZE

ETH_DATA_OFS + 4

// Identifying

ETH_DATA_OFS + 6

// Flags and

ETH_DATA_OFS + 8

// Frame's Time to

ETH_DATA_OFS + 10

// IP Frame's

ETH_DATA_OFS + 12

// Source Address

ETH_DATA_OFS + 16

// Destination

ETH_DATA_OFS + 20

// Frame Data (if

20

// w/o options

#define IP_VER_IHL
Length = 5x32 bit
#define IP_TOS_D
#define IP_TOS_T
throughput
#define IP_TOS_R
reliability

0x4500

// IPv4, Header

0x0010
0x0008

// TOS low delay


// TOS high

0x0004

// TOS high

#define IP_FLAG_DONTFRAG
IP frame
#define IP_FLAG_MOREFRAG
available
#define IP_FRAGOFS_MASK
this fragment belongs

0x4000

// don't fragment

0x2000

// more fragments

0x1FFF

// indicates where

#define PROT_ICMP
Message Protocol
#define PROT_TCP
Control Protocol
#define PROT_UDP
Protocol

// Internet Control

// Transmission

17

// User Datagram

ETH_DATA_OFS + 0

// Hardware address

ETH_DATA_OFS + 2
ETH_DATA_OFS + 4

// Protocol
// byte length of

ETH_DATA_OFS + 6
ETH_DATA_OFS + 8

// Opcode
// Hardw. address

ETH_DATA_OFS + 14

// IP address of

ETH_DATA_OFS + 18

// Hardw. address

ETH_DATA_OFS + 24

// IP address of

// ARP definitions
#define ARP_HARDW_OFS
type
#define ARP_PROT_OFS
#define ARP_HLEN_PLEN_OFS
each hardw. / prot. address
#define ARP_OPCODE_OFS
#define ARP_SENDER_HA_OFS
of sender of this packet
#define ARP_SENDER_IP_OFS
sender
#define ARP_TARGET_HA_OFS
of target of this packet
#define ARP_TARGET_IP_OFS
target
#define ARP_FRAME_SIZE

120

28

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define HARDW_ETH10
10Mbps Ethernet
#define IP_HLEN_PLEN
long, IP = 4 byte long
#define OP_ARP_REQUEST
ARP-frames
#define OP_ARP_ANSWER
// ICMP definitions
#define ICMP_TYPE_CODE_OFS
#define ICMP_CHKSUM_OFS
ICMP-message (16 bit)
#define ICMP_DATA_OFS
#define ICMP_HEADER_SIZE
#define ICMP_ECHO
echo request
#define ICMP_ECHO_REPLY
echo reply

// hardware-type

0x0604

// MAC = 6 byte

// operations for

2
IP_DATA_OFS + 0
IP_DATA_OFS + 2

// type of message
// checksum of

IP_DATA_OFS + 4
4
8

// message is an

// message is an

IP_DATA_OFS + 0

// Source Port (16

IP_DATA_OFS + 2

// Destination Port

IP_DATA_OFS + 4

// Sequence Number

IP_DATA_OFS + 8

// Acknowledge

IP_DATA_OFS + 12

// Data Offset and

IP_DATA_OFS + 14

// Window Size (16

IP_DATA_OFS + 16

// Checksum Field

IP_DATA_OFS + 18

// Urgent Pointer

IP_DATA_OFS + 20

// Frame Data (if

20

// size w/o options

#define DATA_OFS_MASK
words in the TCP Header

0xF000

// number of 32 bit

#define
#define
#define
#define
#define
#define

0x0001
0x0002
0x0004
0x0008
0x0010
0x0020

// TCP layer definitions


#define TCP_SRCPORT_OFS
bit)
#define TCP_DESTPORT_OFS
(16 bit)
#define TCP_SEQNR_OFS
(32 bit)
#define TCP_ACKNR_OFS
Number (32 bit)
#define TCP_DATA_CODE_OFS
Control Bits (16 bit)
#define TCP_WINDOW_OFS
bit)
#define TCP_CHKSUM_OFS
(16 bit)
#define TCP_URGENT_OFS
(16 bit)
#define TCP_DATA_OFS
no options)
#define TCP_HEADER_SIZE

TCP_CODE_FIN
TCP_CODE_SYN
TCP_CODE_RST
TCP_CODE_PSH
TCP_CODE_ACK
TCP_CODE_URG

#define TCP_OPT_MSS
0x0204
Length 4 (Max. Segment Size)
#define TCP_OPT_MSS_SIZE
4

121

Department Of Electronics Engineering| AISSMSCOE,Pune

// Type 2, Option

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


// define some TCP standard-ports, useful for testing...
#define TCP_PORT_ECHO
7
// echo
#define TCP_PORT_DISCARD
9
// discard
#define TCP_PORT_DAYTIME
13
// daytime
#define TCP_PORT_QOTD
17
// quote of the day
#define TCP_PORT_CHARGEN
19
// character
generator
#define TCP_PORT_HTTP
80
// word wide web
HTTP
// macros
#define SWAPB(Word)
((Word) >> 8))

((unsigned short)((Word) << 8) |


// convert little

<-> big endian


// typedefs
typedef enum {
TCP-state machine
CLOSED,
RFC793
LISTENING,
SYN_SENT,
SYN_RECD,
ESTABLISHED,
FIN_WAIT_1,
FIN_WAIT_2,
CLOSE_WAIT,
CLOSING,
LAST_ACK,
TIME_WAIT
} TTCPStateMachine;
typedef enum {
frame sent. used
ARP_REQUEST,
retransmissions
TCP_SYN_FRAME,
TCP_SYN_ACK_FRAME,
TCP_FIN_FRAME,
TCP_DATA_FRAME
} TLastFrameSent;

// states of the
// according to

// type of last
// for

// constants
// Code Red
// ifdef added as due to change to including .h files rather than .c
files.
// The use of ifdef reduces the coding changes that would otherwise
be required,
// depending upon which file is including this one.
//
#ifdef extern
const unsigned short MyIP[] =
//
"MYIP1.MYIP2.MYIP3.MYIP4"
122

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


{
MYIP_1 + (MYIP_2 << 8),
MYIP_3 + (MYIP_4 << 8)
};
const unsigned short SubnetMask[] =
"SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
{
SUBMASK_1 + (SUBMASK_2 << 8),
SUBMASK_3 + (SUBMASK_4 << 8)
};

//

const unsigned short GatewayIP[] =


"GWIP1.GWIP2.GWIP3.GWIP4"
{
GWIP_1 + (GWIP_2 << 8),
GWIP_3 + (GWIP_4 << 8)
};
#else
extern const unsigned short MyIP[2];
"MYIP1.MYIP2.MYIP3.MYIP4"
extern const unsigned short SubnetMask[2];
"SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
extern const unsigned short GatewayIP[2];
"GWIP1.GWIP2.GWIP3.GWIP4"
extern const unsigned char MyMAC[6];
M6"
#endif

//

// easyWEB's internal variables


extern TTCPStateMachine TCPStateMachine;
important var at all ;-)
extern TLastFrameSent LastFrameSent;
type
extern unsigned short ISNGenHigh;
our Initial Sequence Number
extern unsigned long TCPSeqNr;
number to send
extern unsigned long TCPUNASeqNr;
unaknowledged sequence number

//
//
//
// "M1-M2-M3-M4-M5-

// perhaps the most


// retransmission
// upper word of
// next sequence
// last
// incremented

AFTER sending data


extern unsigned long TCPAckNr;
receive and ack to send

// next seq to
// incremented

AFTER receiving data


extern unsigned char TCPTimer;
extern unsigned char RetryCounter;
retransmissions
// properties of the just received frame
extern unsigned short RecdFrameLength;
frame length
extern unsigned short RecdFrameMAC[3];
123

Department Of Electronics Engineering| AISSMSCOE,Pune

// inc'd each 262ms


// nr. of

// EMAC reported
// 48 bit MAC

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


extern unsigned short RecdFrameIP[2];
extern unsigned short RecdIPFrameLength;
length

// 32 bit IP
// 16 bit IP packet

// the next 3 buffers must be word-aligned!


// (here the 'RecdIPFrameLength' above does that)
extern unsigned short _TxFrame1[(ETH_HEADER_SIZE + IP_HEADER_SIZE +
TCP_HEADER_SIZE + MAX_TCP_TX_DATA_SIZE)/2];
extern unsigned short _TxFrame2[(ETH_HEADER_SIZE +
MAX_ETH_TX_DATA_SIZE)/2];
extern unsigned short _RxTCPBuffer[MAX_TCP_RX_DATA_SIZE/2]; // space
for incoming TCP-data
#define TxFrame1
((unsigned char *)_TxFrame1)
#define TxFrame2
((unsigned char *)_TxFrame2)
#define RxTCPBuffer
((unsigned char *)_RxTCPBuffer)
extern unsigned short TxFrame1Size;
TxFrame1
extern unsigned char TxFrame2Size;
TxFrame2
extern unsigned char TransmitControl;
#define SEND_FRAME1
#define SEND_FRAME2
extern unsigned char TCPFlags;
#define TCP_ACTIVE_OPEN
initiate a connection
#define IP_ADDR_RESOLVED
resolved to MAC
#define TCP_TIMER_RUNNING
#define TIMER_TYPE_RETRY
#define TCP_CLOSE_REQUESTED

// bytes to send in
// bytes to send in

0x01
0x02
0x01

// easyWEB shall

0x02

// IP sucessfully

0x04
0x08
0x10

// prototypes
void DoNetworkStuff(void);
// Handlers for incoming frames
void ProcessEthBroadcastFrame(void);
void ProcessEthIAFrame(void);
void ProcessICMPFrame(void);
void ProcessTCPFrame(void);
// fill TX-buffers
void PrepareARP_REQUEST(void);
void PrepareARP_ANSWER(void);
void PrepareICMP_ECHO_REPLY(void);
void PrepareTCP_FRAME(unsigned short TCPCode);
void PrepareTCP_DATA_FRAME(void);
// general help functions
void SendFrame1(void);
void SendFrame2(void);
void TCPStartRetryTimer(void);
void TCPStartTimeWaitTimer(void);
124

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


void TCPRestartTimer(void);
void TCPStopTimer(void);
void TCPHandleRetransmission(void);
void TCPHandleTimeout(void);
unsigned short CalcChecksum(void *Start, unsigned short Count,
unsigned char IsTCP);
// functions to work with big-endian numbers
unsigned short SwapBytes(unsigned short Data);
void WriteWBE(unsigned char *Add, unsigned short Data);
void WriteDWBE(unsigned char *Add, unsigned long Data);
// easyWEB-API functions
void TCPLowLevelInit(void);
LAN-controller, flags...
void TCPPassiveOpen(void);
connection
void TCPActiveOpen(void);
void TCPClose(void);
void TCPReleaseRxBuffer(void);
discard rec'd packet
void TCPTransmitTxBuffer(void);
transfer after TxBuffer is filled
// Code Red - added declaration for Timer0 ISR
void TCPClockHandler(void);
// easyWEB-API global vars and flags
extern unsigned short TCPRxDataCount;
rec'd
extern unsigned short TCPTxDataCount;
send

// setup timer,
// listen for a
// open connection
// close connection
// indicate to
// initiate

// nr. of bytes
// nr. of bytes to

extern unsigned short TCPLocalPort;


extern unsigned short TCPRemotePort;

// TCP ports

extern unsigned short RemoteMAC[3];


current TCP-session
extern unsigned short RemoteIP[2];

// MAC and IP of

extern unsigned char SocketStatus;


#define SOCK_ACTIVE
NOT closed
#define SOCK_CONNECTED
receive data
#define SOCK_DATA_AVAILABLE
available
#define SOCK_TX_BUF_RELEASED
buffer
#define SOCK_ERROR_MASK
check for errors
#define SOCK_ERR_OK
#define SOCK_ERR_ARP_TIMEOUT
for an ARP-REPLY

125

0x01

// state machine

0x02

// user may send &

0x04

// new data

0x08

// user may fill

0xF0

// bit-mask to

0x00
0x10

// no error
// timeout waiting

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


#define SOCK_ERR_TCP_TIMEOUT
for an ACK
#define SOCK_ERR_CONN_RESET
reset by the other TCP
#define SOCK_ERR_REMOTE
caused fatal error
#define SOCK_ERR_ETHERNET
interface error (timeout)

0x20

// timeout waiting

0x30

// connection was

0x40

// remote TCP

0x50

// network

// easyWEB-API buffer-pointers
#define TCP_TX_BUF
((unsigned char *)TxFrame1 + ETH_HEADER_SIZE
+ IP_HEADER_SIZE + TCP_HEADER_SIZE)
#define TCP_RX_BUF
((unsigned char *)RxTCPBuffer)
#endif

5. EASYWEB.C
#include
#include
#include
#include
#include

"stdlib.h"
"stdio.h"
"string.h"
<cr_section_macros.h>
<NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically


// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
// CodeRed - added #define extern on next line (else variables
// not defined). This has been done due to include the .h files
// rather than the .c files as in the original version of easyweb.
#define extern
#include "easyweb.h"
//CodeRed - added for LPC ethernet controller
#include "ethmac.h"
// CodeRed - include .h rather than .c file
#include "tcpip.h"
// easyWEB TCP/IP stack
// CodeRed - added NXP LPC register definitions header
#include "LPC17xx.h"
#include "webside.h"
// webside for our
HTTP server (HTML)
int main (void)
{
TCPLowLevelInit();
HTTPStatus = 0;
server's flag register
TCPLocalPort = TCP_PORT_HTTP;
to listen to
126

Department Of Electronics Engineering| AISSMSCOE,Pune

// clear HTTP// set port we want

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


while (1)
// repeat forever
{
if (!(SocketStatus & SOCK_ACTIVE)) TCPPassiveOpen();
// listen
for incoming TCP-connection
DoNetworkStuff();
// handle
network and easyWEB-stack
HTTPServer();
// events
}
}
//
//
//
//
//
//
//

This function implements a very simple dynamic HTTP-server.


It waits until connected, then sends a HTTP-header and the
HTML-code stored in memory. Before sending, it replaces
some special strings with dynamic values.
NOTE: For strings crossing page boundaries, replacing will
not work. In this case, simply add some extra lines
(e.g. CR and LFs) to the HTML-code.

void HTTPServer(void)
{
if (SocketStatus & SOCK_CONNECTED)
somebody has connected to our TCP
{
if (SocketStatus & SOCK_DATA_AVAILABLE)
TCP sent data
TCPReleaseRxBuffer();
away
if (SocketStatus & SOCK_TX_BUF_RELEASED)
is free for TX
{
if (!(HTTPStatus & HTTP_SEND_PAGE))
counter and pointer to webside
{
1st time
HTTPBytesToSend = sizeof(WebSide) - 1;
ignore trailing zero
PWebSide = (unsigned char *)WebSide;
code
}

// check if
// check if remote
// and throw it
// check if buffer
// init byte// if called the
// get HTML length,
// pointer to HTML-

if (HTTPBytesToSend > MAX_TCP_TX_DATA_SIZE)


// transmit a
segment of MAX_SIZE
{
if (!(HTTPStatus & HTTP_SEND_PAGE))
// 1st time,
include HTTP-header
{
memcpy(TCP_TX_BUF, GetResponse, sizeof(GetResponse) - 1);
memcpy(TCP_TX_BUF + sizeof(GetResponse) - 1, PWebSide,
MAX_TCP_TX_DATA_SIZE - sizeof(GetResponse) + 1);
HTTPBytesToSend -= MAX_TCP_TX_DATA_SIZE sizeof(GetResponse) + 1;
PWebSide += MAX_TCP_TX_DATA_SIZE - sizeof(GetResponse) +
1;
}
127

Department Of Electronics Engineering| AISSMSCOE,Pune

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


else
{
memcpy(TCP_TX_BUF, PWebSide, MAX_TCP_TX_DATA_SIZE);
HTTPBytesToSend -= MAX_TCP_TX_DATA_SIZE;
PWebSide += MAX_TCP_TX_DATA_SIZE;
}
TCPTxDataCount = MAX_TCP_TX_DATA_SIZE;
TCPTransmitTxBuffer();

// bytes to xfer
// xfer buffer

}
else if (HTTPBytesToSend)
// transmit
leftover bytes
{
memcpy(TCP_TX_BUF, PWebSide, HTTPBytesToSend);
TCPTxDataCount = HTTPBytesToSend;
// bytes to xfer
TCPTransmitTxBuffer();
// send last
segment
TCPClose();
// and close
connection
HTTPBytesToSend = 0;
// all data sent
}
HTTPStatus |= HTTP_SEND_PAGE;
executed
}
}
else
HTTPStatus &= ~HTTP_SEND_PAGE;
if not connected
}

// ok, 1st loop

// reset help-flag

6. EASYWEB.H
#ifndef __EASYWEB_H
#define __EASYWEB_H
const unsigned char GetResponse[] =
server sends to a client
{
"HTTP/1.0 200 OK\r\n"
1.0, code 200, reason OK
"Content-Type: text/html\r\n"
want to send
"\r\n"
HTTP-header
};
void start(void);
void InitOsc(void);
void InitPorts(void);
void HTTPServer(void);
void InsertDynamicValues(void);
unsigned int GetAD7Val(void);
unsigned int GetTempVal(void);
128

Department Of Electronics Engineering| AISSMSCOE,Pune

// 1st thing our


// protocol ver
// type of data we
// indicate end of

// prototypes

EMBEDDED PROCESSORS LAB. MANUAL (T.E. ELEX SEM-II)


unsigned char *PWebSide;
webside
unsigned int HTTPBytesToSend;
send
unsigned char HTTPStatus;
#define HTTP_SEND_PAGE

// pointer to
// bytes left to

0x01

#endif

129

Department Of Electronics Engineering| AISSMSCOE,Pune

// status byte
// help flag

Vous aimerez peut-être aussi