1 // **************************************************************************
    2 //   Custom DPA Handler code example - Using SPI MCU peripheral by OS calls *
    3 // **************************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-SPI.c,v $
    7 // Version: $Revision: 1.28 $
    8 // Date:    $Date: 2021/04/26 15:13:50 $
    9 //
   10 // Revision history:
   11 //   2017/03/13  Release for DPA 3.00
   12 //   2015/08/05  Release for DPA 2.20
   13 //   2014/10/31  Release for DPA 2.10
   14 //   2014/04/30  Release for DPA 2.00
   15 //
   16 // **************************************************************************
   17 
   18 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   19 
   20 // Default IQRF include (modify the path according to your setup)
   21 #include "IQRF.h"
   22 
   23 // Default DPA header (modify the path according to your setup)
   24 #include "DPA.h"
   25 // Default Custom DPA Handler header (modify the path according to your setup)
   26 #include "DPAcustomHandler.h"
   27 
   28 // This example shows how to connect custom peripheral with MCU SPI HW peripheral controlled by IQRF OS
   29 
   30 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   31 //############################################################################################
   32 bit CustomDpaHandler()
   33 //############################################################################################
   34 {
   35   // Handler presence mark
   36   clrwdt();
   37 
   38   // Place for local static variables used only within CustomDpaHandler() among more events
   39   // example: static bit interruptOccured;
   40 
   41   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   42   switch ( GetDpaEvent() )
   43   {
   44     // -------------------------------------------------
   45     case DpaEvent_Interrupt:
   46       // Do an extra quick background interrupt work
   47       // ! The time spent handling this event is critical.If there is no interrupt to handle return immediately otherwise keep the code as fast as possible.
   48       // ! Make sure the event is the 1st case in the main switch statement at the handler routine.This ensures that the event is handled as the 1st one.
   49       // ! It is desirable that this event is handled with immediate return even if it is not used by the custom handler because the Interrupt event is raised on every MCU interrupt and the “empty” return handler ensures the shortest possible interrupt routine response time.
   50       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   51       // ! Make sure race condition does not occur when accessing those variables at other places.
   52       // ! Make sure( inspect.lst file generated by C compiler ) compiler does not create any hidden temporary local variable( occurs when using division, multiplication or bit shifts ) at the event handler code.The name of such variable is usually Cnumbercnt.
   53       // ! Do not call any OS functions except setINDFx().
   54       // ! Do not use any OS variables especially for writing access.
   55       // ! All above rules apply also to any other function being called from the event handler code, although calling any function from Interrupt event is not recommended because of additional MCU stack usage.
   56 
   57 DpaHandleReturnTRUE:
   58       return TRUE;
   59 
   60       // -------------------------------------------------
   61     case DpaEvent_Idle:
   62       // Do a quick background work when RF packet is not received
   63 
   64       // Is there anything at SPI received?
   65       if ( !getStatusSPI() && _SPIRX )
   66       {
   67         if ( _SPICRCok )
   68         {
   69           stopSPI();
   70 
   71           // PeripheralRam[0] stores length of received data
   72           PeripheralRam[0] = SPIpacketLength;
   73 
   74           // Limit to max. length of Peripheral RAM
   75           if ( PeripheralRam[0] > sizeof( PeripheralRam ) - 1 )
   76             PeripheralRam[0] = sizeof( PeripheralRam ) - 1;
   77 
   78           // Store data to PeripheralRam[1...] 
   79           copyMemoryBlock( bufferCOM, PeripheralRam + 1, PeripheralRam[0] );
   80 
   81           // Now data can be read by
   82           // 1. reading from Peripheral RAM
   83           // 2. by user peripheral _Pnum=PNUM_USER and _PCMD=1
   84         }
   85 
   86         startSPI( 0 );
   87       }
   88       break;
   89 
   90       // -------------------------------------------------
   91     case DpaEvent_Reset:
   92     {
   93       // Called after module is reset
   94       //goto DpaHandleReturnTRUE; // return TRUE only if you handle node bonding/unbonding
   95       static onlyOnce;
   96 
   97       if ( !onlyOnce )
   98       {
   99         onlyOnce = TRUE;
  100 
  101         // Enable SPI after reset
  102         enableSPI();
  103         bufferCOM[0] = 'R';
  104         bufferCOM[1] = 'e';
  105         bufferCOM[2] = 's';
  106         bufferCOM[3] = 'e';
  107         bufferCOM[4] = 't';
  108         startSPI( 5 );
  109       }
  110       break;
  111     }
  112 
  113     // -------------------------------------------------
  114     case DpaEvent_Init:
  115       // Do a one time initialization before main loop starts
  116 
  117       PeripheralRam[0] = 0;
  118       // SPI stays enabled after reset event
  119       bufferCOM[0] = 'I';
  120       bufferCOM[1] = 'n';
  121       bufferCOM[2] = 'i';
  122       bufferCOM[3] = 't';
  123       startSPI( 4 );
  124       break;
  125 
  126       // -------------------------------------------------
  127     case DpaEvent_DpaRequest:
  128       // Called to interpret DPA request for peripherals
  129       // -------------------------------------------------
  130       // Peripheral enumeration
  131       if ( IsDpaEnumPeripheralsRequest() )
  132       {
  133         _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1;
  134         FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 );
  135         _DpaMessage.EnumPeripheralsAnswer.HWPID = 0x000F;
  136         _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0;
  137 
  138         goto DpaHandleReturnTRUE;
  139       }
  140       // -------------------------------------------------
  141       // Get information about peripheral
  142       else if ( IsDpaPeripheralInfoRequest() )
  143       {
  144         if ( _PNUM == PNUM_USER + 0 )
  145         {
  146           _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA;
  147           _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE;
  148           _DpaMessage.PeripheralInfoAnswer.Par1 = 0;
  149           _DpaMessage.PeripheralInfoAnswer.Par2 = 0;
  150           goto DpaHandleReturnTRUE;
  151         }
  152 
  153         break;
  154       }
  155       // -------------------------------------------------
  156       else
  157       {
  158         // Handle peripheral command
  159         if ( _PNUM == PNUM_USER + 0 )
  160         {
  161           switch ( _PCMD )
  162           {
  163             case 0:
  164               // Write one byte from PData to SPI
  165               if ( _DpaDataLength != 1 )
  166                 goto Error_FAIL;
  167 
  168               bufferCOM[0] = 'C';
  169               bufferCOM[1] = 'm';
  170               bufferCOM[2] = 'd';
  171               bufferCOM[3] = '=';
  172               bufferCOM[4] = _DpaMessage.Request.PData[0];
  173               // SPI is enabled from reset event
  174               startSPI( 5 );
  175               _DpaDataLength = 0;
  176               goto DpaHandleReturnTRUE;
  177 
  178             case 1:
  179               if ( _DpaDataLength != 0 )
  180                 goto Error_FAIL;
  181 
  182               // Read data originally read from SPI
  183               copyMemoryBlock( PeripheralRam + 1, _DpaMessage.Response.PData, _DpaDataLength = PeripheralRam[0] );
  184               goto DpaHandleReturnTRUE;
  185 
  186             default:;
  187               // For simplicity reasons we report only one type of error
  188 Error_FAIL:
  189               DpaApiReturnPeripheralError( ERROR_FAIL );
  190           }
  191         }
  192       }
  193 
  194       break;
  195   }
  196 
  197 DpaHandleReturnFALSE:
  198   return FALSE;
  199 }
  200 //############################################################################################
  201 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 
  202 #include "DPAcustomHandler.h"
  203 //############################################################################################