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 DrvI2cMaster* DrvI2cMaster::sInstances[2];
10 
11 DrvI2cMaster::DrvI2cMaster() :
12  mSema(1, 0) {
13 }
14 
15 void DrvI2cMaster::init(DrvTypes::I2C port) {
16  IRQn_Type irqTypeEv;
17  IRQn_Type irqTypeEr;
18 
19  switch (port) {
20  case DrvTypes::DRV_I2C1:
21  sInstances[0] = this;
22  mI2c = I2C1;
23  irqTypeEv = I2C1_EV_IRQn;
24  irqTypeEr = I2C1_ER_IRQn;
25  break;
26  case DrvTypes::DRV_I2C2:
27  sInstances[1] = this;
28  mI2c = I2C2;
29  irqTypeEv = I2C2_EV_IRQn;
30  irqTypeEr = I2C2_ER_IRQn;
31  break;
32  default:
33  return;
34  }
35  mI2c->CR1 = 0;
36  mI2c->TIMINGR = 0x00902025;
37 
38  NVIC ->IP[irqTypeEv] = RTOS_INT_PRI;
39  NVIC ->IP[irqTypeEr] = RTOS_INT_PRI;
40  NVIC_EnableIRQ(irqTypeEv);
41  NVIC_EnableIRQ(irqTypeEr);
42 }
43 
44 void DrvI2cMaster::setSlaveAddr(uint16_t slaveAddr) {
45  mSlaveAddr = slaveAddr;
46 }
47 
48 bool DrvI2cMaster::readWrite(const uint8_t* src, int srcLen, uint8_t* dst, int dstLen) {
49  mSrc = src;
50  mSrcLen = srcLen;
51  mDst = dst;
52  mDstLen = dstLen;
53  mResult = false;
54  mI2c->CR1 = I2C_CR1_TCIE | I2C_CR1_ERRIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_NACKIE | I2C_CR1_PE;
55  if (srcLen > 0) {
56  mI2c->CR2 = I2C_CR2_START | ((srcLen << 16) & I2C_CR2_NBYTES) | (mSlaveAddr & I2C_CR2_SADD);
57  }
58  else if (dstLen > 0) {
59  mI2c->CR2 = I2C_CR2_START | I2C_CR2_RD_WRN | ((dstLen << 16) & I2C_CR2_NBYTES) | (mSlaveAddr & I2C_CR2_SADD);
60  }
61  else {
62  mI2c->CR1 = 0;
63  return true;
64  }
65  if (!mSema.take(Rtos::convertMsToTick(1000))) {
66  mI2c->CR1 = 0;
67  return false;
68  }
69  mI2c->CR1 = 0;
70  return mResult;
71 }
72 
73 void DrvI2cMaster::onEvent() {
74  uint16_t status = mI2c->ISR;
75 
76  if (status & I2C_ISR_TXE) { // Transmit data register empty
77  Rtos::nop();
78  }
79  if (status & I2C_ISR_TXIS) { // Transmit interrupt status
80  mI2c->TXDR = *mSrc++;
81  mSrcLen--;
82  }
83  if (status & I2C_ISR_RXNE) { // Receive data register not empty
84  if (mDstLen > 0) {
85  *mDst++ = mI2c->RXDR;
86  mDstLen--;
87  }
88  }
89  if (status & I2C_ISR_ADDR) { // Address matched (slave mode)
90  Rtos::nop();
91  }
92  if (status & I2C_ISR_NACKF) { // NACK received flag
93  Rtos::nop();
94  }
95  if (status & I2C_ISR_STOPF) { // STOP detection flag
96  Rtos::nop();
97  }
98  if (status & I2C_ISR_TC) { // Transfer complete (master mode)
99  if (mDstLen > 0) {
100  mI2c->CR2 = I2C_CR2_START | I2C_CR2_RD_WRN | ((mDstLen << 16) & I2C_CR2_NBYTES) | (mSlaveAddr & I2C_CR2_SADD);
101  }
102  else {
103  mI2c->CR2 = I2C_CR2_STOP;
104  mResult = true;
105  mSema.giveFromInt();
106  }
107  }
108  if (status & I2C_ISR_TCR) { // Transfer complete reload
109  Rtos::nop();
110  }
111  if (status & I2C_ISR_BUSY) { // Bus busy
112  Rtos::nop();
113  }
114  if (status & I2C_ISR_DIR) { // Transfer direction (slave mode)
115  Rtos::nop();
116  }
117  if (status & I2C_ISR_ADDCODE) { // Address match code (slave mode)
118  Rtos::nop();
119  }
120 
121 }
122 
123 void DrvI2cMaster::onError() {
124  mI2c->CR1 = 0;
125  mSema.giveFromInt();
126  uint16_t status = mI2c->ISR;
127  if (status & I2C_ISR_BERR) { // Bus error
128  Rtos::nop();
129  }
130  if (status & I2C_ISR_ARLO) { // Arbitration lost
131  Rtos::nop();
132  }
133  if (status & I2C_ISR_OVR) { // Overrun/Underrun
134  Rtos::nop();
135  }
136  if (status & I2C_ISR_TIMEOUT) { // Timeout or Tlow detection flag
137  Rtos::nop();
138  }
139  if (status & I2C_ISR_PECERR) { // PEC error in reception
140  Rtos::nop();
141  }
142  if (status & I2C_ISR_ALERT) { // SMBus alert
143  Rtos::nop();
144  }
145 }
146 
147 void RtosInterrupt::IRQ_I2C1_EV() {
148  DrvI2cMaster::sInstances[0]->onEvent();
149 }
150 
151 void RtosInterrupt::IRQ_I2C1_ER() {
152  DrvI2cMaster::sInstances[0]->onError();
153 }
154 
155 void RtosInterrupt::IRQ_I2C2_EV() {
156  DrvI2cMaster::sInstances[1]->onEvent();
157 }
158 
159 void RtosInterrupt::IRQ_I2C2_ER() {
160  DrvI2cMaster::sInstances[1]->onError();
161 }