µTasker Forum
µTasker Forum => µTasker general => Topic started by: mark on March 06, 2009, 04:01:51 PM
-
Hi All
During the course of updates of user documents the example source code is being added to this thread to enable quick copying of the related code examples.
Regards
Mark
*****************************************************************************
µTasker User Guide – First Steps for New Users
5. Adding a New Task to Your Project
#include "config.h" // include all project headers if this is a new file
extern void fnMyFirstTask(TTASKTABLE *ptrTaskTable)
{
static unsigned char ucCounter = 0;
fnDebugMsg("Hello, World! Test number ");
fnDebugDec(ucCounter++, 0); // note that V1.3 code used an addition , 0 due to a change in this function's use
fnDebugMsg("\r\n");
}
#define DEMO_UART 1 // use UART 1 (the UART connector on the board) )
#define SERIAL_PORT_0 '3' // if we open UART channel 0 we simulate using com3 on the PC
or
#define SIM_COM_EXTENDED // this uses the value literally and not the ASCII value, which otherwise restricts to COM1..9
#define SERIAL_PORT_0 3 // if we open UART channel 0 we simulate using com3 on the PC
extern void fnMyFirstTask(TTASKTABLE *ptrTaskTable); // prototype
#define TASK_MY_FIRST_TASK 'x' // my first task's reference
const UTASK_TASK ctNodes[] = {
DEFAULT_NODE_NUMBER, // configuration the single node
TASK_WATCHDOG,
...
TASK_MY_FIRST_TASK, // add the task to the configuration
0, // end of single configuration
// insert more node configurations here if required
0 // end of configuration list
};
const UTASKTABLEINIT ctTaskTable[] = {
{ "Wdog",fnTaskWatchdog,NO_QUE,0,(DELAY_LIMIT)(0.2 * SEC), UTASKER_GO}, // watchdog task (runs immediately and then periodically)
...
{ "x marks my first task!!", fnMyFirstTask, NO_QUE,(DELAY_LIMIT)(5 * SEC), (DELAY_LIMIT)(2 * SEC), UTASKER_STOP}, // my first task (runs after a delay of 5s and then periodically every 2s)
...
};
6 Second Example – The Task being configured by another
{ “x marks my first task!!”,
fnMyFirstTask,
NO_QUE,(DELAY_LIMIT)(NO_DELAY_RESERVE_MONO),
(DELAY_LIMIT)(0), UTASKER_STOP},
// my first task (a timer has been reserved for its use but not need activated)
if (!fnSetNewSerialMode(FOR_I_O)) { // open serial port for I/O
return; // if the serial port could not be opened we quit
}
DebugHandle = SerialPortID; // assign our serial interface as debug port
uTaskerStateChange(TASK_MY_FIRST_TASK, UTASKER_ACTIVATE);
// activate the new task
uTaskerMonoTimer( TASK_MY_FIRST_TASK, (DELAY_LIMIT)(3 * SEC), 0 );
// set periodic interval
7. Third Example – Adding a Queue to Your Task and getting it to do a bit more Work
{ "x marks my first task!!",
fnMyFirstTask,
SMALL_QUEUE,
(DELAY_LIMIT)(NO_DELAY_RESERVE_MONO),
(DELAY_LIMIT)(0),
UTASKER_STOP},
fnInterruptMessage(TASK_MY_FIRST_TASK, WAKE_UP_LITTLE_BABY);
#define WAKE_UP_LITTLE_BABY 132
#define OWN_TASK TASK_MY_FIRST_TASK
#define E_TIMER_PERIODIC 1
extern void fnMyFirstTask(TTASKTABLE *ptrTaskTable)
{
static unsigned char ucCounter = 0;
QUEUE_HANDLE PortIDInternal = ptrTaskTable->TaskID; // queue ID for task input
unsigned char ucInputMessage[HEADER_LENGTH]; // reserve space for simple messages
while ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH )) { // check input queue
switch ( ucInputMessage[MSG_SOURCE_TASK] ) { // switch on source
case TIMER_EVENT: // timer event
if (E_TIMER_PERIODIC == ucInputMessage[MSG_TIMER_EVENT]) {
fnDebugMsg("Test number ");
fnDebugDec(ucCounter++, 0); // note that V1.3 code used an addition , 0 due to a change in this function's use
fnDebugMsg("\r\n");
if (ucCounter == 10) {
fnDebugMsg("Work done!!\r\n");
ucCounter = 0;
}
else {
uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(1*SEC), E_TIMER_PERIODIC );
}
}
break;
case INTERRUPT_EVENT:
if (WAKE_UP_LITTLE_BABY == ucInputMessage[MSG_INTERRUPT_EVENT]) {
fnDebugMsg("Hello World!!\r\n");
uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(6*SEC), E_TIMER_PERIODIC );
}
}
}
}
*****************************************************************************
-
UART USER'S GUIDE
QUEUE_HANDLE fnOpenUART(void)
{
TTYTABLE tInterfaceParameters; // table for passing information to driver
QUEUE_HANDLE SerialPortID; // UART handle to be obtained during open
tInterfaceParameters.Channel = 1; // set UART channel for serial use
tInterfaceParameters.ucSpeed = SERIAL_BAUD_19200; // baud rate 19’200
tInterfaceParameters.Rx_tx_sizes.RxQueueSize = 256; // input buffer size
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = 512; // output buffer size
tInterfaceParameters.Task_to_wake = TASK_APPLICATION; // wake task on rx
#ifdef SUPPORT_FLOW_HIGH_LOW
tInterfaceParameters.ucFlowHighWater = 80; // set the flow control high in %
tInterfaceParameters.ucFlowLowWater = 20; // set the flow control low in %
#endif
tInterfaceParameters.usConfig =
(CHAR_8 + NO_PARITY + ONE_STOP + USE_XON_OFF + CHAR_MODE);
#ifdef SERIAL_SUPPORT_DMA
tInterfaceParameters.ucDMAConfig = UART_TX_DMA; // activate DMA on transmission
#endif
if ((SerialPortID = fnOpen( TYPE_TTY, FOR_I_O, &tInterfaceParameters )) != 0) {
// open the channel with defined configurations (initially inactive)
fnDriver(SerialPortID, ( TX_ON | RX_ON ), 0 ); // enable rx and tx
}
return SerialPortID; // return the serial port handle for this UART
}
Code 1 – example of UART initialization
SerialPortID = fnOpen(
TYPE_TTY, // serial interface driver type (UART)
FOR_I_O, // for use as input/output device (Rx/Tx)
&tInterfaceParameters);// configuration details
Code 2 – the fnOpen() function used to open a serial interface
fnDriver(
SerialPortID, // the serial interface handle
( TX_ON | RX_ON ), // enable rx and tx
0 ); // unused parameter in this case
Code 3 – the fnDriver() function used to enable receiver and transmitter
extern void fnApplication(TTASKTABLE *ptrTaskTable)
{
unsigned char ucInputByte;
while (fnRead( SerialPortID, &ucInputByte, 1) != 0) {
while (ucInputByte--) {
toggle_output();
}
}
}
Code 4 – a task receiving characters from a UART with handle SerialPortID
extern void fnApplication(TTASKTABLE *ptrTaskTable)
{
QUEUE_TRANSFER length;
unsigned char ucInputBuffer[100];
while ((length = fnMsgs(SerialPortID)) != 0) {// get number of waiting bytes
if (length > sizeof(ucInputBuffer)) { // ensure buffer can’t be overrun
length = sizeof(ucInputBuffer);
}
fnRead(SerialPortID, ucInputBuffer, length); // read to a local buffer
}
}
Code 5 – a task filling a buffer from a UART with handle SerialPortID
fnWrite(SerialPortID, (unsigned char *)"1234567890", 10);
Code 6 – transmission of a string to a UART with handle SerialPortID
if (fnWrite(SerialPortID, 0, 10) == 0) {
fnDriver(SerialPortID, MODIFY_WAKEUP, (MODIFY_TX | OWN_TASK));
// enable TX_FREE event
}
else {
fnWrite(SerialPortID, (unsigned char *)"1234567890", 10);
}
Code 7 – check of output buffer space before transmission
extern void fnDebug(TTASKTABLE *ptrTaskTable)
{
QUEUE_HANDLE PortIDInternal = ptrTaskTable->TaskID; // queue ID for task input
unsigned char ucInputMessage[SMALL_MESSAGE]; // space for receiving messages
while ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH)) { // read input
switch ( ucInputMessage[ MSG_SOURCE_TASK ] ) { // switch on source
case INTERRUPT_EVENT:
if (TX_FREE == ucInputMessage[MSG_INTERRUPT_EVENT]) {
fnDisplayHelp(iMenuLocation);// continue sending further menu items
}
break;
}
}
Code 8 – Example of specific handling the TX_FREE event
// Initialisation code for RS485 mode
//
tInterfaceParameters.usConfig |= INFORM_ON_FRAME_TRANSMISSION;
SerialPortID = fnOpen( TYPE_TTY, FOR_I_O, &tInterfaceParameters ):
...
fnDriver(SerialHandle, (MODIFY_CONTROL | CONFIG_RTS_PIN), 0);
// configure RTS pin for control use
fnDriver(SerialHandle, (MODIFY_CONTROL | SET_RTS), 0); // initially drive '0'
// Message transmission code for RS485 mode
//
fnDriver(SerialHandle, (MODIFY_CONTROL | CLEAR_RTS), 0); // driver RTS ‘1’
fnWrite(SerialHandle, ucMessageData, length); // start message frame transmission
Code 9 – Example of configuring for RS485 mode operation and controlling the RTS line when starting message frame transmission
// The UART is informing that it has just completed transmission of the last character in a frame.
// This is used to control RTS de-assertion, usually after a delay
//
extern void fnUARTFrameTermination(QUEUE_HANDLE Channel)
{
if (Channel == 2) {
//fnDriver(SerialHandle, (MODIFY_CONTROL | SET_RTS), 0);
can only be used for certain processor types
fnConfigureInterrupt(&timer_setup_RTS_negate);
// start delay to RTS negation
}
}
Code 10 – example of controlling negation of the RTS line on message termination
static TIMER_INTERRUPT_SETUP timer_setup_RTS_negate;
timer_setup_RTS_negate.int_type = TIMER_INTERRUPT
timer_setup_RTS_negate.timer_reference = 2;
timer_setup_RTS_negate.int_priority = 3;
timer_setup_RTS_negate.int_handler = fnTimer_RTS;
timer_setup_RTS_negate.timer_mode = (TIMER_SINGLE_SHOT | TIMER_US_VALUE);
timer_setup_RTS_negate.timer_value = 620; // 620us delay before RTS negation
Code 11 – Example of RTS timer configuration
// Initialisation code for RS485 mode
//
fnDriver(SerialHandle, (MODIFY_CONTROL | CONFIG_RTS_PIN | SET_RS485_MODE), 0);
// configure RTS pin for control use
Code 12 – Configuring for HW RS485 mode operation
extern QUEUE_TRANSFER fnNetworkTx(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes)
{
fnWrite(SerialPortID, output_buffer, nr_of_bytes);
fnWrite(SerialPortID2, output_buffer, nr_of_bytes);
fnWrite(USB_handle, output_buffer, nr_of_bytes);
return (fnSendBufTCP(Telnet_socket, output_buffer, nr_of_bytes, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY)));
}
Code 13 – Example of sending debug output to multiple interfaces
-
Hi
when i try out the first code (5. Adding a New Task to You Projekt) i getting a problem
No source available for "0x0000678C (0x0000678C)() "
This problem i dont understand, is this because my UART not is mapped correct ?
-
Hi
Which IDE gives this error and when does it display it (building the project, executing ?)
It is recommended to first try building and testing with the simulator before moving to HW targets.
Regards
Mark
-
When i have the new Task in the projekt, i could not simulate, it make a problem with _fnMyNewTask. I took it away and try again, the simulate, but the debug still make same problem :(
-
Okay i have now startet a new project, and i have make the new task and its compile and debug without any problems, only that, that i newer get the hello world message out
-
In the simulation i get this error
Error 1 error LNK2001: unresolved external symbol _fnMyFirstTask
and that i dont geth
-
Hi
In the simulator you need to add your new file to the VisualStudio project - then it will not be missing when linking.
Regards
Mark
-
Hi Mark
Thanks i have now done the simulation.
When i debug o wont the text to be written out, is this possible?
-
Hi
When simulating the debug message outputs go to a UART that can be hooked to a physical UART on the PC. Alternatively, and generally more practical, is to use a virtual COM port loop back (com0com is recommended) so that this can be connected to a terminal emulator. This is descrived here: http://www.utasker.com/forum/index.php?topic=343.0
When a project with Ethernet is running it is also practical to connect to it via Telnet since the debug output is sent there instead when a connection exists.
Regards
Mark
-
Hi Mark
I still geth in a lot of trouble doing the debug msg. I have try to debug, and my code newer get in to the seriel configuration wich i have make the configuration in app_hw_kinetis.h:
#ifdef SERIAL_INTERFACE
#define WELCOME_MESSAGE_UART "\r\n\nHello, world... KINETIS\r\n"
#define NUMBER_EXTERNAL_SERIAL 0
#define NUMBER_SERIAL (UARTS_AVAILABLE) // the number of physical queues needed for serial interface(s)
#define SIM_COM_EXTENDED // COM ports defined from 1..255
#define SERIAL_PORT_0 3 // if we open UART channel 0 we simulate using comx on the PC
// #define SERIAL_PORT_1 9 // if we open UART channel 1 we simulate using comx on the PC
// #define SERIAL_PORT_2 9 // if we open UART channel 2 we simulate using comx on the PC
// #define SERIAL_PORT_3 9 // if we open UART channel 3 we simulate using comx on the PC
// #define SERIAL_PORT_4 13 // if we open UART channel 4 we simulate using comx on the PC
// #define SERIAL_PORT_5 9 // if we open UART channel 5 we simulate using comx on the PC
#if defined TWR_K70F120M
#define DEMO_UART 2 // use UART 2
#elif defined TWR_K20N50M // {2}
#define DEMO_UART 1 // use UART 1
#elif defined KWIKSTIK || defined TWR_K60F120M
#define DEMO_UART 5 // use UART 5
#else
#define DEMO_UART 3 // use UART 3
#endif
in config.h:
#define SERIAL_INTERFACE // enable serial interface driver
#ifdef SERIAL_INTERFACE
#define SERIAL_STATS // keep statistics about serial interface use
#define SUPPORT_MSG_MODE // enable terminator recognition (MSG_MODE)
#define SUPPORT_MSG_CNT // enable the message counter mode (MSG_MODE_RX_CNT) - requires also SUPPORT_MSG_MODE
#define WAKE_BLOCKED_TX // allow a blocked transmitter to continue after an interrupt event
//#define WAKE_BLOCKED_TX_BUFFER_LEVEL
I don't get it ! you now what i am doing wrong, i tryet to follow the link you send
-
Hi
Assuming that you are using the TWR_K70F120M, this has its debug output on UART 2.
If you want UART2 to be mapped to COM3 on the PC you need
#define SERIAL_PORT_2 3
You can set other SERIAL_PORT_X values to 0 so that they are disabled.
Regards
Mark
-
Sorry Mark to dredge up an old thread, but I'm trying to get the demo UART working in simulation. Should your instruction above about mapping UART2 not actually be referring to SERIAL_PORT_2 rather than SERIAL_PORT_3
ie, is this correct for mapping UART2 to COM3 on the PC ?
#define SERIAL_PORT_2 3
and a related question about the DEMO_UART - is the number referring to the UART channel on the device, and hence is the correct way to define use of UART channel 0 (ie UART0) as follows
#define DEMO_UART 0
-
Geoff
Yes, there was a type (I edited it now).
To select the UART used as command line interface and general debug message output you select it with DEMO_UART.
This counts the same as the UARTs on the Kinetis.
#define DEMO_UART 0 is thus for UART0.
To connect UART0 to a COM port on the PC you can then use (assuming COM9)
#define SERIAL_PORT_0 9
If you want a virtual loop back (to a terminal emulator) you can use com0com to install some loop-backs. If you configure a loop-back between COM 9 and COM 10 you can open the terminal emulator on COM 10 (before you start the simulator) and then let the simulator run (check the status bar when it runs where it shows with UARTs have been opened and which virtual COM port connections that are using to be sure).
After changing the #define SERIAL_PORT_0 setting do a rebuild since otherwise VS doesn't always build the C++ file using the define and so it doesn't take. With the rebuild it is always good afterwards.
Regards
Mark