Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - mark

Pages: 1 ... 16 17 [18] 19
256
NXPTM LPC2XXX and LPC17XX / Getting started with the NXP LPC23XX
« on: November 09, 2007, 10:34:26 PM »
Hi All

I though it be an idea to present an introductory document to working with the LPC23XX based on my experiences porting the uTasker to it. In a nut-shell, the porting work has taken rather longer than expected due to a lack of time to dedicate to the project and also various difficulties which were not always easy to explain when actually finding the time. Since the basic project is however now operational and I believe the initial difficultes have been mastered here is something to get the ball rolling:


Getting started with the LPC23XX

I am using the Keil MCB2300 evaluation board together with IAR and a J-Link debugger. The following is a guide to understanding the LPC23XX (the board uses the LPC2378) and how to overcome first difficulties.

There are various bugs in the first versions of the device and the evaluation boards tend to have these chips on them so one has also to be wary of the restrictions and use the required workarounds to ensure of no unnecessary problems.

Working with the debugger from internal SRAM

The device has a total of 58k internal RAM but some of this RAM is assigned generally for use by various peripheral devices and is not contiguous in memory. Therefore first steps involve the use of 32k of SRAM on the local bus which is located in the address range 0x40000000..0x40007fff. For a program to operating in internal RAM its code and its variable must be located there – this restricts the size of the program which can operate and so this method is only really of use for more simple experiments and debugging of peripheral code. Generally debugging code loaded to internal FLASH is required and this will be looked at after the initial difficulties are solved.

For a program to be able to run from the internal SRAM, it must be linked accordingly. For this reason its code starts at 0x40000000 and the processor stack pointers are set to the top of the 32k SRAM space. This is defined by the linker script.

The code is downloaded by the debugger into RAM at this location and the PC is set to start operation from the first address 0x40000000.

What you need to know about the LPC23XX boot programmer

I have deleted the software in FLASH which was supplied with the board since it initialised some parts of the chip which could cause some difficulties – mainly because programs would run correctly when these initialisations were performed but unexpectedly not when the initialisations failed. This can be confusing so it is best to ensure that your own code is really working correctly without the ‘unexpected’ help of something which will not be there later anyway.

Even with no code loaded into FLASH the LPC23XX doesn’t just try to run non-existent code but contains its own boot loader (called ISP [In System programming] mode). This will either start code execution or else stay in its own code where it supports FLASH programming over UART 0. This FLASH programming will be explained later but first a few details about how the boot loader decides whether to start the code in FLASH or not.

There are two checks which are performed
- first the input P2.10 is read (ISP input). If it is low the boot software continues to run*.
- secondly a value at the reserved interrupt vector location 0x00000014 is checked. This must be equal to the 2's compliments of the check-sum of the other vector values for the boot software to recognise a valid program and thus start execution at the address 0x00000000.
*On the MCB2300 board there is a switch marked INT0 which is connected via jumper J8 to P2.10. If the jumper is in position the boot software can be forced by resetting the board with also the INT button pressed. In addition the software used on the PC to load FLASH can control the reset line and the ISP input via hardware control lines. In some cases one has to be careful when connecting COM0 since a terminal may inadvertently hold the device in reset or cause it to be unintentionally started in ISP mode. To avoid this, jumpers J9 and J10 can be removed.

MEMMAP Register at location 0xe01fc040

This register is very important when working from internal SRAM. It has three possible values:
- 0x00 – 64 bytes of the boot software from its 8k boot block in FLASH from 0x7fffe000 is mapped to address 0x00000000.
- 0x01 – the start of internal FLASH (64 bytes starting at 0x00000000) is mapped to address 0x00000000 (i.e. where it is).
- 0x02 – the start of internal SRAM (64 bytes starting at 0x40000000) is mapped to address 0x00000000.

0x00 is the default after a reset so that the internal boot software is executed. If it decides to start a program in user FLASH it switches the value to 0x01 so that the user code is mapped in to the reset vector and starts it there. If code is to be run in SRAM the code should set the value to 0x02 so that the vectors from 0x40000000..0x4000003f are ‘seen’ also between 0x00000000..0x0000003f so that interrupts will operate correctly.

If you connect a debugger to a target with no program loaded to it is possible to see that MEMMAP has the value 0x00 and then the boot software vectors are present from the address 0x00000000. By modifying the MEMMAP to 0x01 the empty FLASH is switched in and by modifying it to 0x02 the first 64 bytes of SRAM are visible. This can be a useful test when the board does something unexpected – either not starting the code as expected or not executing interrupts as expected – since it is then possible to verify that the expected memory is switched to the vector locations.

Clocks

The LPC23XX can run from several clock sources including an internal RC (Resistor/Capacitor) oscillator, and RTC (Real Time Clock) oscillator, a crystal and the output from a PLL (Phase Locked Loop) derived from one of the inputs.
My interest is to run from a PLL at maximum speed and, due to accuracy issues, to use an external crystal to achieve 72MHz.

There are two important points to bear in mind:
- first that the PLL in the first chips has some problems (check the revision that you have and the most up to data errata sheet) and so the code uses the recommended method of setting the PLL output to 288Mh from a 12MHz crystal before post-dividing by 4 to obtain the desired 72MHz speed.
- secondly, the boot software may set up the PLL to operate from the RC oscillator source. This fact, plus the fact that the boot software also programs some ports, means that it is best to not assume any particular state and thus be able to handle cases where the PLL is already programmed or not. When the PLL is already programmed it is important to correctly disable it before setting it up for the desired configuration.

Ports

As mentioned in the previous section it is important to remember that the boot program can have changed some port settings. In addition to this I found that it is important to actively set all port configurations to defaults on start up to ensure that ports also behaved as expected. This seems contrary to the details in the data sheet but it may also have something to do with the boot software operation – in any case the active initialisation solves any problems.

There is one difficulty that I always experience when debugging. If I stop the processor running and open a memory window which displays the FAST IO register values the content of these registers don’t seem to make any sense. Also the fact that the debugger displays them stops the FAST IO from working correctly any more. After resetting all works fine again just as long as I don’t have a windows causing the debugger to access them. This is strange and a nuisance but I simply avoid looking at them and then there is no further problem…

Running code from FLASH

