embkernel
 All Classes Functions Variables Typedefs Groups Pages
DrvI2cMaster.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "DrvI2cMaster.hpp"
7 #include "RtosInclude.hpp"
8 
9 #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
10 DrvI2cMaster* DrvI2cMaster::sInstances[2];
11 #else
12 DrvI2cMaster* DrvI2cMaster::sInstances[1];
13 #endif
14 
15 DrvI2cMaster::DrvI2cMaster() :
16  mSema(1, 0) {
17 }
18 
19 void DrvI2cMaster::init(DrvTypes::I2C port, int baudrate) {
20  IRQn_Type irqTypeEv;
21  IRQn_Type irqTypeEr;
22 
23  switch (port) {
24  case DrvTypes::DRV_I2C1:
25  sInstances[0] = this;
26  mI2c = I2C1;
27  irqTypeEv = I2C1_EV_IRQn;
28  irqTypeEr = I2C1_ER_IRQn;
29  break;
30 #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
31  case DrvTypes::DRV_I2C2:
32  sInstances[1] = this;
33  mI2c = I2C2;
34  irqTypeEv = I2C2_EV_IRQn;
35  irqTypeEr = I2C2_ER_IRQn;
36  break;
37 #endif
38  default:
39  return;
40  }
41  mI2c->CR1 = 0;
42  mI2c->CR2 = I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | I2C_CR2_ITERREN | (DRV_CFG_PCLK1_FREQ / 1000000);
43  mI2c->CCR = DRV_CFG_PCLK1_FREQ / baudrate;
44 
45  NVIC ->IP[irqTypeEv] = RTOS_INT_PRI;
46  NVIC ->IP[irqTypeEr] = RTOS_INT_PRI;
47  NVIC_EnableIRQ(irqTypeEv);
48  NVIC_EnableIRQ(irqTypeEr);
49 }
50 
51 void DrvI2cMaster::setSlaveAddr(uint16_t slaveAddr) {
52  mSlaveAddr = slaveAddr;
53 }
54 
55 bool DrvI2cMaster::readWrite(const uint8_t* src, int srcLen, uint8_t* dst, int dstLen) {
56  mSrc = src;
57  mSrcLen = srcLen;
58  mDst = dst;
59  mDstLen = dstLen;
60  mI2c->CR1 = I2C_CR1_PE;
61  mI2c->CR1 |= I2C_CR1_START;
62  if (!mSema.take(Rtos::convertMsToTick(1000))) {
63  mI2c->CR1 = 0;
64  return false;
65  }
66  mI2c->CR1 = 0;
67  return mResult;
68 }
69 
70 void DrvI2cMaster::onEvent() {
71  uint16_t status = mI2c->SR1;
72 
73  if (status & I2C_SR1_SB ) {
74  //Temporary set result to true
75  mResult = true;
76  if (mSrcLen > 0) {
77  mI2c->DR = mSlaveAddr;
78  }
79  else if (mDstLen > 0) {
80  mI2c->DR = mSlaveAddr | 0x01;
81  }
82  else {
83  mI2c->CR1 |= I2C_CR1_STOP;
84  }
85  }
86  else if (status & I2C_SR1_ADDR ) {
87  if (mSrcLen-- > 0) {
88  mI2c->DR = *mSrc++;
89  }
90  else if (mDstLen > 0) {
91  if (mDstLen > 1) {
92  mI2c->CR1 |= I2C_CR1_ACK;
93  }
94  else {
95  mI2c->CR1 &= ~I2C_CR1_ACK;
96  }
97  }
98  else {
99  mI2c->CR1 |= I2C_CR1_STOP;
100  }
101  volatile uint16_t dummy = mI2c->SR2; //Used to reset the flag
102  dummy++; //For warning removal
103  }
104  else if (status & I2C_SR1_STOPF ) {
105  mSema.giveFromInt();
106  }
107  else if (status & I2C_SR1_RXNE ) {
108  if (mDstLen > 1) {
109  mI2c->CR1 |= I2C_CR1_ACK;
110  mDstLen--;
111  }
112  else if (mDstLen > 0) {
113  mI2c->CR1 &= ~I2C_CR1_ACK;
114  mDstLen--;
115  }
116  else {
117  mI2c->CR1 |= I2C_CR1_STOP;
118  }
119  *mDst++ = mI2c->DR;
120  }
121  else if (status & I2C_SR1_TXE ) {
122  if (mSrcLen-- > 0) {
123  mI2c->DR = *mSrc++;
124  }
125  else if (status & I2C_SR1_BTF ) {
126  mI2c->CR1 |= I2C_CR1_STOP;
127  }
128  }
129 }
130 
131 void DrvI2cMaster::onError() {
132 
133  uint16_t status = mI2c->SR1;
134 
135  mResult = false;
136 
137  if (status & I2C_SR1_BERR ) {
138  mI2c->SR1 |= I2C_SR1_BERR;
139  mI2c->CR1 = 0;
140  mSema.giveFromInt();
141  }
142  else if (status & I2C_SR1_ARLO ) {
143  mI2c->CR1 = 0;
144  mSema.giveFromInt();
145  }
146  else if (status & I2C_SR1_AF ) {
147  mI2c->CR1 |= I2C_CR1_STOP;
148  }
149  else if (status & I2C_SR1_OVR ) {
150  //Should never happen
151  mI2c->CR1 = 0;
152  mSema.giveFromInt();
153  }
154  else if (status & I2C_SR1_PECERR ) {
155  //Should never happen
156  mI2c->CR1 = 0;
157  mSema.giveFromInt();
158  }
159  else if (status & I2C_SR1_TIMEOUT ) {
160  mI2c->CR1 |= I2C_CR1_STOP;
161  }
162  else if (status & I2C_SR1_SMBALERT ) {
163  //Should never happen
164  mI2c->CR1 = 0;
165  mSema.giveFromInt();
166  }
167 }
168 
169 void RtosInterrupt::IRQ_I2C1_EV() {
170  DrvI2cMaster::sInstances[0]->onEvent();
171 }
172 
173 void RtosInterrupt::IRQ_I2C1_ER() {
174  DrvI2cMaster::sInstances[0]->onError();
175 }
176 
177 #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
178 void RtosInterrupt::IRQ_I2C2_EV() {
179  DrvI2cMaster::sInstances[1]->onEvent();
180 }
181 
182 void RtosInterrupt::IRQ_I2C2_ER() {
183  DrvI2cMaster::sInstances[1]->onError();
184 }
185 #endif