CROSS Technical Documentation User Manual and Technical Doc.
INFN Milano Bicocca
Loading...
Searching...
No Matches
I2C_0.c
Go to the documentation of this file.
1
2/// \file
3
4#include "tutti_gli_header.h"
5
6// DOCUMENTAZIONE DOXYGEN
7
8
9/*! \page I2C_0_page I2C_0
10*\brief <span style="color:red;"> <b> This is the hw for the I2C_0 fw </b> </span>
11*\tableofcontents
12
13 \b SUMMARY:
14*\arg \ref I2C_0_section
15
16
17*\section I2C_0_section User use of the I2C_0
18<hr width="75%" size="10" align="left">
19
20\n The I2C fw exploits the CMSIS functions, in particular to \b Driver_I2C.h,. Two functions are developed on purpose for each I2C,
21I2C_0 and I2C_1..
22The first is the initalization function I2C_0_Initialize(void), while the other is the function
23called from the interrupt,
24I2C_0_SignalEvent_t(uint32_t event). This last function can be exploited, or considered exploting the
25variable #evento_I2C. Its flags ar listed in \ref Table_interrupt_event.
26\n The transmission speed is set at #ARM_I2C_BUS_SPEED_STANDARD, that correspond to 100 KHz.
27
28\n
29<center>
30\anchor Table_interrupt_event \b Table \b Interrput: Flags of the mask #evento_I2C. <span style="color:red;">
31The row highlighted in red marks the bit expected after a successfully communication. </span>
32Parameter event | Bit | Description |
33:------------------------------- | :-----: | :-----------------------------------------------------------------------------------------|
34<span style="color:red;"> ARM_I2C_EVENT_TRANSFER_DONE </span> | <span style="color:red;"> 1UL << 0 </span> | <span style="color:red;"> Occurs after Master/Slave Transmit/Receive operation has finished. </span> |
35ARM_I2C_EVENT_TRANSFER_INCOMPLETE | 1UL << 1 | Occurs together with ARM_I2C_EVENT_TRANSFER_DONE when <br /> less data is transferred then requested. |
36ARM_I2C_EVENT_SLAVE_TRANSMIT | 1UL << 2 | Occurs when addressed as Slave Transmitter and ARM_I2C_SlaveTransmit has not been started.|
37ARM_I2C_EVENT_SLAVE_RECEIVE | 1UL << 3 | Occurs when addressed as Slave Receiver and ARM_I2C_SlaveReceive has not been started. |
38ARM_I2C_EVENT_ADDRESS_NACK | 1UL << 4 | Occurs in master mode when address is not acknowledged from slave. |
39ARM_I2C_EVENT_GENERAL_CALL | 1UL << 5 | Indicates General Call in slave mode together with ARM_I2C_EVENT_TRANSFER_DONE, <br /> ARM_I2C_EVENT_SLAVE_TRANSMIT and ARM_I2C_EVENT_SLAVE_RECEIVE. |
40ARM_I2C_EVENT_ARBITRATION_LOST | 1UL << 6 | Occurs in master mode when arbitration is lost. |
41ARM_I2C_EVENT_BUS_ERROR | 1UL << 7 | Occurs when bus error is detected. |
42ARM_I2C_EVENT_BUS_CLEAR | 1UL << 8 | Occurs after ARM_I2C_BUS_CLEAR Control operation has finished. |
43</center>
44
45\n Let's consider the way the I2C can transmit and receive data exploiting the CMSIS functions. There is a structure
46of functions committed to manage the I22C communication. They are these:
47
48<span style="color:orange;"> <I>
49\code {.c}
50typedef struct _ARM_DRIVER_I2C {
51 ARM_DRIVER_VERSION (*GetVersion) (void);
52 ARM_I2C_CAPABILITIES (*GetCapabilities)(void);
53 int32_t (*Initialize) (ARM_I2C_SignalEvent_t cb_event);
54 int32_t (*Uninitialize) (void);
55 int32_t (*PowerControl) (ARM_POWER_STATE state);
56 int32_t (*MasterTransmit) (uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending);
57 int32_t (*MasterReceive) (uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending);
58 int32_t (*SlaveTransmit) ( const uint8_t *data, uint32_t num);
59 int32_t (*SlaveReceive) ( uint8_t *data, uint32_t num);
60 int32_t (*GetDataCount) (void);
61 int32_t (*Control) (uint32_t control, uint32_t arg);
62 ARM_I2C_STATUS (*GetStatus) (void);
63} const ARM_DRIVER_I2C;
64\endcode
65</I> </span>
66
67\n I2C_0 and I2C_1 have the propoer set of functions. Here we consider that committed to I2C_0:
68<span style="color:orange;"> <I>
69\code {.c}
70// I2C0 Driver Control Block
71ARM_DRIVER_I2C Driver_I2C0 = {
72 I2C_GetVersion,
73 I2C_GetCapabilities,
74 I2C0_Initialize,
75 I2C0_Uninitialize,
76 I2C0_PowerControl,
77 I2C0_MasterTransmit, //This is the function we use most of the time
78 I2C0_MasterReceive, //We use this function, too, when we need to check, or read back some parameters
79 I2C0_SlaveTransmit,
80 I2C0_SlaveReceive,
81 I2C0_GetDataCount,
82 I2C0_Control,
83 I2C0_GetStatus //This function is exploited to poll the bus
84};
85\endcode
86</I> </span>
87
88\n We mainly use the \b I2C0_MasterTransmit, for transmission, \b I2C0_MasterReceive, for reception, and \b I2C0_GetStatus for polling.
89In particular from \b I2C0_GetStatus we get a struct with the following meaning:
90
91\n
92<center>
93\anchor Table_global_status_struct \b Table \b Global \b Status: Retruned struct from \b I2C0_GetStatus.
94<span style="color:red;"> The row highlighted in red marks the field exploited in polling operation. </span>
95Data | Fields |
96:-------------------------- | :--------------------------------------------------------------------|
97<span style="color:red;"> uint32_t busy: 1 </span> |<span style="color:red;"> Busy flag. </span>
98uint32_t mode: 1 | Mode: 0=Slave, 1=Master.
99uint32_t direction: 1 | Direction: 0=Transmitter, 1=Receiver.
100uint32_t general_call: 1 | General Call indication (cleared on start of next Slave operation)
101uint32_t arbitration_lost: 1 | Master lost arbitration (cleared on start of next Master operation)
102uint32_t bus_error: 1 | Bus error detected (cleared on start of next Master/Slave operation)
103uint32_t reserved: 26 | |
104</center>
105
106\n
107\remark The suggestion is to create a pointer to the structure that identifies the I2C to use. As an instance:
108<span style="color:orange;"> <I>
109\code {.c}
110extern ARM_DRIVER_I2C Driver_I2C0; // Viene inclusa la Periferica I2C0
111ARM_DRIVER_I2C * I2C_mux; //Define a pointer to structure of functions
112
113I2C_mux = &Driver_I2C0; //Assign the pointer to the I2C to be selected, I2C_0 in this case
114
115I2C_mux->MasterTransmit( I2C_mux_address_mainboard, &canale_da_abilitare, 1,false); //Example of the use of 1 byte transmission
116
117while( I2C_mux->GetStatus().busy); // Wait transmission completes, if we need to wait
118
119I2C_mux->MasterReceive( I2C_mux_address_mainboard, &tappo, 1,false); //Example of the receiving of one byte
120
121while( I2C_mux->GetStatus().busy); // Wait reception completes, if we need to wait
122\endcode
123</I> </span>
124
125\n
126\n
127\sa That shown above is an extraction of the documentation from CMSIS drivers.
128For a complete reference to the I2C driver from CMSIS see the webs at Keil or ARM (in case of failure of either):
129- <a href="https://arm-software.github.io/CMSIS_5/Driver/html/group__i2c__interface__gr.html" target=_blank><b>CMSIS doc for I2C from ARM</b></a>,
130- <a href="https://www.keil.com/pack/doc/CMSIS/Driver/html/group__i2c__interface__gr.html" target=_blank><b>CMSIS doc for I2C from KEIL</b></a>
131
132\n The codes for I2C_0 is at:
133- \ref I2C_0.c
134- \ref I2C_0.h
135
136<!-- pappa -->
137*/
138
139/*! <!-- La funzione driver I2C0 -->
140<!-- ************************************************************************************************ -->
141
142\fn I2C0_Initialize(ARM_I2C_SignalEvent_t cb_event)
143
144\param[in] cb_event Pointer to \b ARM_I2C_SignalEvent()
145\return #Status_Error_Codes_I2C
146
147\brief The function \b ARM_I2C_Initialize() initializes the I2C interface. It is called when the middleware component
148starts operation.
149
150The function performs the following operations:
151
152Initializes and the I/O resources for the I2C interface.
153Registers the \b ARM_I2C_SignalEvent() callback function.
154The parameter cb_event is a pointer to the \b ARM_I2C_SignalEvent() callback function.
155Use a NULL pointer when no callback events are required.
156
157Can be called multiple times. If the peripheral is already initialized the function performs no
158operation and returns with \b ARM_DRIVER_OK. Refer to Function Call Sequence for more information.
159
160<!-- ************************************************************************************************ -->
161
162\fn I2C0_Uninitialize(void)
163
164\return #Status_Error_Codes_I2C
165
166\brief De-initialize I2C Interface.
167The function \b ARM_I2C_Uninitialize() releases the I/O resources of I2C interface.
168
169It is called when the middleware component stops operation and releases the I/O resources used by the I2C interface.
170Refer to Function Call Sequence for more information.
171
172\fn I2C0_PowerControl(ARM_POWER_STATE state)
173
174\param[in] state Power state
175\return #Status_Error_Codes_I2C
176\brief The function \b ARM_I2C_PowerControl() operates the power modes of the I2C interface.
177
178The parameter state can have the following values:
179- \b ARM_POWER_FULL : set-up peripheral for data transfers, enable interrupts (NVIC) and optionally DMA. Can be called multiple times.
180If the peripheral is already in this mode, then the function performs no operation and returns with \b ARM_DRIVER_OK.
181- \b ARM_POWER_LOW : may use power saving. Returns \b ARM_DRIVER_ERROR_UNSUPPORTED when not implemented.
182- \b ARM_POWER_OFF : terminates any pending data transfers, disables peripheral, disables related interrupts and DMA.
183
184<!-- ************************************************************************************************ -->
185
186\fn I2C0_MasterTransmit(uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending)
187
188\param[in] addr Slave address (7-bit or 10-bit)
189\param[in] data Pointer to buffer with data to transmit to I2C Slave
190\param[in] num Number of data bytes to transmit
191\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
192\return #Status_Error_Codes_I2C
193
194\brief Start transmitting data as I2C Master.
195This function ARM_I2C_MasterTransmit transmits data as Master to the selected Slave.
196
197The operation consists of:
198
199Master generates START condition
200Master addresses the Slave as Master Transmitter
201Master transmits data to the addressed Slave
202Master generates STOP condition (if xfer_pending is "false")
203The parameter addr is the address of the slave to transmit the data to. The value can be ORed with #ARM_I2C_ADDRESS_10BIT
204to identify a 10-bit address value.
205The parameter data and num specify the address of a data buffer and the number of bytes to transmit.
206Set the parameter xfer_pending to 'true' if another transfer operation follows.
207With xfer_pending set to 'false' a STOP condition is generated.
208
209The function is non-blocking and returns as soon as the driver has started the operation.
210During the operation it is not allowed to call any Master function again.
211Also the data buffer must stay allocated and the contents of data must not be modified.
212When transmit operation has finished the #ARM_I2C_EVENT_TRANSFER_DONE event is generated.
213When not all the data is transferred then the #ARM_I2C_EVENT_TRANSFER_INCOMPLETE flag is set at the same time.
214
215Number of data bytes transmitted and acknowledged is returned by the function \b ARM_I2C_GetDataCount
216during and after the operation has finished.
217
218The operation is aborted in the following cases (#ARM_I2C_EVENT_TRANSFER_DONE event is generated together with):
219
220selected slave has not acknowledged the address: #ARM_I2C_EVENT_ADDRESS_NACK event
221arbitration has been lost: #ARM_I2C_EVENT_ARBITRATION_LOST event
222bus error has been detected: #ARM_I2C_EVENT_BUS_ERROR event
223Status can be monitored by calling the \b ARM_I2C_GetStatus and checking the flags.
224
225Transmit operation can be aborted also by calling \b ARM_I2C_Control with the parameter control #ARM_I2C_ABORT_TRANSFER.
226
227<!-- ************************************************************************************************ -->
228
229\fn I2C0_MasterReceive(uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending)
230
231\param[in] addr Slave address (7-bit or 10-bit)
232\param[out] data Pointer to buffer for data to receive from I2C Slave
233\param[in] num Number of data bytes to receive
234\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
235\return #Status_Error_Codes_I2C
236\brief This function ARM_I2C_MasterReceive is used to receive data as Master from the selected Slave.
237
238The operation consists of:
239
240Master generates START condition
241Master addresses the Slave as Master Receiver
242Master receives data from the addressed Slave
243Master generates STOP condition (if xfer_pending is "false")
244The parameter addr is the address of the slave to receive the data from. The value can be ORed with #ARM_I2C_ADDRESS_10BIT to identify a 10-bit address value.
245The parameter data and num specify the address of a data buffer and the number of bytes to receive.
246Set the parameter xfer_pending to 'true' if another transfer operation follows. With xfer_pending set to 'false' a STOP condition is generated.
247
248The function is non-blocking and returns as soon as the driver has started the operation. During the operation it is not allowed to call any Master function again. Also the data buffer must stay allocated.
249When receive operation has finished the #ARM_I2C_EVENT_TRANSFER_DONE event is generated. When not all the data is transferred
250then the #ARM_I2C_EVENT_TRANSFER_INCOMPLETE flag is set at the same time.
251
252Number of data bytes received is returned by the function #ARM_I2C_GetDataCount during and after the operation has finished.
253
254The operation is aborted in the following cases (#ARM_I2C_EVENT_TRANSFER_DONE event is generated together with):
255
256selected slave has not acknowledged the address: #ARM_I2C_EVENT_ADDRESS_NACK event
257arbitration has been lost: #ARM_I2C_EVENT_ARBITRATION_LOST event
258bus error has been detected: #ARM_I2C_EVENT_BUS_ERROR event
259Status can be monitored by calling the ARM_I2C_GetStatus and checking the flags.
260
261Receive operation can be aborted also by calling #ARM_I2C_Control with the parameter control = #ARM_I2C_ABORT_TRANSFER.
262
263<!-- ************************************************************************************************ -->
264
265\fn I2C0_GetStatus(void)
266
267\return I2C status \ref Table_global_status_struct "ARM_I2C_STATUS"
268\brief Get I2C status.
269The function I2C0_GetStatus() returns the current I2C interface status.
270*/
271
272// <!-- ************************************************************************************************ -->
273// <!-- Definizione solo per creare un commento -->
274/*! \brief
275Macros
276- \b ARM_DRIVER_OK 0
277 Operation succeeded.
278- \b ARM_DRIVER_ERROR -1
279 Unspecified error.
280- \b ARM_DRIVER_ERROR_BUSY -2
281 Driver is busy.
282- \b ARM_DRIVER_ERROR_TIMEOUT -3
283 Timeout occurred.
284- \b ARM_DRIVER_ERROR_UNSUPPORTED -4
285 Operation not supported.
286- \b ARM_DRIVER_ERROR_PARAMETER -5
287 Parameter error.
288- \b ARM_DRIVER_ERROR_SPECIFIC -6
289 Start of driver specific errors.
290
291Description
292Negative return values of functions indicate errors occurred during execution.
293
294Most functions return a status information using negative return values.
295The following list provides the status error codes that are common in all drivers.
296The drivers may return also status error codes that are specific to the peripheral.
297*/
298int8_t Status_Error_Codes_I2C; //Creata solo per generare un commento
299
300uint32_t evento_I2C; ///< This is the variable which resembles the flags from the communication
301extern ARM_DRIVER_I2C Driver_I2C0; // Viene inclusa la Periferica I2C0
302ARM_DRIVER_I2C * I2CBdrv = &Driver_I2C0; // Viene creato un puntatore a Driver_I2C0
303
304/*****************************************************************************
305 Callback della Periferica I2C_B
306 ******************************************************************************/
307
308/*! \brief The I2C_0 interrupt function
309
310*\return No Parameters
311 \showrefby
312*\snippet{lineno} I2C_0.c fun_I2C_0_SignalEvent_t
313 */
314//! <!-- [fun_I2C_0_SignalEvent_t] -->
315void I2C_0_SignalEvent_t (uint32_t event)
316{
317 evento_I2C=event;
318 if(event==ARM_I2C_EVENT_TRANSFER_DONE) // Ricezione e trasmissione finita sia del master che dello slave
319 {
320 __NOP();
322 }
323 if( event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE)
324 {
326 }
327 if(event==ARM_I2C_EVENT_SLAVE_TRANSMIT)
328 {
329 __NOP();
331 }
332 if(event==ARM_I2C_EVENT_SLAVE_RECEIVE)
333 {
334 __NOP();
336 }
337 if (event & ARM_I2C_EVENT_ADDRESS_NACK){
339 }
340 if (event & ARM_I2C_EVENT_ARBITRATION_LOST){
342 }
343 if( event & ARM_I2C_EVENT_BUS_ERROR){
345 }
346 if( event & ARM_I2C_EVENT_BUS_CLEAR){
348 }
349}
350//! <!-- [fun_I2C_0_SignalEvent_t] -->
351
352
353
354/*****************************************************************************
355 I2C INIZIALIZE
356 *****************************************************************************/
357
358
359 /*! \brief The I2C_0 initialize
360
361 *\return No Parameters
362 \showrefby
363\showrefs
364\callgraph
365 *\snippet{lineno} I2C_0.c fun_I2C_0_Initialize
366 */
367
368//! <!-- [fun_I2C_0_Initialize] -->
369void I2C_0_Initialize (void) {
370
371 I2CBdrv->Initialize (I2C_0_SignalEvent_t); // Viene inizializzata la periferica I2C
372 I2CBdrv->PowerControl (ARM_POWER_FULL); // Viene accesa la periferica
373 I2CBdrv->Control (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_STANDARD); // Viene impostata la velocit\'a del Bus
374 I2CBdrv->Control (ARM_I2C_BUS_CLEAR, 0);
375}
376//! <!-- [fun_I2C_0_Initialize] -->
377
volatile uint32_t Error_bad_operation
exploited to mark the errors
void I2C_0_SignalEvent_t(uint32_t event)
The I2C_0 interrupt function.
Definition: I2C_0.c:315
uint32_t evento_I2C
This is the variable which resembles the flags from the communication.
Definition: I2C_0.c:300
int8_t Status_Error_Codes_I2C
Macros.
Definition: I2C_0.c:298
void I2C_0_Initialize(void)
The I2C_0 initialize.
Definition: I2C_0.c:369