00001 /********************************************************************************* 00002 00003 Copyright 2006-2008 MakingThings 00004 00005 Licensed under the Apache License, 00006 Version 2.0 (the "License"); you may not use this file except in compliance 00007 with the License. You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software distributed 00012 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00013 CONDITIONS OF ANY KIND, either express or implied. See the License for 00014 the specific language governing permissions and limitations under the License. 00015 00016 *********************************************************************************/ 00017 00018 // MakingThings - Make Controller Board - 2006 00019 00020 /** \file can.c 00021 CAN - Control Area Network. 00022 Functions for interacting with the CAN Network. 00023 00024 Note this subsystem is not implemented 00025 */ 00026 00027 /* Library includes. */ 00028 #include <string.h> 00029 #include <stdio.h> 00030 00031 /* Scheduler includes. */ 00032 #include "FreeRTOS.h" 00033 #include "task.h" 00034 #include "semphr.h" 00035 00036 /* Hardware specific headers. */ 00037 #include "Board.h" 00038 #include "AT91SAM7X256.h" 00039 00040 #include "config.h" 00041 00042 #include "io.h" 00043 00044 #include "can.h" 00045 #include "can_internal.h" 00046 00047 00048 // CAN DISABLE 00049 #if ( CONTROLLER_VERSION == 50 ) 00050 #define CAN_ENABLE IO_PA02 00051 #define CAN_RX IO_PA19 00052 #define CAN_TX IO_PA20 00053 #endif 00054 #if ( CONTROLLER_VERSION == 90 ) 00055 #define CAN_ENABLE IO_PB16 00056 #define CAN_RX IO_PA19 00057 #define CAN_TX IO_PA20 00058 #endif 00059 #if ( CONTROLLER_VERSION == 95 || CONTROLLER_VERSION == 100 ) 00060 #define CAN_ENABLE IO_PA07 00061 #define CAN_RX IO_PA19 00062 #define CAN_TX IO_PA20 00063 #endif 00064 00065 static int Can_Start( void ); 00066 static int Can_Stop( void ); 00067 00068 static int Can_Init( void ); 00069 00070 extern void ( CanIsr_Wrapper )( void ); 00071 00072 struct Can_ Can; 00073 00074 /* \defgroup Can 00075 * The CAN (Controller Area Network) subsystem allows for fast and reliable board-to-board communication. 00076 * \ingroup Core 00077 * @{ 00078 */ 00079 00080 /** 00081 Sets whether the CAN subsystem is active. 00082 @param state An integer specifying the active state - 1 (on) or 0 (off). 00083 @return 0 on success. 00084 */ 00085 int Can_SetActive( int state ) 00086 { 00087 if ( state ) 00088 return Can_Start( ); 00089 else 00090 return Can_Stop( ); 00091 } 00092 00093 /** 00094 Returns the active state of the CAN subsystem. 00095 @return State - 1/non-zero (on) or 0 (off). 00096 */ 00097 int Can_GetActive( ) 00098 { 00099 return Can.users > 0; 00100 } 00101 00102 /** 00103 Send a CAN message. 00104 @param id An integer specifying the message ID. 00105 @param message A pointer to the message to be sent. 00106 @param count ??? 00107 @return Status - 0 on success. 00108 */ 00109 int Can_SendMessage( int id, char* message, int count ) 00110 { 00111 (void)id; 00112 (void)message; 00113 (void)count; 00114 00115 if ( Can.users < 1 ) 00116 { 00117 int status = Can_Start( ); 00118 if ( status != CONTROLLER_OK ) 00119 return status; 00120 } 00121 00122 int value = 0; 00123 00124 int i; 00125 int j; 00126 00127 for ( i = 0; i < 20; i++ ) 00128 { 00129 Io_SetValue( CAN_TX, 1 ); 00130 for ( j = 0; j < 100; j++ ) 00131 ; 00132 Io_SetValue( CAN_TX, 0 ); 00133 for ( j = 0; j < 100; j++ ) 00134 ; 00135 } 00136 00137 /* 00138 // This is the semaphore that lets only one instance get messages at a time 00139 if ( !xSemaphoreTake( Can.semaphore, 1000 ) ) 00140 return CONTROLLER_ERROR_CANT_LOCK; 00141 00142 // start the business 00143 00144 // Busy wait - nah 00145 // while ( !( AT91C_BASE_ADC->ADC_CHSR & ( 1 << index ) ) ); 00146 00147 // This is the semaphore that signals that it's done 00148 if ( !xSemaphoreTake( Can.doneSemaphore, 1000 ) ) 00149 return CONTROLLER_ERROR_TIMEOUT; 00150 00151 // extract the message 00152 00153 xSemaphoreGive( Can.semaphore ); 00154 00155 00156 // Disable mailbox 0 00157 AT91C_BASE_CAN->CAN_MB0.CAN_MB_MMR = AT91C_CAN_MOT_DIS; 00158 00159 // Set ID to send 00160 AT91C_BASE_CAN->CAN_MB0.CAN_MB_MID = ( ( 0x55 << 18 ) & AT91C_CAN_MIDvA ); 00161 00162 // Set mailbox 0 up as a transmitter 00163 AT91C_BASE_CAN->CAN_MB0.CAN_MB_MMR = AT91C_CAN_MOT_TX; 00164 00165 // Set the length, and transmit 00166 AT91C_BASE_CAN->CAN_MB0.CAN_MB_MCR = ( ( 0x4 << 16 ) & AT91C_CAN_MDLC ) || AT91C_CAN_MTCR; 00167 00168 while ( !AT91C_BASE_CAN->CAN_MB0.CAN_MB_MSR & AT91C_CAN_MRDY ) 00169 ; 00170 */ 00171 return value; 00172 } 00173 00174 /** 00175 Receive a CAN message. 00176 @param id An integer specifying the message ID. 00177 @param message A pointer to where the message should be saved. 00178 @param count ??? 00179 @return Status - 0 on success. 00180 */ 00181 int Can_GetMessage( int* id, char* message, int* count ) 00182 { 00183 (void)id; 00184 (void)message; 00185 (void)count; 00186 00187 if ( Can.users < 1 ) 00188 { 00189 int status = Can_Start( ); 00190 if ( status != CONTROLLER_OK ) 00191 return status; 00192 } 00193 00194 int value = 0; 00195 00196 // This is the semaphore that lets only one instance get messages at a time 00197 if ( !xSemaphoreTake( Can.semaphore, 1000 ) ) 00198 return CONTROLLER_ERROR_CANT_LOCK; 00199 00200 // start the business 00201 00202 /* Busy wait - nah */ 00203 // while ( !( AT91C_BASE_ADC->ADC_CHSR & ( 1 << index ) ) ); 00204 00205 // This is the semaphore that signals that it's done 00206 if ( !xSemaphoreTake( Can.doneSemaphore, 1000 ) ) 00207 return CONTROLLER_ERROR_TIMEOUT; 00208 00209 // extract the message 00210 00211 xSemaphoreGive( Can.semaphore ); 00212 00213 return value; 00214 } 00215 00216 /** @} 00217 */ 00218 00219 int Can_Start() 00220 { 00221 // int status; 00222 if ( Can.users++ == 0 ) 00223 { 00224 Can_Init(); 00225 } 00226 return CONTROLLER_OK; 00227 } 00228 00229 int Can_Stop() 00230 { 00231 if ( Can.users <= 0 ) 00232 return CONTROLLER_ERROR_TOO_MANY_STOPS; 00233 00234 if ( --Can.users == 0 ) 00235 Can_Stop(); 00236 00237 return CONTROLLER_OK; 00238 } 00239 00240 int Can_Init() 00241 { 00242 // Try to lock the enable pin 00243 int status = Io_Start( CAN_ENABLE, true ); 00244 if ( status != CONTROLLER_OK ) 00245 return status; 00246 00247 // Try to lock the tx pin 00248 status = Io_Start( CAN_TX, true ); 00249 if ( status != CONTROLLER_OK ) 00250 { 00251 Io_Stop( CAN_ENABLE ); 00252 return status; 00253 } 00254 00255 // Try to lock the rx pin 00256 status = Io_Start( CAN_RX, true ); 00257 if ( status != CONTROLLER_OK ) 00258 { 00259 Io_Stop( CAN_ENABLE ); 00260 Io_Stop( CAN_TX ); 00261 return status; 00262 } 00263 00264 Io_SetDirection( CAN_TX, true ); 00265 Io_SetDirection( CAN_RX, false ); 00266 Io_SetPullup( CAN_RX, false ); 00267 00268 Io_SetDirection( CAN_ENABLE, true ); 00269 Io_SetValue( CAN_ENABLE, false ); 00270 00271 /* 00272 // Enable the peripheral clock 00273 AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_CAN; 00274 00275 // Make sure the pins are running on the right peripheral (A in this case) 00276 Io_SetPeripheralA( CAN_TX ); 00277 Io_SetPeripheralA( CAN_RX ); 00278 00279 Io_SetOutput( CAN_ENABLE ); 00280 Io_SetValue( CAN_ENABLE, false ); 00281 00282 // Set some random bit timing up. 00283 AT91C_BASE_CAN->CAN_BR = 0x0053255; 00284 00285 // Enable the CAN system 00286 AT91C_BASE_CAN->CAN_MR = AT91C_CAN_CANEN; 00287 00288 // Do the OS stuff 00289 vSemaphoreCreateBinary( Can.semaphore ); 00290 00291 // Create the sempahore that will be used to wake the calling process up 00292 vSemaphoreCreateBinary( Can.doneSemaphore ); 00293 xSemaphoreTake( Can.doneSemaphore, 0 ); 00294 00295 // Do the hardware init 00296 00297 // Initialize the interrupts 00298 00299 // WAS AT91F_AIC_ConfigureIt( AT91C_ID_ADC, 3, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) CanIsr_Wrapper ); 00300 // Which is defined at the bottom of the AT91SAM7X256.h file 00301 unsigned int mask ; 00302 00303 mask = 0x1 << AT91C_ID_CAN; 00304 00305 // Disable the interrupt on the interrupt controller 00306 AT91C_BASE_AIC->AIC_IDCR = mask ; 00307 // Save the interrupt handler routine pointer and the interrupt priority 00308 AT91C_BASE_AIC->AIC_SVR[ AT91C_ID_CAN ] = (unsigned int)CanIsr_Wrapper; 00309 // Store the Source Mode Register 00310 AT91C_BASE_AIC->AIC_SMR[ AT91C_ID_CAN ] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 4 ; 00311 // Clear the interrupt on the interrupt controller 00312 AT91C_BASE_AIC->AIC_ICCR = mask ; 00313 00314 // AT91C_BASE_AIC->CAN_IER = 0; // AT91C_ADC_DRDY; 00315 00316 AT91C_BASE_AIC->AIC_IECR = mask; 00317 */ 00318 00319 return CONTROLLER_OK; 00320 } 00321 00322 #ifdef OSC 00323 00324 #include "osc.h" 00325 #include "string.h" 00326 #include "stdio.h" 00327 00328 // Need a list of property names 00329 // MUST end in zero 00330 static char* CanOsc_Name = "can"; 00331 static char* CanOsc_PropertyNames[] = { "active", "value", 0 }; // must have a trailing 0 00332 00333 int CanOsc_PropertySet( int property, int value ); 00334 int CanOsc_PropertyGet( int property ); 00335 00336 // Returns the name of the subsystem 00337 const char* CanOsc_GetName( ) 00338 { 00339 return CanOsc_Name; 00340 } 00341 00342 // Now getting a message. This is actually a part message, with the first 00343 // part (the subsystem) already parsed off. 00344 int CanOsc_ReceiveMessage( int channel, char* message, int length ) 00345 { 00346 int status = Osc_IntReceiverHelper( channel, message, length, 00347 CanOsc_Name, 00348 CanOsc_PropertySet, CanOsc_PropertyGet, 00349 CanOsc_PropertyNames ); 00350 00351 // the can system is complex it will need another kind of helper - one that 00352 // can handle 00353 // /can/active 1 as well as 00354 // /can/0/id 21213 00355 // also the can getters and setters will need to be able to handle complex data 00356 00357 if ( status != CONTROLLER_OK ) 00358 return Osc_SendError( channel, CanOsc_Name, status ); 00359 return CONTROLLER_OK; 00360 } 00361 00362 // Set the index LED, property with the value 00363 int CanOsc_PropertySet( int property, int value ) 00364 { 00365 switch ( property ) 00366 { 00367 case 0: 00368 Can_SetActive( value ); 00369 break; 00370 } 00371 return CONTROLLER_OK; 00372 } 00373 00374 // Get the property 00375 int CanOsc_PropertyGet( int property ) 00376 { 00377 int value = 0; 00378 switch ( property ) 00379 { 00380 case 0: 00381 value = Can_GetActive( ); 00382 break; 00383 } 00384 00385 return value; 00386 } 00387 00388 #endif // OSC 00389 00390 00391
The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.