- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# can.c

Go to the documentation of this file.

    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.