1 /******************************************************************************
2 * Filename: i2c.c
3 *
4 * Description: Driver for the I2C module
5 *
6 * Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1) Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2) Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36
37 #include "i2c.h"
38
39 //*****************************************************************************
40 //
41 // Handle support for DriverLib in ROM:
42 // This section will undo prototype renaming made in the header file
43 //
44 //*****************************************************************************
45 #if !defined(DOXYGEN)
46 #undef I2CMasterInitExpClk
47 #define I2CMasterInitExpClk NOROM_I2CMasterInitExpClk
48 #undef I2CMasterErr
49 #define I2CMasterErr NOROM_I2CMasterErr
50 #undef I2CIntRegister
51 #define I2CIntRegister NOROM_I2CIntRegister
52 #undef I2CIntUnregister
53 #define I2CIntUnregister NOROM_I2CIntUnregister
54 #endif
55
56 //*****************************************************************************
57 //
58 // Initializes the I2C Master block
59 //
60 //*****************************************************************************
61 void
I2CMasterInitExpClk(uint32_t ui32Base,uint32_t ui32I2CClk,bool bFast)62 I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
63 bool bFast)
64 {
65 uint32_t ui32SCLFreq;
66 uint32_t ui32TPR;
67
68 // Check the arguments.
69 ASSERT(I2CBaseValid(ui32Base));
70
71 // Must enable the device before doing anything else.
72 I2CMasterEnable(ui32Base);
73
74 // Get the desired SCL speed.
75 if(bFast == true)
76 {
77 ui32SCLFreq = 400000;
78 }
79 else
80 {
81 ui32SCLFreq = 100000;
82 }
83
84 // Compute the clock divider that achieves the fastest speed less than or
85 // equal to the desired speed. The numerator is biased to favor a larger
86 // clock divider so that the resulting clock is always less than or equal
87 // to the desired clock, never greater.
88 ui32TPR = ((ui32I2CClk + (2 * 10 * ui32SCLFreq) - 1) / (2 * 10 * ui32SCLFreq)) - 1;
89 HWREG(ui32Base + I2C_O_MTPR) = ui32TPR;
90 }
91
92 //*****************************************************************************
93 //
94 // Gets the error status of the I2C Master module
95 //
96 //*****************************************************************************
97 uint32_t
I2CMasterErr(uint32_t ui32Base)98 I2CMasterErr(uint32_t ui32Base)
99 {
100 uint32_t ui32Err;
101
102 // Check the arguments.
103 ASSERT(I2CBaseValid(ui32Base));
104
105 // Get the raw error state.
106 ui32Err = HWREG(ui32Base + I2C_O_MSTAT);
107
108 // If the I2C master is busy, then all the other status bits are invalid,
109 // and there is no error to report.
110 if(ui32Err & I2C_MSTAT_BUSY)
111 {
112 return(I2C_MASTER_ERR_NONE);
113 }
114
115 // Check for errors.
116 if(ui32Err & (I2C_MSTAT_ERR | I2C_MSTAT_ARBLST))
117 {
118 return(ui32Err & (I2C_MSTAT_ARBLST | I2C_MSTAT_DATACK_N | I2C_MSTAT_ADRACK_N));
119 }
120 else
121 {
122 return(I2C_MASTER_ERR_NONE);
123 }
124 }
125
126 //*****************************************************************************
127 //
128 // Registers an interrupt handler for the I2C module
129 //
130 //*****************************************************************************
131 void
I2CIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))132 I2CIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
133 {
134 uint32_t ui32Int;
135
136 // Check the arguments.
137 ASSERT(I2CBaseValid(ui32Base));
138
139 // Get the interrupt number.
140 ui32Int = INT_I2C_IRQ;
141
142 // Register the interrupt handler.
143 IntRegister(ui32Int, pfnHandler);
144
145 // Enable the I2C interrupt.
146 IntEnable(ui32Int);
147 }
148
149 //*****************************************************************************
150 //
151 // Unregisters an interrupt handler for the I2C module
152 //
153 //*****************************************************************************
154 void
I2CIntUnregister(uint32_t ui32Base)155 I2CIntUnregister(uint32_t ui32Base)
156 {
157 uint32_t ui32Int;
158
159 // Check the arguments.
160 ASSERT(I2CBaseValid(ui32Base));
161
162 // Get the interrupt number.
163 ui32Int = INT_I2C_IRQ;
164
165 // Disable the interrupt.
166 IntDisable(ui32Int);
167
168 // Unregister the interrupt handler.
169 IntUnregister(ui32Int);
170 }
171