The first thing which needs to be solved to run code from FLASH is to get it programmed. After compiling and linking the project with settings appropriate for the target (linker script file for FLASH based code) I load it using the program FLASH MAGIC. This is a free software available on the Internet [http://www.flashmagictool.com/], and developed by the company Embedded Systems Academy for NXP – it should however not be used for production work according to the programs notes.

This program communicates with the LPC23XX via UART 0 (COM0 on the MCB2300 evaluation board). If there is no valid program already loaded in FLASH the LPC23XX start up the boot software automatically and waits for a synchronisation over the serial port. It is very easy to test whether it is basically operating by connecting a terminal emulator to the serial port and typing a question mark “?” – the board will adapt itself to the baud rate used and answer with “SYNCHRONIZED”.

If there is already valid software loaded in FLASH simply reset the board and keep the INT0 button pressed (ensure that the INT0 jumper is set so that this button is connected with P2.10).

Start FLASH MAGIC and configure it to use the appropriate COM port – I use 115200 BAUD which works reliably – and the device LPC2378, plus oscillator (12.000000) in the case of the MCB2300 board.

In the ISP menu you can do some things like reading the chip’s signature and checking whether its FLASH is blank. To program the FLASH memory enter the path to the HEX file to be loaded (Intel Extended format is required for it to be recognised). It may be a good idea to verify the contents after loading by checking the option “Verify after programming”. Although it is also possible to delete the FLASH contents in the ISP menu it is practical to check the Ease option “Erase blocks used by Hex File” so that it is automated. To program just press the Start button and wait until it confirms that all has completed.

Should something not work, verify that the board is really in ISP mode by resetting with INT0 pressed. If working on your own hardware be careful about the quality of the RXD signal at the UART input – I know from experience that even the smallest glitches on the line can cause synchronisation or loading to fail. There are a number of posts in various forums where people are despairing about not being able to work with the ISP port. Usually bad capacitors in the RS232 driver circuit or other problems are found to be the cause. In my case I had a fast logic gate in the line which was ringing slightly (overshoot) and this would almost always cause FLASH loading to fail somewhere during the process. After removing this circuit (which was found to be unnecessary in the design after all) we never had any problems again – this was with LPC210X devices but I understand that the LPC2378 can also be sensitive.

Hopefully the software works correctly on the target, but if there is a need to debug it, debugging from FLASH works well, with the usual restriction of 2 program breakpoints.

The uTasker project supplies IAR projects to work in RAM and also to compile to the target FLASH. The uTasker simulator also enables a large part of the development/debugging to already be performed in the uTasker simulator environment on the LPC23XX so it is hoped that debugging on the target is only necessary in some specific situations.





This will eventually make its way into a new tutorial for the LPC23XX. Comments are welcome.

Regards

Mark




257
µTasker general / NetBIOS - try it out
« on: November 08, 2007, 12:10:51 AM »
Hi All

I hope that no one is getting the impression that there is no development work progress at the moment. It is true that new service pack releases are a bit (too) quiet but this is rather to do with the fact that there is a lot of activity requiring rather more work to get everything in line for something official. [On top of this is a generally high level of 'project' work which is diverting more energy that anticipated [positive side is that there will be more features soon such as graphical LCD support...], plus some new chip work which is proving more complicated than expected before it can be shown]. All-in-all well behind on all fronts, but battling and having some fun on the way at least.

So I though it would be nice to give something general which may well prove useful for a number of users. It is not a big thing but can prove useful, especially when you have a device configured to gets its configuration from a DHCP server.

It is all about NetBIOS

First a typical case of its use.
If you have a device configured to get its IP set up from a DHCP server it is not always that easy to indicate its configuration to a user (or find it out yourself).
If you use the simulator, the IP address is displayed after DHCP resolution has been achieved (useful for yourself as developer but not for an end-user).
If you have a display or a serial port it is usually possible to display the present configuration, but this is only useful in some situations.
If you can monitor the network using Ethereal (or similar) you can see the setting obrained, but this is hardly a user friendly approach!!
Even if you are not using DHCP, but have set up a device with fixed setting, often its address is forgotten and so it has to be found by using one of the above methods or even by setting it back to its default state (typically done by pressing an input switch on power up).

Working with a name rather than an IP address

This is where NetBIOS comes in - it allows you to communicate with the device by using its name.
In the demo project the device has a user configurable name (default "uTasker Number 1") and this can easily be set up to be used as its name in the network by using the new NetBIOS support. [in fact the default name is too long for NetBIOS so has to be shortened by one to the maximum of 15 characters - the name is not case sensitive so both capitals and small letters can be freely used. I will assume the name "uTasker-1" in the following discussion].
To access its web server, it can be addressed from the browser by entering the URL http ://uTaster-1, or its FTP server by ftp ://uTasker-1. It can also be pinged by using ping uTasker-1 etc. If several devices are in the network just make sure that each has a unique device name, in the same way that they also need unique IP configurations.

With a device supporting NetBIOS it is therefore possible to work with it in a local network without ever needing to actually know its IP address.

How to set it up in your project

First of all you will need a new file called NetBIOS.c which you can add to your project (simulator and/or target). This file is available in its initial form at the following address: http://www.uTasker.com/software/test/NetBIOS.c

This version works without any other header files but the project needs to be configured as follows to add the option:
In config.h add the following to the UDP protocol group (and ensure that UDP itself is enabled!):
Code: [Select]
            #define USE_NETBIOS                                          // enable NetBIOS - needs UDP
Then add the following just below it:
Code: [Select]
            #ifdef USE_NETBIOS
                #define NETBIOS_SOCKET 1
                #define SUPPORT_SUBNET_BROADCAST                         // NetBIOS needs to receive sub-net broadcast frames
            #else
                #define NETBIOS_SOCKET 0
            #endif

and finally
            #define UDP_SOCKETS   (DHCP_SOCKET + DNS_SOCKET + TFTP_SOCKET + NETBIOS_SOCKET + USER_UDP_SOCKETS) // the number of UDP sockets supported
to ensure that there are adequate UDP ports in the UDP pool for the new NetBIOS server.

In a user file (such as in the initialision part of application.c) start the NetBIOS server:

Code: [Select]
  #ifdef USE_NETBIOS
        fnStartNetBIOS_Server(parameters->cDeviceIDName);               
  #endif

To ensure the project compiles without warning or even errors, add the prototype for the new function to tcpip.h:
    extern int fnStartNetBIOS_Server(CHAR *name);               


Here the device ID (a null-terminated string) is set to be used as name. This can of course be changed to any string (limited to 15 characters) if another source for the name is prefered.

That was it - the server simply responds to NetBIOS queries in the background and the rest works as before.

A small warning

The new NetBIOS support is limited to handling single queries in a very lean way. Take a look at the file to see how simple it is to do this (it simply manipulates the query directly in the LAN input buffer and send this back with the local IP details). It may not work in all cases but a single query is the standard method used by a real application - and there may be some other not yet known issues.
Use it and inform me if you do have any problems so that your case can be added to the presently minimal solution.
The code has however been constructed to silently discard NetBIOS frames if they do not conform and so the code should never be able to cause any system problems (commonly known as 'to crash').

Note that NetBIOS works with sub-net broadcasts which is automatically activated by the new code in the configuration. Should your project base not support this option NetBIOS will not be able to work so check latest service packs (I see it is not in the SAM7X pack so contact me for the files if you are interested).

If you have any problems or would like to discuss NetBIOS extensions feel free to discuss here.

Good luck

regards

Mark



Additional notes:
Since NetBIOS communicates using sub-net broadcast frames you need to be careful with the network mask setting when not using DHCP. If for example you set a network mask to be 255.255.254.0 but the local network uses 255.255.255.0 NetBIOS will not work. The reason is that the PCs sub-net broadcast frames (assume 192.168.0.1 as PC IP address) will be  192.168.0.255. This is a broadcast in the 255.255.255.0 subnet but not in the 255.255.254.0 sub-net, which needs 192.168.1.255 - so this will not be received by the device in this case.
Using  DHCP will also ensure that the entire sub-net set-up is correct.

If the IP address of the board is changed the PCs using NetBIOS which have the NAME:IP combination in their cache will not be able to find the board at its new address. In this case the Windows nbtstat -R command can be used to purge the cache, which causes a new request to be sent out on the network and so the entry updated.


 





258
NXPTM LPC2XXX and LPC17XX / LPC23XX ports - strange behaviour
« on: October 20, 2007, 11:25:11 PM »
Hi All

I have a strange effect with the Fast IOs on the LPC2378.

When my test program is running normally everthing is fine - FIOs are blinking a RUN LED and showing moving text on an LCD.

I can stop the code with JTAG debugger and restart with out any problems..
until I have a memory window open which is displaying the FIO registers (from 0x3fffc000). When the code is paused , the debugger updates the block of memory and this cause the ports to stop operating correctly.

Specifically the values read from 0x3fffc000, 0x3fffc010, 0x3fffc020 etc. show 0x400000df, and change often to 0x600000df (these are DIR and MASK addresses - the mask register was never changed by the code). Afterwards the ports don't respond when the program continues. Sometimes I can correct the situation by closing the memory window and forcing the code to write 0x00000000 to the MASK resisters (eg by manipulating register values to force this rather than a normal port write). Afterwards the ports then function correctly again.

If the port registers are never displayed in the debugger I never have any problems.

Has any one else experienced such behaviour or can explain how the debugger can disturb the ports by reading the register values?

Regards

Mark


259
Hi All

Interfacing between the application and HTML - in order to general dynamic content or pass information - is in fact very simple. Generating dynamic content involves parsing the HTML content and replacing escape sequences, whereby the parsing and manipulation details are intergrated in the project files.

The actual interpreter part belongs to the application and is thus very flexible.

The following is a quick guide which has served as useful in the past.


All interfacing between the Browser and the application takes place in the file webinterface.c. There are the following calls from the web server part (which doesn’t need to be understood in itself):

- fnIsSelected()   the web server asks the application whether a check box or other such field is to be displayed as active or not (eg. Whether a port input is high or low)

- fnHandleWeb()  the web server passes received parameters to the application (eg. A change of a setting such as a port output level)

- fnInsertString() the web server asks the application to fill out text to be displayed on the web side (eg. Display a counter value, define a colour, size, etc.)

 
The rest is basically defined in the html files which can be loaded by ftp and modified as required (they are not compiled into the code as performed by most embedded suites and so can even be changed by users without means to compile the project (eg. To translate the web pages into other languages etc. or to personalise them for a specific customer).

An example: Look at the source to the file “0Menu.html” where you will see the following lines:

<form action=/0 name=r>
Email address <input maxLength=40 size=40 name=M value="£vE0" £Dm0><input type=submit value="Enter" name=r £Dm0></form>


"£vE0" informs the web server that this field is to be filled out by the application and so it will cause fnInsertString() to be called and the application returns in this case an email address to be displayed.


£Dm0 informs the web server that it must request the application as to whether the field should be displayed as enabled (can be changed and not grey) or disabled (can not be modified and is grey). This causes fnIsSelected() to be called so that the application can decide how it should be displayed.


name=M is a reference to the form which is sent when the user clicks on the “Enter” button (when enabled). This causes the web server to call fnHandleWeb() so that the data received (in this case a new email address) can be passed to the application.

 
By simply adding new references in the html and supporting them equivalently in the application it is very easy to built interactive and dynamic web browser interfaces.

If you use the simulator you can simply put a break point in these routines and see how it all interacts. Then it is simple to modify and test new parameters – simulate it to ensure it all works well and then compile with Codewarrior and load to the target – it will then work without any debugging effort on the hardware…




Comments welcome.

Regards

Mark

260
µTasker general / Using a Character LCD in the uTasker Project
« on: October 10, 2007, 12:53:12 PM »
Hi All

Often some form of simple text interface is require (coffee machines, credit card terminals, process control equipment) which can be fulfilled using a charcacter LCD. The uTasker project support such an interface and also enables complete testing in the uTasker simulator.

This post discusses the use of the module.


Using a character LCD in the uTasker project

The uTasker project supports character displays which conform to the HD44780 standard interface (which is probably just about all). The display can be from the smallest type I know (1 x 8 ) up to 4 x 40 and its interfaces using either an 8 bit or 4 bit interface. The 8 bit interface is a bit faster since all read/writes to/from the display can be made in one access cycle, whereas the 4 bit interface saves bus/port lines since the data interface is less wide - accesses require two cycles in this mode and so it is a bit slower. Generally the access speed is not a big issue when interfacing to this type of LCD so 4 bit mode is often preferred.

The uTasker simulator aids in developments since it includes a configurable simulated LCD. The demo project shows an example of initialising and controlling the LCD. This may not be the best method for a particular application but is quite easy to use and reliable so represents a good starting point.

Connecting an LCD to a processor

The LCDs have an interface which follows the following pattern. The actual connector type can vary widely, being a single or double row of pins. I will describe one which I often use which is easily translated to and other type as well.

Pin 1  Vss  (Ground for the power supply)
Pin 2  VDD  (+ve voltage power supply, eg. 5V or 3V3)
Pin 3  VO   (Contrast control voltage typically 0..1.5V when powered by 5V or a slightly negative value when powered by 3V3)
Pin 4  RS   (Data/Instruction select)
Pin 5  R/W  (Read/Write)
Pin 6  E    (Enable signal)
Pin 7  DB0  (Data Bus 0 - don't connect for 4 bit mode)
Pin 8  DB1  (Data Bus 1 - don't connect for 4 bit mode)
Pin 9  DB2  (Data Bus 2 - don't connect for 4 bit mode)
Pin 10 DB3  (Data Bus 3 - don't connect for 4 bit mode)
Pin 11 DB4  (Data Bus 4 - always connected)
Pin 12 DB5  (Data Bus 5 - always connected)
Pin 13 DB6  (Data Bus 6 - always connected)
Pin 14 DB7  (Data Bus 7 - always connected)
Pin 15 LEDA (Backlight LED - if available - Anode - connect positive backlight drive voltage to this - 5V with current limiting resistor recommended)
Pin 16 LEDK (Backlight LED - if available - Kathode - connect negative backlight drive voltage to this)

If connecting a 5V LCD to a 3V3 processor it may be necessary to use a level shifter. Note also that the processor not only drives the data bus but can also read back data. In particular DB7 is read back to check whether the LCD is busy so this should also be supported. If your processor is 5V tolerant this is of course no problem at all.


Trying the LCD out in the uTasker simulator.
If you want to test drive the LCD without actually having to connect one to a target the simulator comes in very handly. It can also be used for developing applications which require an LCD to display text (and a limited amount of graphics).
In config.h the LCD demo can be activated and the LCD type configured:

Code: [Select]
#define SUPPORT_LCD                                                      // enable a task for interfacing to an LCD
#ifdef SUPPORT_LCD
    #define LCD_LINES              2                                     // use 2 x 16 LCD
    #define LCD_CHARACTERS         16                                    // Options are 1:8 / 1:16 / 1:20 / 1:24 / 1:40 / 2:x / 4:x
    #define LCD_ON_COLOUR          (COLORREF)RGB(60,220,60)              // RGB colour of LCD when backlight is on
    #define LCD_OFF_COLOUR         (COLORREF)RGB(70,160,0)               // RGB colour of LCD when backlight is off
    #define LCD_PARTNER_TASK       TASK_APPLICATION
#endif

Various LCDs sizes can be selected and the text and background colour configured. Real LCDs have limited colour choice so best choose realistic colour settings to avoid disappointment..! The following description is valid when USE_TIME_SERVER has not also been activated (otherwise the LCD will display the present time).

The result is an LCD with the defined characteristics displayed when the simulator is running, showing "Hi uTasker!" continuously moving left and right.

Setting the SW interface to the target
In order to actually control an LCD the processor must be connected to it via the control lines as specified above. Each target in the uTasker project has an LCD setup to allow it to operate with a standard demo board and to easily be adapted to almost any other board. The set up is defined in the header file app_hw_xxx.h (wher xxx is the target processor in question). Here is an example for the M5223X project.

Code: [Select]
// LCD interface: Backlight control Port AS bit 0 : Data bus (4 Bit) Port TA 0..3 : RS Port AS bit 1, RW Port AS bit 2, E Port AS bit 3
//
typedef unsigned char LCD_BUS_PORT_SIZE;                                 // we use 8 bit ports
typedef unsigned char LCD_CONTROL_PORT_SIZE;
//#define LCD_BUS_8BIT                                                   // data bus in 8 bit mode
#define LCD_BUS_4BIT                                                     // data bus in 4 bit mode

#ifdef LCD_BUS_8BIT
    #define LCD_BUS_MASK         0xff
    #define DATA_SHIFT_RIGHT     0                                       // no shift required to bring data into position
    #define DATA_SHIFT_LEFT      0
#else
    #define LCD_BUS_MASK         0x0f
    #define DATA_SHIFT_RIGHT     4                                       // nibble shift down required to bring data into position
    #define DATA_SHIFT_LEFT      0
#endif

#define O_CONTROL_RS             PORT_AS_BIT1
#define O_WRITE_READ             PORT_AS_BIT2
#define O_CONTROL_EN             PORT_AS_BIT3
#define O_LCD_BACKLIGHT          PORT_AS_BIT0

#define O_CONTROL_LINES          (O_CONTROL_RS | O_WRITE_READ | O_CONTROL_EN)
#define IO_BUS_PORT_DDR          DDRTA
#define O_CONTROL_PORT_DDR       DDRAS
#define IO_BUS_PORT_DAT          PORTTA
#define IO_BUS_PORT_DAT_IN       PORTIN_SETTA
#define O_CONTROL_PORT_DAT       PORTAS

// Drive the control lines R/W + LCD Backlight '1', RS + E '0'  and the data lines with all high impedance at start up
#define INITIALISE_LCD_CONTROL_LINES()       IO_BUS_PORT_DDR = 0; IO_BUS_PORT_DDR = 0; \
                                             O_CONTROL_PORT_DDR &= ~(O_CONTROL_LINES | O_LCD_BACKLIGHT); O_CONTROL_PORT_DAT &= ~(O_CONTROL_LINES | O_LCD_BACKLIGHT); O_CONTROL_PORT_DAT |= (O_LCD_BACKLIGHT | O_WRITE_READ); \
                                             O_CONTROL_PORT_DDR |= (O_CONTROL_LINES | O_LCD_BACKLIGHT);


#define LCD_DRIVE_DATA()          IO_BUS_PORT_DDR |= LCD_BUS_MASK;    IO_BUS_PORT_DDR |= LCD_BUS_MASK;
                                  // ensure data bus outputs (delay) by repetitions according to processor speed

#define CLOCK_EN_HIGH()           O_CONTROL_PORT_DAT |= (O_CONTROL_EN); O_CONTROL_PORT_DAT |= (O_CONTROL_EN);
                                  // clock EN to high state - repeat to slow down (delay)

#define DELAY_ENABLE_CLOCK_HIGH() O_CONTROL_PORT_DAT &= ~(O_CONTROL_EN);


I must admit that this is not the simplest thing to configure but with a little understanding it should be possible to adapt to almost any other configuration, as long as a few rules are adhered to.
First of all, the mapping of the LCD control lines to real ports has to be defined. The above example is set to operate in 4 bit bus mode and controls the LCD via port AS. The bus interface is required to be on a single port and the bits are assumed to be next to each other in an accending row. In the example port TA is used and the 4 data bits are situated from TA0..TA3.
The control lines are assumed to be all on a single port but their position on the port is not important.
The routines actually controlling accesses do so using macros (like LCD_DRIVE_DATA()) where the exact method of achieving this for a particular processor is defined above.

Since modern processors are quite fast (although port bit banging can may not necessarily be as fast as expected) the actual routines may be too fast for the LCD interface. Depending on the processor and its speed setting, it is often necessary to slow down accesses by introducing 'wait-states' - this can be performed by repeating instructions in the macros as follows:

Code: [Select]
#define CLOCK_EN_HIGH()           O_CONTROL_PORT_DAT |= (O_CONTROL_EN); O_CONTROL_PORT_DAT |= (O_CONTROL_EN); \
                                  O_CONTROL_PORT_DAT |= (O_CONTROL_EN); \
                                  O_CONTROL_PORT_DAT |= (O_CONTROL_EN); \
                                  O_CONTROL_PORT_DAT |= (O_CONTROL_EN);

It may be a good idea to once tune the accesses by looking at the accesses with an oscilloscope (or logic analyser) to ensure that the accesses are not too fast (check the times in the data chip for the LCD used) but also not unnecessarily slow due to too many wait-states.
As a reference, the M5223X running at 60MHz doesn't need any wait states to operate with a display in 8 bit mode. In 4 bit mode the inter-cycle gap (when it does two back-to-back nibble reads) is at the limit so and so DELAY_ENABLE_CLOCK_HIGH() is used to ensure that this can not become an issue.


Initialisation procedure
When the define SUPPORT_LCD is activated in the uTasker demo project an LCD task is added to the system (see lcd.c). On start up this task configures the ports used by the LCD interface using the macro INITIALISE_LCD_CONTROL_LINES().

It then works through an LCD initialisation sequence:
1. The task is started by the application task afer a delay of 100ms to ensure that the LCD is ready to respond to data.
2. The first command sent to the LCD is the INIT_FUNCTION_SET command (always in 4 bit mode after power up).
3. After a delay of at least 4.1ms (one system tick is used) the command is repeated again.
4. After a delay of at least 100us (one system tick is used) the command is repeated again before finally issuing the INIT_FUNCTION_SET_MODE. The task is set to polling mode where it ready the busy bit of the LCD to see when the next command can be performed.
5. The INIT_FUNCTION_SET_MODE is repeated with final configuration settings.
6. Still operating in polling mode (meaning that the last instruction is being polled to identify when it has completed), the next command is DISPLAY_OFF_NO_CURSOR - to ensure that no cursor is being displayed.
7. Followed by CLEAR_DISPLAY, to ensure nothing is visible and the (invisible) cursor is at the top left.
8. Followed by DISPLAY_ON_NO_CURSOR so that any text written will actually be seen.

Inter-task details
The demo solution involves communication between the application task and the display task. The application task determines what is displayed and the LCD task just does what it is told. It starts by informing the application task that the initialisation has completed by sending an event E_LCD_INITIALISED.
The application task then sends a welcome text to the LCD task which writes it to the display.
When the LCD task writes to the display it does so from a text/command queue. It operates in polling mode until the commands in the queue have been completely written. It sets itself to the sleep state (to avoid unnecessary polling) and informs the application task (using event E_LCD_READY) that the previous command has completed. The application task can then send the next text or commands.
This solution this requires the application task to wait for an acknowledge from the previous commands before continuing. Individual commands/text sequences are queued in the LCD task itself.

A closer look at the hardware set up
As long as the control lines are on one single port the configuration involves simply masking out the port bits as required. Should they have to be spread over different ports the standard routine is no longer compatible and so will have to be adapted to suit. Therefore try to plan these on the same port to save any extra work.
The data lines are very simple if working in 8 bit mode on an 8 bit port.
    #define LCD_BUS_MASK         0xff
    #define DATA_SHIFT_RIGHT     0                                       // no shift required to bring data into position
    #define DATA_SHIFT_LEFT      0
This means that bytes to be written are passed to the write routine and require no manipulation to be written to the bus (PORT = byte_of_data). Also when reading it is just as simple (read_byte = PORT).
If the port width is not 8 bit bit 16 or 32, it is equally simple as long as the data bus is aligned with the lowest 8 bits.
Should the port width be 32 for example and the bus be connected to port bits 5..12 then the set up will be
    #define LCD_BUS_MASK         0x3fc0
    #define DATA_SHIFT_RIGHT     5                                       // no shift required to bring data into position
    #define DATA_SHIFT_LEFT      0

This causes the correct port bits to be masked and then the read value to be shiften into position. When reading form the bus, the inverted process takes place.

Working in 4 bit mode is a little tricker. It should be remembered that it is the higher 4 bit nibble which is important, so if the lower 4 bits of a port are connected to the LCD lines 7..4, the following setting is required:

    #define LCD_BUS_MASK         0x0f
    #define DATA_SHIFT_RIGHT     4                                       // nibble shift down required to bring data into position
    #define DATA_SHIFT_LEFT      0

When writing, the byte is passed as two nibbles (each positioned to the higher nibble position). This explains why a right shift of 4 bits is required to position it correctly in the byte to be physically written. When reading, the nibble is read at the lower nibble position and so the opposite (left shift) is performed to reconstruct the complete byte (two read cycles).
It is assumed that the data bus lines are all next to each other on a port and that the sequence is the same as the LCS (0,1,2,3 /0,1,2,3 and not 4,3,2,1...). If this is not the case, more manipulation in the code is required to get it right, so a simpel physical wiring will also keep the coding simple.

Note that reading from the LCD is important to ensure that following write cycles are not performed while the LCD is still busy. If this is not respected, text and commands will probably not all be correctly interpreted which results in either the display not operating or doing so only unreliably.





Comments are welcome. Give it a try if you would like to control an LCD in your project.

Regards

Mark

261
NXPTM LPC2XXX and LPC17XX / LPC2468
« on: September 26, 2007, 05:31:08 PM »
Hi All

NXP has just released a data sheet for a new part - LPC2468

32-bit microcontroller with USB2.0, Ethernet, CAN and 512 Kbyte Flash memory
Break through your current microcontroller limits with our 32-bit ARM7-based microcontroller LPC2468. This powerful yet cost-effective device was built for connectivity and supports 10/100 Ethernet, full-speed USB 2.0, USB OTG and CAN 2.0B. An extensive feature list includes 512 Kbytes of Flash with ISP / IAP, 98 Kbytes of SRAM and 10-bit ADC and DAC - all in a choice of LQFP208 or TFBGA208 packages. Ideal for communications gateways and protocol converters, it also delivers outstanding performance in industrial control and medical applications.


http://www.nxp.com/acrobat_download/datasheets/LPC2468_1.pdf

In the data sheet it says that the USB interface Host, Device and OTG!!

Regards

Mark

262
NXPTM M522XX, KINETIS and i.MX RT / New Coldfire M522XX parts
« on: September 22, 2007, 12:42:10 PM »
Hi All

In case anyone doesn't keep up to date with the Freescale product portfolio for the M522XX Coldfire parts, there have been a few new ones announces - also some user manuals have been reworked and no longer have preliminary status. It may be worth updating your copies.

See the following:
http://forums.freescale.com/freescale/board/message?board.id=CFCOMM&message.id=3206&jump=true#M3206

As far as I understand it, the new ones tend to expand the range of memory and possibly price by offering reduced RAM and reduced maximum speed.

Regards

Mark

263
ATMELTM AT91SAM7X and AVR32 / Rowley GCC Crossworks project available
« on: September 16, 2007, 01:42:05 AM »
Hi All

I know that several users have been using Rowley GCC Crossworks for their projects and I helped out a bit earlier in the year to get the V1.3 for the SAM7X running in that environment.

But the time has come to integrate the Rowley project into the uTasker project and so, rather than wait for the next SAM7X SP release, it has been added as an intermediate release so that interested and loyal Rowley fans can get it into productive use.

I have worked with Rowley CrossWorks a little, and also used their CrossConnect JTAG debugger. I have also had contact with Paul at Rowley Associates so can assure that they have a good solution for professional developments based on the GNU compiler. It is all well thought out and of high quality and the debugger is very easy to use. The big advantage of the CrossWorks package for ARM is that it is so easy to install and use. Install the IDE and all tools as any other Windows program and plug in the JTAG debugger (various ones are supported, including the popular J-Link). Open the (new) uTasker project in the IDE, compile and click on the debug button. When using the FLASH target the SAM7X FLASH will automatically be erased and the new code loaded and then you are running and - it all works very reliably. If there are any question just send the guys in Gloucestershire, England a mail and you will very quickly get the answer to your problem.

Visit the Rowely Associates web site at:
    http://www.rowley.co.uk/
where you can not only get a copy of the CrossWorks software (evaluation possible) but you can even read about what Paul has been up to in his own blog!

Note that as well as the full commerical license, they offer reduced priced educational and now personal licenses. I see that there is presently, for a limited time, an offer where you get a CrossConnect Lite JTAG adapter free when purchasing ARM software.

One final point worth noting is that the run-time library delivered with CrossWorks is a version optimised by Rowely Associates and not the normal GCC library version, which is otherwise rumoured to be the weak link in the GCC chain (although I can't comment in any more detail on this).

The new SP 1 (Rowely) can be found on the Service Packs page of the web site:
    http://www.utasker.com/software/softwareV1.3.html
Simple use your standard V1.3 SAM/X project password!

Good luck

Regards

Mark

264
NXPTM M522XX, KINETIS and i.MX RT / New Service Pack SP5 release
« on: August 28, 2007, 12:12:57 AM »
Hi All

Here's an anouncement of a new service pack available for the M5223X project. It is SP5 and includes not only the promised SPI FLASH software upload support but has also SW encryption upload support to enable SW to be distributed and loaded without it being interpretable.

There are new documents detailing the operation and use of the new boot loader version, plus an updated totorial about using it with the M5223X and CodeWarrior.

http://www.utasker.com/docs/uTasker/uTaskerBoot_003.PDF
and
http://www.utasker.com/docs/uTasker/BM-Booloader_for_M5223X.PDF
respectively.

A circuit for connecting an ATMEL AT45DBXXX to typical M5223X boards can be found here:
http://www.utasker.com/docs/uTasker/spi_flash_freescale.PDF

Along side various other improvements, there is an exciting new HTTP serving technique included in the new project which allows much faster serving of larger pages and images. This uses a special TCP windowing technique which requires just 6 more bytes of RAM per TCP socket but achieves around 25x speed improvement in a local area network. Activate it and you will see what I mean...!

Then there is complete RTC and edge port (IRQ1..15) support and simulation. And to round it off, it includes all required for GCC and Eclipse builds with the latest CodeSourcery GCC versions.

Below is a copy of the new part of the release note. You will notice two restrictions (fairly minor) which will be looked into... but if anyone is feeling really industrious then why not have a go at solving the puzzle and give us the details here!

The SP5 is available on the Service Pack side (http://www.utasker.com/software/softwareV1.3.html) and can be extracted using the normal technique and M5223X project password.

Good luck. I hope you enjoy the new features!

Regards

Mark


28.8.2007 SP5


uTasker:
- uFile.c         SPI FLASH support
- iic_drv.c       Removed GNU warning
- Driver.c        uStrlen() const type to match prototype
                  Use static RAM for code from RAM since uMalloc may not always be ready
- uNetwork.c      Add next rx acknowledgement count to ensure correct order of received acks
                  Sequence number correction on sequence count overflow
- uTasker.c       Timer delays of less than 1 TICK rounded up to 1 so that they will not be lost
                  Timer entries use enabled flag to ensure validity
- uTasker.h       enabled flag added to Timer table


WinSim:
- FileToDisk.c    Add SPI FLASH support
- WinSim.h        Add fnInitSPI_DataFlash(), fnGetDataFlashStart(), fnGetDataFlashSize() and fnSimAT45DBXXX()
- WinSim.c        Added SPI Data FLASH to support the AT45DBXXX. Set initialised flag.

Hardware:
- M5223X\M5223X_boot.c   SPI FLASH support added
- M5223X\mcf5223X_boot.s Added adjustment for boot loader with external SPI FLASH
- M5223X\SimM5223X.h     Add Edge port module registers and Add RTC registers / correct M5223X_QSPI content size
- M5223X\M5232XSim.c     Correct IRQ simulation on user port changes and improve level sensitive simulation - for IRQ1..IRQ7
                         Correct DD, GP and AN port function simulation
                         Add RTC support
                         User memset rather than uMemset since uMemset is not yet available when running from SRAM
- M5223x\M5223X.h        Add Edge port module 1 registers and interrupt masks.
                         Add RTC registers and extend the RTC setup to use it.
- M5223X\M5223X.c        IRQ support extended to IRQ1..15 (11 for 80 pin device)
                         All calls of fnIncrementEthernetStats made conditional on USE_IP_STATS
                         Add SPI FLASH support
                         Add RTC support
                         Rework auto-negotiation mode to control full-duplex mode in PHY
                         Alternative UART pins defines. Alternative forced for UART2 when 80 pin package used
                         Correct I2C  mult-read sequence
- Hardware.h      Add fnSPI_Flash_available() and fnConfigureRTC()

Stack:
- arp.c           Optionally only add used addresses to ARP table (rather than all 'seen' ones) - add define
                    ARP_IGNORE_FOREIGN_ENTRIES to IP configuration (config.h) to activate this
- ip.c            Use static RAM for code from RAM since uMalloc may not always be ready
- webutils.c      Allow displaying short strings (less than 4 bytes) without inserting spaces (improves formular field

inputs) - add define INSERT_SHORT_STRINGS to HTTP configuration (config.h) to activate this
- tcpip.h         ucNegotiate no longer conditional on Telnet
                  Add HTTP windowing tx support (HTTP_WINDOWING_BUFFERS)
- tcp.c           Add HTTP windowing tx support (HTTP_WINDOWING_BUFFERS)
                  Discard buffered TCP data when no connection
                  Optionally silently discard peer's data when closing (DISCARD_DATA_WHILE_CLOSING)
- http.c          Correct message regeneration in delayed serving state
                  Add HTTP windowing tx support (HTTP_WINDOWING_BUFFERS)
                  allow displaying short strings (less than 4 bytes) without inserting spaces (improves formular field

inputs) (INSERT_SHORT_STRINGS)


Demo application \Application\uTaskerV1.3
- application.c   Add IRQ test (M5223X)
                  Add RTC test (M5223X)
- app_hw_m5223x.h Add RTC configuration


Demo application CodeWarrior project:
- \Applications\uTaskerV1.3\CodeWarrior_M5223X\uTaskerV1.3\include\mwerks.h modified to force function pointers in A0 to be

compatible with libraries.
- \Applications\uTaskerV1.3\CodeWarrior_M5223X\uTaskerV1.3\bin\uTaskerConvert.exe New version of binary converter supporting

encryption and Motorola binary input files

Demo application GNU/Eclipse project:
- \Applications\uTaskerV1.3\GNU_ColdFire\Build_M5223X.bat  uses same make file as Eclipse
- \Applications\uTaskerV1.3\GNU_ColdFire\m52235evb-rom.ld  supports all present CodeSourcery versions
- \Applications\uTaskerV1.3\GNU_ColdFire\makefile supports make file for use with GNU standalone and Eclipse builds

                 


uTasker boot loader project \Applications\uTaskerBoot:
- config.h               Add M5223X SPI FLASH support - activate define SPI_SW_UPLOAD to enable SPI FLASH support
- uTaskerBootLoader.c    Changed header interpretation so that it is endian-independent
                         Added decryption support
                         Added SPI FLASH support (M5223X)
-\Applications\uTaskerV1.3\CodeWarrior_M5223X\uTaskerV1.3\cfg\M52235_BOOT_APP_FLASH.lcf to support SPI FLASH based upload


Configuration notes:
1. The define RUN_LOOPS_IN_RAM is not supported in the SP5 under CodeWarrior. The reason is that the compiler won't accept

the method of calcualting the code space when changing from malloc based to static RAM space, which is required due to new

start-up requirements. The advantages of the loops in RAM are minor and DMA_MEMCPY_SET is recommended. Methods of solving

this restrictions will be investigated.

2. INSERT_SHORT_STRINGS
Add the following line to config.h, in the USE_HTTP block, to activate this:
            #define INSERT_SHORT_STRINGS                                 // allow displaying short strings (less than 4

bytes) without inserting spaces (improves formular field inputs)
This is recommeded when working with formulars to avoid short strings being padded with spaces.

3. HTTP_WINDOWING_BUFFERS
Add the following line to config.h, in the USE_HTTP block, to activate this:
            #define HTTP_WINDOWING_BUFFERS  2                            // we can send 2 frames before requiring ACKs
When activated it introduces a new method of using TCP windowing when the HTTP server sends data. The increased memory

requirement is quite small at 6 bytes per TCP socket but allows all HTTP data, including dynamically generate data to be

sent at much improved speed to the HTTP client.
The basic problems when no windowing is used are round-trip delay and delayed-acks at the client. the new solution enables

regeneration of all data without the need to store in large buffers, while respecting the receive winodw of slow clients -

inlcuding a persistent timer to probe a closed window. In a local network a speed improvement of around 25x is obtained,

which is especially useful when serving larger pages and images!
This technique has not yet been intensively tested so if any problems are found please report them. By removing the define

the original technique is returned.

Note that this requires also CONTROL_WINDOW_SIZE and SUPPORT_PEER_WINDOW to be active (which is generally already the case).


4. IRQ
The simulator has been improved to accurately simulate all edge interrupts.
See the new IRQ_TEST in application.c. Activate also the serial debug interface (SERIAL_INTERFACE) to see messages when the

IRQ interrupts are triggered.

5. RTC
The RTC is activated per default (it can be completely deactivated by removing SUPPORT_RTC from app_hw_m5223x.h).
For an example of configuration and use see RTC_TEST in application.c
The RTC is also fully simulated.

6. GCC Eclipse
The GCC directory is included in the SP5 with the Eclipse make file.
See the following forum topic for details of how to set up Eclipse:
http://www.utasker.com/forum/index.php?topic=14.0

7. Encrypted SW upload
The boot loader project now suppports uploads of encrypted data. Full details of using this with the M5223X project is

included in the newest version of the bare-minimum users' guide for the M5233X - see

http://www.utasker.com/docs/documentation.html.
The updated converter utility uTaskerConvert.exe to support the encryption is included in the SP5 - to check the version

number it can be called with "uTaskerConvert.exe -v", which returns:
 uTaskerConvert V1.1 - supporting encryption and Motorola binary format


8. SPI FLASH SW uploads
By adding the following define in the M5223X section of config.h, the external SPI FLASH (supporting ATMEL AT45DBXXX

devices) is activated:
  //#define SPI_SW_UPLOAD                                                // SW upload to SPI FLASH support enabled

The following new defines in app_hw_m5223x.h define the properties of the SPI FLASH and define a file name used by the HTTP post method on the application web side to be loaded to it:

#define SPI_FLASH_PAGE_LENGTH 264                                        // standard page size (B-device only allows 256)
//#define SPI_FLASH_PAGE_LENGTH 256                                      // size when power of 2 mode selected (only

possible on D-device)
#define SPI_FLASH_BLOCK_LENGTH (8*SPI_FLASH_PAGE_LENGTH)                 // block size - a block can be deleted
#define SPI_FLASH_SECTOR_LENGTH (64*4*SPI_FLASH_PAGE_LENGTH)             // exception sector 0a is 2k and sector 0b is 62k
#define SPI_FLASH_PAGES         1024                                     // 256k part expected
#define SPI_DATA_FLASH_SIZE    (SPI_FLASH_PAGES*SPI_FLASH_PAGE_LENGTH)

#define SW_UPLOAD_FILE()       (*ucIp_Data == 'H') && (*(ucIp_Data+1) == 'S') && (*(ucIp_Data+2) == '.')  &&  (fnSPI_Flash_available() != 0)

Should the device not be detected, the upload will go to the internal FLASH as in the previous version, even if the new  option is enabled.

See the latest edition of the bare-minimum users' guide for the M5233X for full details about setting up the boot program.
Note that the boot loader space requirement increases from 2k to 4k when using external SPI FLASH due to the fact that it requires both the original flash driver and also the new SPI flash driver at the same time. The size fo uploadable code  however increases to maximum internal FLASH size minus 4k.

Although the uploaded file is never visible in the file system, its contents can be recovered using FTP under DOS and the  "GET HS.bin" command.

There is presently one restriction when using SPI_SW_UPLOAD support. The define DMA_MEMCPY_SET (in app_hw_m5223x.h) has to be deactivated. The reason is not yet understood but the DMA copies cause an exception to occur when the SPI FLASH support is operation. This doesn't happen when stepping with the debugger but does when the code runs at full speed - making it more difficult to debug. Hopefully a solution will be found in the near future...



265
Hi All

Some one pointed out to me a chip from Luminary Micro (http://www.luminarymicro.com/home/home.html).
It is from their Stellaris family of processor with 25MHz / 50MHz CortexTM-M3 (new ARM) in 100 pin LQFP.
16..64k RAM and 64..256k FLASH.
Internal 10/100MHz EMAC + PHY!!
Various peripherals including UART, I2C, ADC, SPI, RTC - 5V tolerant I/Os etc.

Who knows more about it or has even ordered the evaluation board?

It sounds good - but is it too good to be true? It seems very new...

Any comments??

Regards

Mark


266
NXPTM M522XX, KINETIS and i.MX RT / SW uploads to SPI FLASH
« on: August 13, 2007, 12:05:29 AM »
Hi All

I have managed to add a boot loader to the M5223X demo project which allows SW uploads to an external SPI FLASH.
It posts the file to the start of SPI FLASH and the boot loader reads this and programs it to program FLASH.
I believe that it is compatible with AT45DB011B, AT45DB021B, AT45DB041B, AT45DB041D, AT45DB081B, AT45DB081D, AT45DB161D but I have only actually tested with AT45DB041B.
An encryption option is also included so that the distributed code is not readable at any stage until it is extracted by the boot loader to its final destination in FLASH.

I have had to increase the boot loader space to 4k since the SPI driver and FLASH driver are needed at the same time and the 2k mark was easily passed…

What I haven’t done is used the SPI FLASH for anything other than the SW upload so the application will still have to sort the general use out itself. My solution was to define a file (HS.bin in the demo project) which is diverted to the SPI FLASH rather than the internal FLASH file system. This works fine for the SW upload but is far from a general solution for application data saving and retrieval along side an internal file system!!

Nevertheless it enables full 256k (minus Bootloader and any file system space) SW uploads and so opens up some interesting new possibilities. This should be included in the next M5223X SP.

Regards

Mark

P.S. See also the general discussion about external SPI FLASH in  http://www.utasker.com/forum/index.php?topic=4.0

267
NXPTM M522XX, KINETIS and i.MX RT / RTC in M5223X
« on: August 12, 2007, 09:51:55 PM »
Hi All

On the one hand the RTC (Real Time Clock) in the M5223X is a bit disappointing - normally one thinks of a battery backed up device with 32kHz crystal, time of day, week day, day, month, year and automatic months and leap year adjustments - but on the other hand it could well come in handy in certain applications.

The RTC is clocked by a 1Hz clock which is derived from the local crystal (25MHz typically) and is only operational when the CPU is powered. It is not designed for keeping the time but rather counting elapsed time - however it can be set to a known time, for example from the information from a Time Server.

So it was time that it became supported in the uTasker project. Here is a brief of how the new interface can be used and how it can be tested in the demo project. The new support will be included in the next service pack or is available on demand (in development version) before then. The simulator has also be updated to include the RTC.

Features
  • The time (Day count from 0...64k, hours, minutes and seconds) can be set
  • The present time can be read back - to nearest second
  • A seconds interrupt can be configured
  • A minutes interrupt can be configured
  • A hours interrupt can be configured
  • A days interrupt can be configured
  • An alarm interrupt can be configured (matching day, hour, minute and second)
  • A stopwatch interrupt can be configured (from 1 to 60 minutes, to the nearest minute)

These are more or less the capabilities of the RTC in the M5223X so the driver allows each to be simply configured. All of the events are interrupt events and any combination can be used at the same time - for example an alarm can be set, the stopwatch can be running and any of the other periodic interrupts can also be used [like seconds and hours]. Each event is dispatched to its own interrupt handler.

The easiest way to see how to use the interface is to try out the following demo code.

1. Add the define  SUPPORT_RTC to app_hw_m5223x.h
2. Enable define RTC_TEST in application.c

The following subroutine will be called to start the test.

Code: [Select]
static void fnTestRTC(void)
{
    RTC_SETUP rtc_setup;

    CONFIG_TIMER_TEST_LEDS();                                            // drive some LEDs for visibility
    TIMER_TEST_LED_ON();
    TIMER_TEST_LED2_ON();

    rtc_setup.command = RTC_TIME_SETTING;                                // set the present time to the RTC (this could be collected from a timer server and is a fixed value here)
    rtc_setup.usDays    = 5;
    rtc_setup.hours     = 3;
    rtc_setup.ucMinutes = 23;
    rtc_setup.ucSeconds = 53;

    fnConfigureRTC((void *)&rtc_setup);                                  // set the time

    rtc_setup.command = RTC_TICK_MIN;                                    // configure periodic interrupts - once a minute
    rtc_setup.int_handler = test_minute_tick;
    fnConfigureRTC((void *)&rtc_setup);                                  // set a minute interrupt rate (first expected after 7 seconds)

    rtc_setup.command = RTC_ALARM_TIME;                                  // set an alarm time
    rtc_setup.int_handler = test_alarm;
    rtc_setup.ucMinutes = 24;
    rtc_setup.ucSeconds = 14;
    fnConfigureRTC((void *)&rtc_setup);                                  // set an alarm interrupt rate (expected after 21 seconds)

    rtc_setup.command = RTC_STOPWATCH_GO;                                // set a stop watch time (minutes to nearest minute)
    rtc_setup.int_handler = test_stopwatch;
    rtc_setup.ucMinutes = 2;                                             
    fnConfigureRTC((void *)&rtc_setup);                                  // set 2 minute stop watch (expected after 67 seconds)   
}

Each event is given an interrupt handler which is called from the corresponding interrupt dispatched when the event occurs. For example test_minute_tick() is set to be called when the minute interrupt occurs.

Code: [Select]
// Interrupt once a minute
//
static void test_minute_tick(void)
{
    static int iBlick = 0;

    RTC_SETUP rtc_setup;
    rtc_setup.command = RTC_GET_TIME;

    fnConfigureRTC((void *)&rtc_setup);                                  // get the present time

    if (iBlick == 0) {
        iBlick = 1;
        TIMER_TEST_LED_OFF();
    }
    else {
        iBlick = 0;
        TIMER_TEST_LED_ON();
    }
}

When an alarm time occurs:

Code: [Select]
// Interrupt at alarm time
//
static void test_alarm(void)
{
    RTC_SETUP rtc_setup;
    rtc_setup.command = RTC_GET_TIME;

    fnConfigureRTC((void *)&rtc_setup);                                  // get the present time

    TIMER_TEST_LED_ON();
    TIMER_TEST_LED2_OFF();
}

and when the stopwatch counts down:

Code: [Select]
// Interrupt at stopwatch count down
//
static void test_stopwatch(void)
{
    RTC_SETUP rtc_setup;
    rtc_setup.command = (RTC_TICK_MIN | RTC_DISABLE);

    fnConfigureRTC((void *)&rtc_setup);                                  // disable further minute TICKs

    rtc_setup.command = RTC_TICK_SEC;                                    // change to second TICKs
    rtc_setup.int_handler = test_minute_tick;                            // re-use this interrupt routine
   
    fnConfigureRTC((void *)&rtc_setup);

    TIMER_TEST_LED2_ON();
}

The interrupt dispatcher is also so constructed that the Stopwatch and Alarm events are true single shot events so the user doesn't need to undertake any thing to ensure that there will not be multiple events generated over time.

Two LEDs are used to visualise the test process. The test works in the simulator or on the target boards and this is what it does - as defined by the configuration code and the interrupt handling as above:

1. The time is set to Day 5: Hour 3: Minute 23: Second 53 [5:3:23:53]
2. A minute interrupt is configured - the first is expected after just 7 seconds, when the minute counter overflows from 59 to 0.
3. An alarm time is set for 5:3:24:14. Therefore the alarm interrupt is expected 14s after the first minute interrupt.
4. A 2 minute stopwatch is started. Since the stop watch has a minute resolution it will count down the first time after only 7s and then will fire on the second minute - 46s after the alarm interrupt.
5. The stopwatch interrupt disables further minute interrupts, so only one minute interrupt is expected.
6. All interrups (excluding the stopwatch) read the present time (using the debugger the present time can be checked).
7. The stopwatch interrupt also enable a second interrupt (using the same handling code as the minute interrupt) so afterwards an interrupt once a second is expected.

The LEDs make this visible and so they do the following:

5:3:23:53 - LED 4:3 = ON:ON
5:3:24:00 - LED 4:3 = ON:OFF  (Minute interrupt)
5:3:24:14 - LED 4:3 = OFF:ON  (Alarm interrupt)
5:3:25:00 - LED 4:3 = ON:ON  (Stopwatch interrupt - clears minute interrupt and starts second interrupt
5:3:25:01 - LED 4:3 = ON:OFF (Second interrupt)
5:3:25:02 - LED 4:3 = ON:ON (Second Interrupt)
5:3:25:03 - LED 4:3 = ON:OFF (Second interrupt)
5:3:25:04 - LED 4:3 = ON:ON (Second Interrupt)
... etc. LED 1 will toggle every second.

Summary of commands used with fnConfigureRTC():
RTC_TIME_SETTING - pass the time to be set
RTC_TICK_SEC - enable seconds interrupt
RTC_TICK_MIN - enable minutes interrupt
RTC_TICK_HOUR - enable hours interrupt
RTC_TICK_DAY - enable days interrupt
RTC_ALARM_TIME - pass an alarm time and enable alarm interrupt
RTC_STOPWATCH_GO - pass stopwatch count down time (minutes) and enable stopwatch interrupt
RTC_GET_TIME - collect the present time
RTC_DISABLE - set together with other command to disable rather than enable interrupst (eg. RTC_ALARM_TIME  | RTC_DISABLE will disable the Alarm before it goes off)

Expect the support in the M5223X SP5 which will be available quite shortly.

Regards

Mark



268
Hi All

I am in the process of porting the uTasker SAM7X project to work with the tool chain as decribed by James Lynch in his article "Using Open Source Tools for AT91SAM7S Cross Development revision C".

This article and some tutorial files can be loaded from the ATMEL web site - the article is very readable and gives some background to the development of the various tools and a clear step-by-step of installing and getting them running. Therefore it is not worth me giving too much detail here since it is all available in neat and tidy form there. To get the document and the files simply do the following:
1. Go to the web site www.at91.com
2. Click on the register "Documents"
3. Find the document "Using Open Source Tools for AT91SAM7S Cross Development" and click on it.
4. It appears by itself under the title "Key Resources" so click on it again.
5. This will cause "Source package" as download option to appear. Click on this to download a 12.4MByte ZIP file.
In the zip file you will find the famous document (8.6M) which you can follow to obtain all software and install the Eclipse IDE.

This uses the YAGARTO package which is an extremely simple set of 4 executables which install the GCC compiler and libraries, plus all other bits and pieces necessary. It works under Windows without the need for Cygwin or any tedious searching for the various components needed. You can read more about the history of this in James Lynch's article - but it is really easy to use so do have ago.

In fact I have used Eclipse before (for the Coldfire) and I have also compiled the uTasker project with GCC but this path seems the best way to go to ensure that the complete package is really simple and useable.

I can't say how long that it will take until everything is finalised. The uTasker project will run on the ATMEL EVAL board when built with GCC but I know that Emerson had difficulties with this package so it is an oppertunity to clean up and solve any special problems involved.

One important subject is the JTAG debugger used. I studied the various options which are supported by the package and found that the Segger J-Link which I use together with my IAR compiler and IDE will work but it requires another license to work with the debugger [GDB server software]. This license costs $261 (on top of the J-Link price which retails stand-alone for $327). It is repackaged as the ATMEL SAM-ICE JTAG for $129, including the necessary GDB server software. So if you don't have one and want to use it then it seems logical to get the ATMEL offerings. One strange thing about the J-Link GBD server is that it can not program FLASH and so needs either another J-Flash software for $525 or the ATMEL SAM-BA utility.

Anyway I decided that it would be a good idea to try out another solution so have ordered the Olimex ARM-USB-OCD which also works very well (according to James) and is compatible with the OpenOCD daemon which is included in the package. This costs $69.95 and there is a smaller Hobbyist/Student version called the ARM-USB-Tiny for $49.95 (without the serial interface and 5V supply output that the OCD version has). I hope that this will arrive shortly so that I can confirm that it works correctly. In any case it seems to be a more sensible choice seeing as the SAM7X is most popular in the educational world and so will probably be the preferred parts due to its affordable price.

I will report here again as soon as I have some results. If anyone else is interested in being involved just let me known.

Regards

Mark



269
µTasker general / Working with tasks
« on: August 03, 2007, 11:38:11 AM »
Hi All

One question which is often asked is about how to create new tasks. The basics to this are in the document about the operating system basics but it would be interesting to have various examples so here are some:

1. Every task requires first a unique name. For example the watchdog task has the name "Wdog". This string is quite useful when working in debug mode in the tasking part of the code since the name can be displayed. However the actual scheduling works only with the first letter of the name - this is since it is much more efficient to compare just the first letter than a string and keeps with the goals of the uTasker which are to achieve a high level of code size and speed efficiency but still keep a useful degree of comfort.

2. In order to work with the task a simple define is required:
#define TASK_WATCHDOG           'W'                                      // watchdog task
which corresponds to the first letter of the name.

3. In order to add a new task, simply define a name with unique first letter or number, or any other sign. Try to match the name to the tasks job but still do this without colliding with an existing name - capitals and small letters are of course not equal.

#define TASK_MY_NEW_ONE           'n'                                    // my new task task
"new task.."                      // the name we will give it

4. Every task requires a function which is called when it is scheduled

Code: [Select]
#include "config.h"

#define OWN_TASK  TASK_MY_NEW_ONE

void fnMyNewTask(TTASKTABLE *ptrTaskTable)                                // task function
{
}

but before it can actually be used it must be defined in the task table as well as in the node list.
Note that the task table entry defines the properties of the task (at least when it first starts) but it doesn't cause the task actually to be created. It is only created when its reference is ALSO in the node list. The idea behind this is that various node lists can be defined (eg. one for each node in a distributed system) which then create only the tasks which are actually needed for it's own work.

const UTASK_TASK ctNodes[] = {                                           // we use a single fixed configuration (single node)
  DEFAULT_NODE_NUMBER,                                                   // configuration our single node
  TASK_MY_NEW_ONE,
  0,                                                                     // end of single configuration

  // insert more node configurations here if required
  0                                                                      // end of configuration list
};

extern void fnMyNewTask(TTASKTABLE *);

const UTASKTABLEINIT ctTaskTable[] = {
  { "Wdog",      fnTaskWatchdog, NO_QUE,   0, (DELAY_LIMIT)( 0.2 * SEC ),  UTASKER_GO}, // watchdog task (runs immediately and then periodically)
  { "new task..",fnMyNewTask, NO_QUE,   0, 0,  UTASKER_STOP},                           // new task not doing much yet
};

When the system starts, the resources for the new task will now be created. In this case the task will have no input queue and no timers associated with it. In fact it will not do much and never be scheduled by the tasker.
It could however be activated from another task in the system when it calls uTaskerStateChange(TASK_MY_NEW_ONE, UTASKER_ACTIVATE);

This will cause the new task to be scheduled once before it is set back to the UTASKER_STOP state.

If it is started using uTaskerStateChange(TASK_MY_NEW_ONE, UTASKER_GO); it will cause the task to be scheduled every time the tasker cycles. This will then convert the task into a polling task.

However it can of course also be immediately started as a polling task by already defining it like that in the task list.
  { "new task..",fnMyNewTask, NO_QUE,   0, 0,  UTASKER_GO},

5. Now it may be that you have some code which you would like to add to the project which looks something like this:

Code: [Select]
int main(void)
{
    fnInitialiseSomeThings();

    while (1) {
        if (event1 != 0) {
            fnHandleEvent1();
        }
        if (event2 != 0) {
            fnHandleEvent2();
        }
        if (event3 != 0) {
            fnHandleEvent3();
        }
    }
}

SUch code don't assume any operating system and is build around polling for events to take place, which may be flagged from interrupt routines or by other events. The question is how to allow this code or may be several similar modules which are constructed like this to operate in a way that all receive processing rources and all can live along side the uTasker demo project (or similar) with its TCP/IP resouces?

The answer is in this case thankfully very simple. Since it is based on polling anyway we simply add each module to a polling task:

Code: [Select]
void fnMyNewTask(TTASKTABLE *ptrTaskTable)
{
    static iTaskState = 0;

    if (iTaskState == 0) {
        fnInitialiseSomeThings();
        iTaskState = 1;
    }

    if (event1 != 0) {
        fnHandleEvent1();
    }
    if (event2 != 0) {
        fnHandleEvent2();
    }
    if (event3 != 0) {
        fnHandleEvent3();
    }
}


Now we have these modules and the complete demo project working along side each other.

6. If for some reason one of the modules needs to start delayed this can be achieved by defining the task characteristics accordingly:

  { "new task..",fnMyNewTask, NO_QUE,   (DELAY_LIMIT)(5.10 * SEC), 0,  UTASKER_STOP},

Now this task will be started after a delay of 5.1s. However it will only be started once but it can turn itself into a polling task by simply making the following change:

Code: [Select]
    if (iTaskState == 0) {
        fnInitialiseSomeThings();
        iTaskState = 1;
        uTaskerStateChange(OWN_TASK, UTASKER_GO);                        // switch to polling mode of operation
    }


7. If the polling rate of the task, which is presently as fast as the task list is being worked through, is not needed to be so fast it could be set to a user-defined rate by changing the task definition again (and removing the uTaskerStateChange(OWN_TASK, UTASKER_GO); command):
  { "new task..",fnMyNewTask, NO_QUE,   (DELAY_LIMIT)(5.10 * SEC), (DELAY_LIMIT)(0.10 * SEC),  UTASKER_STOP},
Now the first time the task is scheduled is after 5.1s and afterwards it will be scheduled (polled) every 100ms.

8. The polling is in fact using a monostable task time which was created according to the task configuration. The task still has no input queue, but this if OK because the monostable task timer wakes the task for scheduling without needing to place any messages into its queue. The disadvantage of this is simply that it is only possible to have a single timer event. If the different event should be polled at different rates we could do this by using a different technique. (Note that when using GLOBAL_TIMER_TASK support a single task can also have several timers associated to it - this is described in the corresponding document!).

  { "new task..",fnMyNewTask, SMALL_QUEUE,   (DELAY_LIMIT)(5.10 * SEC), 0,  UTASKER_STOP},

Code: [Select]
void fnMyNewTask(TTASKTABLE *ptrTaskTable)
{
    static iTaskState = 0;
    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input
    unsigned char       ucInputMessage[SMALL_QUEUE];                     // reserve space for receiving messages

    if (iTaskState == 0) {
        fnInitialiseSomeThings();
        iTaskState = 1;
        uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(1.5*SEC), E_TIMER_EVENT1 );
    }

    while ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH )) {   // check input queue
        switch ( ucInputMessage[ MSG_SOURCE_TASK ] ) {                   // switch depending on message source
        case TIMER_EVENT:
            switch (ucInputMessage[ MSG_TIMER_EVENT ]) {
            case E_TIMER_EVENT1:
                fnHandleEvent1();
                uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(0.1*SEC), E_TIMER_EVENT2 );
                break;
            case E_TIMER_EVENT2:
                fnHandleEvent2();
                uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(0.05*SEC), E_TIMER_EVENT3 );
                break;
            case E_TIMER_EVENT3:
                fnHandleEvent3();
                uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(1.5*SEC), E_TIMER_EVENT1 );
                break;
            default:
                break;
            }
            break;
        default;
            break;
        }
    }
}

Now the task is controlling its own delays on an event basis [1.5s, 100ms, 50ms]. It needs now an input queue so that it can distinguish between the timer events. Its task definition still has a 5.1s delay before it is first scheduled and this causes it to also to be defined with the appropriate timer resources.

9. If there is no start delay required, the following can be used:
  { "new task..",fnMyNewTask, SMALL_QUEUE,   (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0,  UTASKER_ACTIVATE},

This will cause it to immediately be scheduled once at start. It is however created with the required timer resources which it will use later.


Using these simple techniques quite interesting things can already be performed.
In the next part of this series of examples I will show how the operating system support and its drivers can enable a more modular software design of a project which is easier to maintain and expand. These features will allow the simple reconstruction of projects which are using less efficient polling techniques to become fully event driven. Tasks will only operate when there is really work to do.

Regards

Mark


270
µTasker general / Using TCP in the uTasker project
« on: July 20, 2007, 10:18:51 PM »
Hi All

The uTasker demo project uses TCP for several services. These include HTTP, SMTP, FTP, TIME SERVER and TELNET, to name the ones which initially spring to mind.

The demo project enables these services to be easily studied and own services to be written (usually termed clients and servers) based on these example. There is, at the time of writing, no 'official' document which contains a definitive guide.

This is logically the reason why the use of TCP is a frequent question and frequent discussion topic in private mails. It is also a reason why this document, which is long overdue, should soon be made available.

Therefore this thread is designed to be an introduction to the subject to answer the first burning questions and to give first practical examples, as well as more detailed insight into how it works, how it can be used and why it all works like that. If all goes well, the thread comntent can be moved to a more structured document at a later point in time.

TCP is in fact a very simple protocol - in its simpest form. But in order to allow it to perform with the speed and reliability which has enabled it to become originally the standard in the Internet and eventually the standard in almost all networks it does need a few additional frills which can then make it quite complicated indeed.

If you would like to discuss standard TCP details please feel free to create your own topic to get a discussion going. I have always found it very difficult to find any really meaningful discussions about the practical aspects in the Internet so it would be nice to be able to find some good ones here!


A simple TCP server example. (The HTTP service is a good source for reference).

First we get a socket from the TCP socket pool. The size of the socket pool is defined in config.h, where the define USER_TCP_SOCKETS can be incremented for every additional socket which user code (as opposed to standard services like HTTP) will need.
The following configures a socket with the defined characteristic (minimum delay as opposed to maximum throughput or maximum reliability - these are router parameters), a timeout of 10 seconds (after this length of time with no activity it will close the connection. A value 0xffff means no timeout!), and a callback routine called fnTestListener() which will be doing the work later.

Code: [Select]
static USOCKET Test_socket = -1;                                          // declare a static socket variable
...
    Test_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, (unsigned short)10, fnTestListener); // from task or sub-routine code

The socket is not in the listening state (which is needed for it to act as a server) so we start it in this state by calling
Code: [Select]
static unsigned short usTestPort = 0x9999;                               // declare a static socket variable (the value could also be fixed)
....
    fnTCP_Listen(test_socket, usTestPort, 0);                             // after getting the socket, bind it to a listening port

Now the socket is listening on port 0x9999, which means if you have a test client (eg. Telnet on this port) send a connection request to it it will start a connection process.
Note that the parameter 0 when setting the listening state is the maximum windows size which the connection can receive - a zero defaults to the standard LAN TCP pay load size of 1460 bytes. For some applications with special buffer restrictions this can be used to improve flow control in the rx sense (CONTROL_WINDOW_SIZE needs to be enabled in config.h) but this won't be described here just yet.

The simple server listener looks something like this.

Code: [Select]
#define TEST_BUFFER_LENGTH 10
typedef struct stTCP_MESSAGE
{
    TCP_HEADER     tTCP_Header;     // reserve header space
    unsigned char   ucTCP_Message[TEST_BUFFER_LENGTH];
} TCP_MESSAGE;

static int fnTestListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen) {
   TCP_MESSAGE test_message;

    switch (ucEvent) {
    case TCP_EVENT_CONREQ:                                             
    case TCP_EVENT_CONNECTED:
    case TCP_EVENT_CLOSE:
    case TCP_EVENT_ACK:
    case TCP_EVENT_ARP_RESOLUTION_FAILED:
    case TCP_EVENT_PARTIAL_ACK:
        break;
    case TCP_EVENT_REGENERATE:
    case TCP_EVENT_DATA:
        if ((ucEvent == TCP_EVENT_REGENERATE) || (!uMemcmp((CHAR*)ucIp_Data, "TEST" , 4))) {
            uStrcpy((CHAR*)test_message.ucTCP_Message, "Hi!!");
            if (fnSendTCP(Socket, (unsigned char *)&test_message.tTCP_Header, 4, TCP_FLAG_PUSH) > 0) {
                return APP_SENT_DATA;
            }
        }
        break;
    case TCP_EVENT_ABORT:
    case TCP_EVENT_CLOSED:
        fnTCP_Listen(Socket, ++usTestPort, 0);                    // go back to listening state on next port number
        break;
    }
    return APP_ACCEPT;
}

As you can see it receives events from the TCP layer, some with other details such as a pointer to data.

This is a list of the events which can arrive:

  • TCP_EVENT_ABORT               TCP connection was closed (due to error or a reset from peer)
  • TCP_EVENT_CONNECTED        TCP connection has been successfully established
  • TCP_EVENT_ACK                   Data which we sent have been successfully acknowledged (for all sent data, with outstanding acks)
  • TCP_EVENT_DATA                 Data frame received with data content for us to treat
  • TCP_EVENT_CLOSE                Peer is starting a close of the present TCP connection
  • TCP_EVENT_CLOSED              The TCP connection has been fully closed
  • TCP_EVENT_REGENERATE       The last data frame was lost and must be resent!!!
  • TCP_EVENT_CONREQ              A peer wants to establish a TCP connection (SYN received)
  • TCP_EVENT_ARP_RESOLUTION_FAILED  Generally only when working as client and sending a connection request or data after a longer period of no activity. It means that the the SYN or the data could not be sent by the IP layer since the address of the destination could not be resolved (destination powered down or network problem, or just doesn’t exist). In this cause the application is informed that the connection is either not possible of the connection has broken down due to this.
  • TCP_EVENT_PARTIAL_ACK       This is only used when Windowing is in operation. Presently only TELNET uses it. It means that an ACK has been received for a part of the data which has been sent (rather that all data that has been sent). This is used to acknowledge that only a part of the data has been successfully delivered rather than all outstanding data. This has to be treated differently to a normal ACK event since the ack number has to be used to calculate which outstanding data acks are still open and expect their own ack later.

Now if you are new to TCP, enter in the above test program - best in the simulator - and you can see your first simple TCP server in operation. It won't do a lot but it will at least do the following.

1. When the client requests a connection to port 0x9999 the event TCP_EVENT_CONREQ will be received. Here it would be possible to deny the connection to a black-listed IP for example but our server always allows connections.
2. The TCP connection will be established and the event TCP_EVENT_CONNECTED is received.
3. If the client sends any data it will arrive with the event TCP_EVENT_DATA. The server will only respond to the message "TEST" in which case it will send the string "Hi!!" as answer.
4. After 10s with no activity, the server will close the connection (it is actually TCP that does this after the idle timer fires but the server receives the event TCP_EVENT_CLOSED when the connection has successfully closed).
5. The lister socket is not active after the connection has been closed so the code sets it up as listener again, this time with port number 0x999a.
6. If the connection is repeated, the port number is always incremented each time and the connection always times out after 10s.

Note that when the server sends data it returns APP_SENT_DATA. This informs TCP that the application has just successfully sent something and TCP doesn't have to acknowledge the received data - the ack has already been piggy-backed with the transmitted data.

If the transmission were to fail and need repeating, the server has to handle the event TCP_EVENT_REGENERATE. Since we only ever send one message it is obviouse that this has failed and so it is simply resent. The event TCP_EVENT_ACK will be received when the transmitted message actually has arrived safely.
It is in fact a great shame that messages can and do get lost (but it is not a perfect world and so we have to be ready for it) because regeneration of previously sent messages is probably the most complicated and/or RAM consuming parts of TCP implementations. This example has it real easy, but this is also a real simple example!

Here is a list of all possible return codes from the listener.

  • APP_ACCEPT             This is normal return when no data has been sent. The TCP level will then acknowledge the received frame and the connection will continue
  • APP_SENT_DATA       The listener is informing TCP that it has sent data (be sure that data was really sent when returning this, it should not be returned if a transmission attempt failed)
    The TCP level will therefore not send an ACK of its own since the data will have had a piggy-back ack of its own. If there is a mistake and data is sent and APP_ACCEPT is returned it is not serious – there will simply be an unnecessary ACK sent which doesn’t actually hurt anything (just not so efficient)
  • APP_REJECT             This is used to reject a connection (for example if the IP address is on a black list…) It causes TCP level to return a RESET rather than perform the TCP connection sequence
  • APP_REQUEST_CLOSE    The application informs TCP that the application has just actively started the close of the present TCP connection.
    It is returned after the application calls fnTCP_close(socket); 
  • APP_REJECT_DATA       This is a special case where the application doesn’t want to accept data at the moment. It doesn’t cause the connection to be broken down but TCP will not ACK the data. The peer will then be forced to repeat the data – resulting in a delay (using the peer as a queue, possibly until data can be received).
  • APP_WAIT                Same as previous but delay on TCP connection establishment.

Our example has made use of very few features up to now and there is much more to be explained. However this should allow first steps to be taken and also the servers in the project (HTTP, FTP etc.) to already make a lot more sense.

I will continue the topic later with a first simple client example. If you already have confusions or questions, or corrections etc. please feel free to comment.

Regards

Mark

Pages: 1 ... 16 17 [18] 19