Add in a DHCP Server

advertisement
Making a HTTP Server with MCU SDK
(and a DHCP Server too)
Todd Mullanix
TCP/IP Stack
H
T
T
P
OS
Adaptation
Layer
Network
Service
Manager
D
H
C
P
D
N
S
Standard BSD Sockets Interface
Route
Manager
TCP
UDP
ICMP
IGMP
IP
IF
Manager
NAT
Network
Initialization
T
E
L
N
E
T
T
F
T
P
ARP
Ethernet IF
Hardware Adaptation Layer
Stack Event
Scheduler
Ethernet Serial
Packet
Port
Driver
Driver
Timer
Driver
User
LED
Driver
TCP/IP Key Features
 Supports both IPv4 and IPv6
C
O
N
F
I
G
U
R
A
T
I
O
N
 DHCP Client and Server
 HTTP Server
 Standard BSD Sockets interface
 Zero-copy sockets interface available
 Highly configurable to meet footprint
constraints
 Example on how to create daemon task
required by TCP/IP stacks
Hardware
2
Let’s Make a WebServer!
Steps
• Create and build new “empty” project
• Load and debug the empty project
• Add in Networking stack
• Add HTTP pages
• Add in a DHCP Server
3
Creating an Empty Project
First let’s create an empty project via the
CCS Project Wizard.
Doing “File->New->CCS Project” will start
the wizard on the right.
You need to
1. Give the project a unique name
2. Select the Family and Variant
3. Select the Connection (optional, but
we’ll use this later)
4. Select the MCU SDK Empty project for
Concerto (TMDXDOCKH52C1)
Hit “Next”
4
Creating an Empty Project
This page shows which software is
being used. Note: MCU SDK
automatically includes SYS/BIOS,
NDK, Ipc, UIA and *Ware. So you do
not need to specify them.
Hit “Finish”
5
Creating an Empty Project
Once the new project is
created, select
“Properties” to get the
following window.
This is the place to
change compiler and
linker options and other
settings. The General
page shows the
product software
configuration (again).
6
Building the httpServer Project
• Let’s look at the files in the new project
–
–
–
–
empty.c: main source file
empty.cfg: main configuration file
TMDXDOCKH52C1.c: board specific peripheral runtime configuration
TMDXDOCKH52C1.h: header file for board specific peripheral
runtime configuration APIs
– TMDXDOCKH52C1.cmd: Linker command file
– Board.h: Small “shim” header file to make board specific APIs
generic.
– F28M35H52C1.ccxml: Target Configuration file.
• Build project (right click, Project menu or build icon
)
– Build output goes to the console window
– One warning that we are working on removing for the GA release of MCU SDK.
– After the build is successful, if asked, do not load the application yet.
7
Let’s Make a WebServer!
Steps
• Create and build new “empty” project
• Loading and debugging the empty project
• Add in Networking stack
• Add HTTP pages
• Add in a DHCP Server
8
Loading the Project
• Debug the application. This will do the following:
– Launch the Debug session
– Connect to the M3
– Load the application
9
Run the project
• Run.
You’ll probably halt in main(). This is configurable via the Tools->Debugger
Options->Generic Debugger Options
• Open RTOS Object View (Tools->ROV)
Look at HeapMem and Task (shown below)
• Open System Anaylzer (Tools->System Analyzer->Live) and select Start
One event at this point. Notice that the Task handle address corresponds to the Idle
Task shown in ROV above.
10
Debug Information
• Resume
• Suspend
• Look at System Analyzer’s Live Session
The LoggingSetup module is controlling what gets logged. We’ll look
more at this later when there is more interesting data…
11
Let’s Make a WebServer!
Steps
• Create and build new “empty” project
• Loading and debugging the empty project
• Add in Networking stack
• Add HTTP pages
• Add in a DHCP Server
12
Adding Networking Stack
• Open up
empty.cfg and
view System
Overview
• Add EMAC by
right clicking
and selecting
“Use EMAC”
This will add the
EMAC driver
and allows you
to configure it.
Note: MCUSDK and
GPIO are already
there.
13
Adding Networking Stack
Currently there is not much configuration for the driver. This will be
expanded in future releases.
The instrumented library includes assert checking and Log events to help
in debugging.
14
Adding Networking Stack
• Go back to the MCU SDK
System Overview and do a
“Use” on the “TCP/IP” box.
• You can now deselect IPv6 (below the IP box).
• If you select the IP box, it goes to the IP configuration. You can specify whether
to use a static IP address or DHCP. (We’ll play with this later)
15
Adding Networking Stack
• In Empty.c, add the following bolded line around line 53. This initializes
the EMAC driver
Board_initGPIO();
Board_initEMAC();
• In TMDXDOCKH52C1.c, you need to change the MAC address to
match the sticker on your board. Note: there is a request to place the
MAC address into a dedicated location in ROM.
UInt8 macAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Note: Once you have your company’s own custom board, you’ll need to
make your own “board” source file.
16
Adding Networking Stack
• Navigate to include HTTP Server by left clicking TCP/IP box from MCU
SDK System Overview.
• Right Click on HTTP and select “Use HTTP”. You should see the
following now.
17
Adding Networking Stack
• Select “Instance” and hit “Add”. We’ll leave the defaults.
• Save and build application.
18
Adding Networking Stack
• Before loading, Close System Analyzer Session.
• Load and halt at main().
– Look at ROV’s Task, EMAC and Ndk windows
• Load and halt at main().
[Cortex_M3_0] 00000.000 mmBulkAlloc(): could not allocate memory.
[Cortex_M3_0] 00000.000 out of memory: handle=0x20e375, size=10
[Cortex_M3_0] Service Status: DHCPC
: Failed
:
: 000
[Cortex_M3_0] ti.sysbios.heaps.HeapMem: line 294: out of memory: handle=0x20009100,
size=1804
ti.sysbios.heaps.HeapMem: line 294: out of memory: handle=0x20009100, size=2048
xdc.runtime.Error.raise: terminating execution
What happened!
Look at HeapMem in ROV. There is not enough memory. The default Networking
settings are too big.
We are working to fix this for the next release. But let’s figure out how to fix this.
19
Fitting Networking Stack into Target
First, the default Memory heap is too small. Select the Memory page in
the outline window and increase the heap to 25088 (0x6200)
20
Fitting Networking Stack into Target
Additionally, select the “Task” page and reduce the Idle Task size to 1024
(instead of 2048).
21
Fitting Networking Stack into Target
There are several other fields that need tweaking. Instead of doing this
graphically, you can do this via a text file. Close the graphical configuration and
right click on the empty.cfg file and select Open With-> Text Editor and add the
following lines at the bottom. Save the file. (Again we are trying to make this
easier for the next release)
Program.stack = 1024;
var Udp = xdc.useModule('ti.ndk.config.Udp');
Udp.receiveBufSize = 2048;
var Tcp = xdc.useModule('ti.ndk.config.Tcp');
Tcp.transmitBufSize = 2048;
Tcp.receiveBufSize = 2048;
Tcp.receiveBufLimit = 2048;
Global.lowTaskStackSize = 1792;
Global.normTaskStackSize = 1792;
Global.highTaskStackSize = 1792;
Global.ndkThreadStackSize = 1792;
Global.pktSizeFrameBuf = 1552;
Global.pktNumFrameBufs = 16;
Global.memRawPageCount = 8;
22
Running HTTP Server
• Make sure you have the Ethernet cable connection!
• Rebuild and load the application. Once you run it, you should see the
following:
[Cortex_M3_0]
[Cortex_M3_0]
[Cortex_M3_0]
[Cortex_M3_0]
[Cortex_M3_0]
Service
Service
Service
Network
Service
Status: DHCPC
: Enabled
Status: HTTP
: Enabled
Status: DHCPC
: Enabled
Added: If-1:146.252.161.8
Status: DHCPC
: Enabled
:
:
: Running
: 000
: 000
: 000
: Running
: 017
• Look at ROV’s Task, Ndk, and EMAC
• Open browser to IP Address…
What’s wrong! The reason is because we have no web content on the
target.
23
Let’s Make a WebServer!
Steps
• Create and build new “empty” project
• Loading and debugging the empty project
• Add in Networking stack
• Add HTTP pages
• Add in a DHCP Server
24
Adding HTTP Server Content
The following slides are going to summarize the
<mcusdk>/products/<ndk>/docs/spru524h.pdf’s
“Appendix E: Web Programming with the HTTP Server” section…
25
Adding HTTP Server Content
Let’s add a simple index.html page for the target.
1. Create a simple default.html file that contains “Hello World” in the same
directory as your project.
2. Convert this to a Char array that can be included into the application. Run the
binsrc.exe that is in the <mcusdk>products\<ndk>\packages\ti\ndk\tools\binsrc
directory. Add this directory to your path or use the full path name
>binsrc.exe default.html default.h DEFAULT
This creates a default.h file, which has the Char array representation of the
webpage.
•
Added the following header files into the empty.c file
#include <ti/ndk/inc/netmain.h>
#include "default.h"
26
Adding HTTP Server Content
4.
Add the following functions into empty.c
Void AddWebFiles(Void)
{
//Note: both DEFAULT_SIZE and DEFAULT are defined in default.h
efs_createfile("index.html", DEFAULT_SIZE, (UINT8 *)DEFAULT);
}
Void RemoveWebFiles(Void)
{
efs_destroyfile("index.html");
}
5.
Add the following into the empty.cfg file
Global.stackInitHook = '&AddWebFiles';
Global.stackDeleteHook = '&RemoveWebFiles';
6.
Rebuild, load, run and now point your browser at the IP address.
FYI: WireShark is a great free Network Analyzer that helps view the packets.
27
Adding HTTP Server Content
Let’s add a second page. Make an greetings.html file that contains “Greets
Everyone” and a picture (e.g. dspchip.gif).
1. Run the binsrc.exe convertor on the page and the image.
>binsrc.exe greetings.html greetings.h GREETINGS
>binsrc.exe dspchip.jpg dspchip.h DSPCHIP
2. Include the greetings.h and dspchip.h files into your project.
#include "greetings.h"
#include "dspchip.h"
3. Add greetings and dspchip into the AddWebFiles/RemoveWebFiles
Void AddWebFiles(Void)
{
efs_createfile("index.html", DEFAULT_SIZE, (UINT8 *)DEFAULT);
efs_createfile("greetings.html", GREETINGS_SIZE, (UINT8 *)GREETINGS);
efs_createfile("dspchip.jpg", DSPCHIP_SIZE, (UINT8 *)DSPCHIP);
}
Void RemoveWebFiles(Void)
{
efs_destroyfile("index.html");
efs_destroyfile("greetings.html");
efs_destroyfile("dspchip.jpg");
}
28
Adding HTTP Server Content
Rebuild, load and run the target now. Point your browser at the IP
address. It should still be the “Hello World” page.
Now point to <ipaddr>/greetings.html. You should see the greeting and
the picture.
It is also possible to pull the pages from the network or from an SD card.
29
Adding HTTP Server Content: CGI
Pages are great, but how do you add “smarts” to the page? For example,
how long has the target been up?
The NDK supports CGI scripts to be on the target. The basic idea is that
you write a CGI function in ‘C’ that plugs into the EFS.
Let’s add the number of SYS/BIOS Clock ticks that have occurred since
the system has started.
1. Add a getTicks.cgi command onto the default.html page.
<body>
Hello World<br>
<br>
Get current Clock tick  <a href="getTicks.cgi">getTick.cgi</a><br>
2. Convert the default.htm via binsrc
>binsrc.exe default.html default.h DEFAULT
30
Adding HTTP Server Content: CGI
Now add the following code into empty.c
#include <ti/sysbios/knl/Clock.h>
Int getTicks(SOCKET s, int length)
{
Char buf[200];
static UInt scalar = 0;
if (scalar == 0) {
scalar = 1000000u / Clock_tickPeriod;
}
httpSendStatusLine(s, HTTP_OK, CONTENT_TYPE_HTML);
httpSendClientStr(s, CRLF);
httpSendClientStr(s,
"<html><head><title>SYS/BIOS Clock "\
"Time</title></head><body><h1>Time</h1>\n");
System_sprintf(buf, "<p>Up for %d seconds</p>\n",
((unsigned long)Clock_getTicks() / scalar));
httpSendClientStr(s, buf);
httpSendClientStr(s, "</table></body></html>");
return (1);
}
31
Adding HTTP Server Content: CGI
Now hook the cgi into the EFS in empty.c
Void AddWebFiles(Void)
{
Void *pFxn;
efs_createfile("index.html", DEFAULT_SIZE, (UINT8 *)DEFAULT);
efs_createfile("greetings.html", GREETINGS_SIZE,
(UINT8 *)GREETINGS);
efs_createfile("dspchip.jpg", DSPCHIP_SIZE, (UINT8 *)DSPCHIP);
pFxn = (Void*) &getTicks;
efs_createfile("getTicks.cgi", 0, (UINT8 *) pFxn);
}
Void RemoveWebFiles(Void)
{
efs_destroyfile("index.html");
efs_destroyfile("greetings.html");
efs_destroyfile("dspchip.jpg");
efs_destroyfile("getTicks.cgi");
}
Rebuild, load and run. Point browser to the IP address.
32
Debug Information
• Start System Analyzer.
• Analyze the application
(right-click in the Live
Session window)
– Open Execution Graph
Note: Hwi and Swi logging was not enabled, so you don’t see them. Hwi/Swi
logging does impact performance (~2-3%).
33
Debug Information
Open Task Load (both Graph and Summary)
34
Let’s Make a WebServer!
Steps
• Create and build new “empty” project
• Loading and debugging the empty project
• Add in Networking stack
• Add HTTP pages
• Add in a DHCP Server
35
Add in a DHCP Server
Let’s add in a DHCP Server into the application.
1. Move your PC and target to a private network.
2. Add DHCP Server into your application’s configuration
36
Add in a DHCP Server
3. “Add” an instance and configure DHCP Server as needed.
37
Add in a DHCP Server
4. Give the target a static IP address. Select IP and configure accordingly
38
Add in a DHCP Server
5. Rebuild, load and run. Have you PC attempt to get an IP address now.
6. Future DHCP Server enhancements
•
•
•
Configurable lease time (currently 7 days)
Configurable Gateway (currently Gateway IP address is the target’s IP address)
API/ROV to display requests that have been serviced
39
Extra Material
• Using a different Software product
• printf vs System_printf
• CPU Load vs Task Load
• USB Logging
40
Creating an Empty Project
The “Order” page
shows the order that
the software packages
are used (both for
configuration and
linking).
41
Using a different product version.
If you wanted to use a
different sub-product
version, select it on the
RTSC page. Then on
the “Order” page, move
it up above the MCU
SDK’s sub-product
entry (see next slide).
42
Using a different product version.
When building now, the
1.1.00.04 UIA will be
used instead of the
MCU SDK’s UIA.
43
printf vs System_printf
The biggest question we have is “Why don’t I get output to the console”
First some background…
System_printf: This function behaves much like the ANSI C Standard printf but
does not support the full range of format strings specified by the C Standard. In
addition, several non-standard format specifiers are recognized.
You can plug in different implementations into the System module.
SysMin: Small implementation that stores output in an internal buffer. It is flushed
to stdout when a System_flush is called or when the program exits.
SysStd: Basically sits on top of printf and other RTS functions.
SysFlex: Let’s the customer plug in different functions. MCU SDK ships a UART
implementation.
Please refer to the MCU SDK User Guide for more details
44
CPU Load vs Task Load
Within the SYS/BIOS Idle Task, there is a list of functions that are executed.
These N functions are repeated executed while in Idle. The execution of all N
functions is 1 idle loop. One of the function is placed there by the Load module.
For a time period (default 500ms) the number of loops completed by the Idle Task
is counted. While this the counting is going on, the minimal time for a loop is also
determined.
The product of the number of times through the loop and the minimal time is an
approximation for the time spent in Idle. The CPU Load is determined in this
manner.
An individual Task Load is determined by looking at the context switches.
The Task Load is a more accurate measure. So 100 - %Load of Idle is more
accurate than %CPULoad. However, there is more of a performance overhead to
manage Task Load.
Note: LoggerIdle plugs in an Idle function that messes up CPULoad, but not Task
Load.
45
USB Logging
Some of the examples (demo and uartconsole) already show how to log via the
USB peripheral instead of stop-mode.
46
Download