]> begriffs open source - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_M0_LPC43xx_Keil/M4/ParTest.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / CORTEX_M4F_M0_LPC43xx_Keil / M4 / ParTest.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /*-----------------------------------------------------------\r
30  * Normally, a demo application would define ParTest (parallel port test)\r
31  * functions to write to an LED.  In this case, four '*' symbols that are\r
32  * output to the debug printf() port are used to simulate LED outputs.\r
33  *-----------------------------------------------------------*/\r
34 \r
35 /* Standard includes. */\r
36 #include <stdio.h>\r
37 #include <string.h>\r
38 \r
39 /* Library includes. */\r
40 #include "lpc43xx_i2c.h"\r
41 \r
42 /* Kernel includes. */\r
43 #include "FreeRTOS.h"\r
44 #include "task.h"\r
45 #include "queue.h"\r
46 \r
47 /* Standard demo include. */\r
48 #include "partest.h"\r
49 \r
50 /* The number of LED outputs. */\r
51 #define partstMAX_LEDS 4\r
52 \r
53 /* Commands written to the PCA9502. */\r
54 #define partstIO_WRITE_COMMAND  ( ( unsigned char ) ( 0x0BU << 3U ) )\r
55 #define partstIO_DIR_COMMAND    ( ( unsigned char ) ( 0x0AU << 3U ) )\r
56 #define partstSLAVE_ADDRESS             ( ( unsigned char ) ( 0x9AU >> 1U ) )\r
57 \r
58 /* Just defines the length of the queue used to pass toggle commands to the I2C\r
59 gatekeeper task. */\r
60 #define partstLED_COMMAND_QUEUE_LENGTH  ( 6 )\r
61 /*-----------------------------------------------------------*/\r
62 \r
63 /*\r
64  * The LEDs are connected to an I2C port expander.  Therefore, writing to an\r
65  * LED takes longer than might be expected if the LED was connected directly\r
66  * to a GPIO pin.  As several tasks, and a timer, toggle LEDs, it is convenient\r
67  * to use a gatekeeper task to ensure access is both mutually exclusive and\r
68  * serialised.  Tasks other than this gatekeeper task must not access the I2C\r
69  * port directly.\r
70  */\r
71 static void prvI2CGateKeeperTask( void *pvParameters );\r
72 \r
73 /* The queue used to communicate toggle commands with the I2C gatekeeper\r
74 task. */\r
75 static QueueHandle_t xI2CCommandQueue = NULL;\r
76 /*-----------------------------------------------------------*/\r
77 \r
78 void vParTestInitialise( void )\r
79 {\r
80 unsigned char ucBuffer[ 2 ];\r
81 I2C_M_SETUP_Type xI2CMessage;\r
82 \r
83         /* The LEDs are on an I2C IO expander.  Initialise the I2C interface. */\r
84         I2C_Init( LPC_I2C0, 300000 );\r
85         I2C_Cmd( LPC_I2C0, ENABLE );\r
86 \r
87         /* GPIO0-GPIO2 to output. */\r
88         ucBuffer[ 0 ] = partstIO_DIR_COMMAND;\r
89         ucBuffer[ 1 ] = 0x0f;\r
90         xI2CMessage.sl_addr7bit = partstSLAVE_ADDRESS;\r
91         xI2CMessage.tx_data = ucBuffer ;\r
92         xI2CMessage.tx_length = sizeof( ucBuffer );\r
93         xI2CMessage.rx_data = NULL;\r
94         xI2CMessage.rx_length = 0;\r
95         xI2CMessage.retransmissions_max = 3;\r
96         I2C_MasterTransferData( LPC_I2C0, &xI2CMessage, I2C_TRANSFER_POLLING );\r
97 \r
98         /* Create the mutex used to guard access to the I2C bus. */\r
99         xI2CCommandQueue = xQueueCreate( partstLED_COMMAND_QUEUE_LENGTH, sizeof( unsigned char ) );\r
100         configASSERT( xI2CCommandQueue );\r
101 \r
102         /* Create the I2C gatekeeper task itself. */\r
103         xTaskCreate( prvI2CGateKeeperTask, "I2C", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );\r
104 }\r
105 /*-----------------------------------------------------------*/\r
106 \r
107 void vParTestToggleLED( unsigned long ulLED )\r
108 {\r
109 unsigned char ucLED = ( unsigned char ) ulLED;\r
110 \r
111         /* Only the gatekeeper task will actually access the I2C port, so send the\r
112         toggle request to the gatekeeper task.  A block time of zero is used as\r
113         this function is called by a software timer callback. */\r
114         xQueueSend( xI2CCommandQueue, &ucLED, 0UL );\r
115 }\r
116 /*-----------------------------------------------------------*/\r
117 \r
118 static void prvI2CGateKeeperTask( void *pvParameters )\r
119 {\r
120 unsigned char ucBuffer[ 2 ], ucLED;\r
121 static unsigned char ucLEDState = 0xffU;\r
122 static I2C_M_SETUP_Type xI2CMessage; /* Static so it is not on the stack as this is called from task code. */\r
123 \r
124         /* Just to remove compiler warnings. */\r
125         ( void ) pvParameters;\r
126 \r
127         for( ;; )\r
128         {\r
129                 /* Wait for the next command. */\r
130                 xQueueReceive( xI2CCommandQueue, &ucLED, portMAX_DELAY );\r
131 \r
132                 /* Only this task is allowed to touch the I2C port, so there is no need\r
133                 for additional mutual exclusion. */\r
134                 if( ucLED < partstMAX_LEDS )\r
135                 {\r
136                         /* Which bit is being manipulated? */\r
137                         ucLED = 0x01 << ucLED;\r
138 \r
139                         /* Is the bit currently set or clear? */\r
140                         if( ( ucLEDState & ucLED ) == 0U )\r
141                         {\r
142                                 ucLEDState |= ucLED;\r
143                         }\r
144                         else\r
145                         {\r
146                                 ucLEDState &= ~ucLED;\r
147                         }\r
148 \r
149                         ucBuffer[ 0 ] = partstIO_WRITE_COMMAND;\r
150                         ucBuffer[ 1 ] = ucLEDState;\r
151 \r
152                         xI2CMessage.sl_addr7bit = partstSLAVE_ADDRESS;\r
153                         xI2CMessage.tx_data = ucBuffer ;\r
154                         xI2CMessage.tx_length = sizeof( ucBuffer );\r
155                         xI2CMessage.rx_data = NULL;\r
156                         xI2CMessage.rx_length = 0;\r
157                         xI2CMessage.retransmissions_max = 3;\r
158                         I2C_MasterTransferData( LPC_I2C0, &xI2CMessage, I2C_TRANSFER_POLLING );\r
159                 }\r
160         }\r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r