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