]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cr4/drivers/Dio.c
Merge in from fixes branch
[arc.git] / arch / arm / arm_cr4 / drivers / Dio.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 #include "Std_Types.h"\r
18 #include "Dio.h"\r
19 #include "Det.h"\r
20 #include "Cpu.h"\r
21 #include <string.h>\r
22 \r
23 GIO_RegisterType *GPIO_ports[] = { GIO_PORTA_BASE, GIO_PORTB_BASE };\r
24 \r
25 #define DIO_GET_PORT_FROM_CHANNEL_ID(_channelId) (_channelId >> 8)\r
26 #define DIO_GET_BIT_FROM_CHANNEL_ID(_channelId) (1 << (_channelId & 0x1F))\r
27 \r
28 #if ( DIO_DEV_ERROR_DETECT == STD_ON )\r
29 static int Channel_Config_Contains(Dio_ChannelType channelId)\r
30 {\r
31         Dio_ChannelType* ch_ptr=(Dio_ChannelType*)(&DioChannelConfigData);\r
32         int rv=0;\r
33         while (DIO_END_OF_LIST!=*ch_ptr)\r
34         {\r
35         if (*ch_ptr==channelId)\r
36         {\r
37                 rv=1;\r
38                 break;\r
39         }\r
40         ch_ptr++;\r
41         }\r
42         return rv;\r
43 }\r
44 \r
45 static int Port_Config_Contains(Dio_PortType portId)\r
46 {\r
47         Dio_PortType* port_ptr=(Dio_PortType*)(&DioPortConfigData);\r
48         int rv=0;\r
49         while (DIO_END_OF_LIST!=*port_ptr)\r
50         {\r
51         if (*port_ptr==portId)\r
52         { rv=1; break;}\r
53         port_ptr++;\r
54         }\r
55         return rv;\r
56 }\r
57 \r
58 static int Channel_Group_Config_Contains(const Dio_ChannelGroupType* _channelGroupIdPtr)\r
59 {\r
60         Dio_ChannelGroupType* chGrp_ptr=(Dio_ChannelGroupType*)(&DioConfigData);\r
61         int rv=0;\r
62 \r
63         while (DIO_END_OF_LIST!=chGrp_ptr->port)\r
64         {\r
65         if (chGrp_ptr->port==_channelGroupIdPtr->port&&\r
66                 chGrp_ptr->offset==_channelGroupIdPtr->offset&&\r
67                 chGrp_ptr->mask==_channelGroupIdPtr->mask)\r
68         { rv=1; break;}\r
69         chGrp_ptr++;\r
70         }\r
71         return rv;\r
72 }\r
73 \r
74 #define VALIDATE_CHANNEL(_channelId, _api) \\r
75         if(0==Channel_Config_Contains(channelId)) {     \\r
76                 Det_ReportError(MODULE_ID_DIO,0,_api,DIO_E_PARAM_INVALID_CHANNEL_ID ); \\r
77                 level = 0;      \\r
78                 goto cleanup;   \\r
79                 }\r
80 #define VALIDATE_PORT(_portId, _api)\\r
81         if(0==Port_Config_Contains(_portId)) {\\r
82                 Det_ReportError(MODULE_ID_DIO,0,_api,DIO_E_PARAM_INVALID_PORT_ID ); \\r
83                 level = STD_LOW;\\r
84                 goto cleanup;\\r
85         }\r
86 #define VALIDATE_CHANNELGROUP(_channelGroupIdPtr, _api)\\r
87         if(0==Channel_Group_Config_Contains(_channelGroupIdPtr)) {\\r
88                 Det_ReportError(MODULE_ID_DIO,0,_api,DIO_E_PARAM_INVALID_GROUP_ID ); \\r
89                 level = STD_LOW;\\r
90                 goto cleanup;\\r
91         }\r
92 #else\r
93 #define VALIDATE_CHANNEL(_channelId, _api)\r
94 #define VALIDATE_PORT(_portId, _api)\r
95 #define VALIDATE_CHANNELGROUP(_channelGroupIdPtr, _api)\r
96 #endif\r
97 \r
98 Dio_PortLevelType Dio_ReadPort(Dio_PortType portId)\r
99 {\r
100         Dio_PortLevelType level = 0;\r
101         VALIDATE_PORT(portId, DIO_READPORT_ID);\r
102 \r
103         level = (uint8)GPIO_ports[portId]->DIN;\r
104 \r
105         cleanup: return level;\r
106 }\r
107 \r
108 void Dio_WritePort(Dio_PortType portId, Dio_PortLevelType level)\r
109 {\r
110     VALIDATE_PORT(portId, DIO_WRITEPORT_ID);\r
111 \r
112         GPIO_ports[portId]->DOUT = (uint32)level;\r
113 \r
114     cleanup: return;\r
115 }\r
116 \r
117 Dio_LevelType Dio_ReadChannel(Dio_ChannelType channelId)\r
118 {\r
119         Dio_LevelType level;\r
120         VALIDATE_CHANNEL(channelId, DIO_READCHANNEL_ID);\r
121 \r
122         Dio_PortLevelType portVal = Dio_ReadPort(DIO_GET_PORT_FROM_CHANNEL_ID(channelId));\r
123         Dio_PortLevelType bit = DIO_GET_BIT_FROM_CHANNEL_ID(channelId);\r
124 \r
125         if ((portVal & bit) != STD_LOW){\r
126                 level = STD_HIGH;\r
127         } else{\r
128                 level = STD_LOW;\r
129         }\r
130 \r
131         cleanup: return (level);\r
132 }\r
133 \r
134 void Dio_WriteChannel(Dio_ChannelType channelId, Dio_LevelType level)\r
135 {\r
136         VALIDATE_CHANNEL(channelId, DIO_WRITECHANNEL_ID);\r
137 \r
138         Dio_PortType port = DIO_GET_PORT_FROM_CHANNEL_ID(channelId);\r
139         uint16 bit = DIO_GET_BIT_FROM_CHANNEL_ID(channelId);\r
140 \r
141         if (!( GPIO_ports[port]->DIR & bit)) { // This is an input channel.\r
142                 goto cleanup;\r
143         }\r
144 \r
145         Dio_PortLevelType portVal = Dio_ReadPort(port);\r
146 \r
147         if(level == STD_HIGH){\r
148                 portVal |= bit;\r
149         }else{\r
150                 portVal &= ~bit;\r
151         }\r
152 \r
153         Dio_WritePort(port, portVal);\r
154 \r
155         cleanup: return;\r
156 }\r
157 \r
158 \r
159 Dio_PortLevelType Dio_ReadChannelGroup(\r
160     const Dio_ChannelGroupType *channelGroupIdPtr)\r
161 {\r
162         Dio_LevelType level;\r
163         VALIDATE_CHANNELGROUP(channelGroupIdPtr,DIO_READCHANNELGROUP_ID);\r
164 \r
165         // Get masked values\r
166         level = Dio_ReadPort(channelGroupIdPtr->port) & channelGroupIdPtr->mask;\r
167 \r
168         // Shift down\r
169         level = level >> channelGroupIdPtr->offset;\r
170 \r
171         cleanup: return level;\r
172 }\r
173 \r
174 void Dio_WriteChannelGroup(const Dio_ChannelGroupType *channelGroupIdPtr,\r
175     Dio_PortLevelType level)\r
176 {\r
177         VALIDATE_CHANNELGROUP(channelGroupIdPtr,DIO_WRITECHANNELGROUP_ID);\r
178 \r
179         // Shift up and apply mask so that no unwanted bits are affected\r
180         level = (level << channelGroupIdPtr->offset) & channelGroupIdPtr->mask;\r
181 \r
182         // Read port and clear out masked bits\r
183         Dio_PortLevelType portVal = Dio_ReadPort(channelGroupIdPtr->port) & (~channelGroupIdPtr->mask);\r
184 \r
185         // Or in the upshifted masked level\r
186         portVal |= level;\r
187 \r
188         Dio_WritePort(channelGroupIdPtr->port, portVal);\r
189 \r
190         cleanup: return;\r
191 }\r
192 \r
193 \r