I2CRTOS Driver by Helmut Schmücker. Removed included mbed-rtos library to prevent multiple definition. Make sure to include mbed-rtos library in your program!

Fork of I2cRtosDriver by Helmut Schmücker

Committer:
humlet
Date:
Sun May 19 11:21:16 2013 +0000
Revision:
14:352609d395c1
Parent:
13:530968937ccb
almost beta?; ***refactored (removed mbed-NXP and mbed-src hacks/dependencies) ; *** bugs fixed; *** performance improved (read/write sequence now handled in ISR);

Who changed what in which revision?

UserRevisionLine numberNew contents of line
humlet 0:13c962fecb13 1 #include "I2CDriver.h"
humlet 9:65aae53a34de 2 #include "i2cRtos_api.h"
humlet 14:352609d395c1 3 //#include "rt_System.h"
humlet 0:13c962fecb13 4 #include "error.h"
humlet 0:13c962fecb13 5
humlet 1:90455d5bdd8c 6 using namespace mbed;
humlet 1:90455d5bdd8c 7 using namespace rtos;
humlet 0:13c962fecb13 8
humlet 14:352609d395c1 9 //DigitalOut I2CDriver::osci2(p7);
humlet 14:352609d395c1 10
humlet 14:352609d395c1 11 #define PREFIX i2cRtos
humlet 14:352609d395c1 12 //#define PREFIX i2c // fallback to offical busy wait i2c c-api for performance testing
humlet 13:530968937ccb 13 #define PASTER(x,y) x ## _ ## y
humlet 13:530968937ccb 14 #define EVALUATOR(x,y) PASTER(x,y)
humlet 13:530968937ccb 15 #define FUNCTION(fun) EVALUATOR(PREFIX, fun)
humlet 1:90455d5bdd8c 16
humlet 1:90455d5bdd8c 17 const PinName I2CDriver::c_sdas[] = {p9,p28};
humlet 1:90455d5bdd8c 18 const PinName I2CDriver::c_scls[] = {p10,p27};
humlet 1:90455d5bdd8c 19
humlet 1:90455d5bdd8c 20 I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
humlet 0:13c962fecb13 21
humlet 3:967dde37e712 22 I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
humlet 3:967dde37e712 23 {
humlet 14:352609d395c1 24 // ensure exclusive access for initialization
humlet 14:352609d395c1 25 static Mutex mtx;
humlet 14:352609d395c1 26 bool locked = false;
humlet 14:352609d395c1 27 if(osKernelRunning()) { // but don't try to lock if rtos kernel is not running yet. (global/static definition)
humlet 14:352609d395c1 28 mtx.lock();
humlet 14:352609d395c1 29 locked = true;
humlet 14:352609d395c1 30 }
humlet 14:352609d395c1 31
humlet 3:967dde37e712 32 // check pins and determine i2c channel
humlet 3:967dde37e712 33 int channel=0;
humlet 3:967dde37e712 34 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 3:967dde37e712 35 if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
humlet 3:967dde37e712 36 else
humlet 3:967dde37e712 37 #endif
humlet 3:967dde37e712 38 if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
humlet 9:65aae53a34de 39 else error("I2CDriver: Invalid I2C pins selected\n");
humlet 14:352609d395c1 40
humlet 14:352609d395c1 41 // initialize the selected i2c channel
humlet 9:65aae53a34de 42 if(s_channels[channel]==0) {
humlet 13:530968937ccb 43 s_channels[channel] = new I2CDriver::Channel;
humlet 13:530968937ccb 44 m_channel = s_channels[channel];
humlet 13:530968937ccb 45 m_channel->freq = 0;
humlet 13:530968937ccb 46 m_channel->slaveAdr = 0;
humlet 13:530968937ccb 47 m_channel->modeSlave = 0;
humlet 14:352609d395c1 48 m_channel->initialized=false; // defer i2c initialization util we are sure the rtos kernel is running (config() function)
humlet 8:5be85bd4c5ba 49 }
humlet 3:967dde37e712 50 m_channel = s_channels[channel];
humlet 14:352609d395c1 51 if(locked) mtx.unlock();
humlet 0:13c962fecb13 52 }
humlet 0:13c962fecb13 53
humlet 6:5b98c902a659 54 void I2CDriver::lock()
humlet 6:5b98c902a659 55 {
humlet 14:352609d395c1 56 //osci2.write(1);
humlet 6:5b98c902a659 57 // One and the same thread can lock twice, but then it needs also to unlock twice.
humlet 6:5b98c902a659 58 // exactly what we need here
humlet 6:5b98c902a659 59 m_channel->mutex.lock(osWaitForever);
humlet 14:352609d395c1 60 m_channel->callerID = osThreadGetId();
humlet 14:352609d395c1 61 m_channel->callerPrio = osThreadGetPriority(m_channel->callerID);
humlet 13:530968937ccb 62 // maximize thread prio
humlet 14:352609d395c1 63 osThreadSetPriority(m_channel->callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above
humlet 13:530968937ccb 64 // mutex code looks like that waiting threads are priority ordered
humlet 13:530968937ccb 65 // also priority inheritance seems to be provided
humlet 14:352609d395c1 66 //osci2.write(0);
humlet 6:5b98c902a659 67 }
humlet 6:5b98c902a659 68
humlet 6:5b98c902a659 69 void I2CDriver::unlock()
humlet 6:5b98c902a659 70 {
humlet 14:352609d395c1 71 //osci2.write(1);
humlet 13:530968937ccb 72 // free the mutex and restore original prio
humlet 14:352609d395c1 73 //rt_tsk_lock(); // just prevent beeing preempted after restoring prio before freeing the mutex
humlet 14:352609d395c1 74 osThreadSetPriority(m_channel->callerID, m_channel->callerPrio);
humlet 14:352609d395c1 75 m_channel->mutex.unlock();
humlet 14:352609d395c1 76 //rt_tsk_unlock();
humlet 14:352609d395c1 77 //osci2.write(0);
humlet 6:5b98c902a659 78 }
humlet 6:5b98c902a659 79
humlet 13:530968937ccb 80 void I2CDriver::config()
humlet 0:13c962fecb13 81 {
humlet 14:352609d395c1 82 //osci2.write(1);
humlet 14:352609d395c1 83 // check and initialize driver
humlet 14:352609d395c1 84 if(!m_channel->initialized) {
humlet 14:352609d395c1 85 int channel = m_channel==s_channels[0] ? 0 : 1; // ...ugly
humlet 14:352609d395c1 86 FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]);
humlet 14:352609d395c1 87 m_channel->initialized=true;
humlet 14:352609d395c1 88 }
humlet 13:530968937ccb 89 // check and update frequency
humlet 13:530968937ccb 90 if(m_freq != m_channel->freq) {
humlet 13:530968937ccb 91 m_channel->freq = m_freq;
humlet 13:530968937ccb 92 i2c_frequency(&m_channel->i2c, m_freq);
humlet 13:530968937ccb 93 }
humlet 13:530968937ccb 94 // check and update slave/master mode
humlet 13:530968937ccb 95 if(m_modeSlave != m_channel->modeSlave) {
humlet 13:530968937ccb 96 m_channel->modeSlave = m_modeSlave;
humlet 13:530968937ccb 97 i2c_slave_mode(&m_channel->i2c, m_modeSlave);
humlet 13:530968937ccb 98 }
humlet 13:530968937ccb 99 // check and update slave address
humlet 13:530968937ccb 100 if(m_modeSlave && m_slaveAdr != m_channel->slaveAdr) {
humlet 13:530968937ccb 101 m_channel->slaveAdr = m_slaveAdr;
humlet 13:530968937ccb 102 i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0);
humlet 13:530968937ccb 103 }
humlet 14:352609d395c1 104 //osci2.write(0);
humlet 0:13c962fecb13 105 }
humlet 0:13c962fecb13 106
humlet 3:967dde37e712 107 int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
humlet 1:90455d5bdd8c 108 {
humlet 13:530968937ccb 109 m_modeSlave = false;
humlet 13:530968937ccb 110 lockNconfig();
humlet 13:530968937ccb 111 int ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
humlet 13:530968937ccb 112 unlock();
humlet 13:530968937ccb 113 return ret;
humlet 1:90455d5bdd8c 114 }
humlet 3:967dde37e712 115 int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
humlet 3:967dde37e712 116 {
humlet 13:530968937ccb 117 m_modeSlave = false;
humlet 13:530968937ccb 118 lockNconfig();
humlet 13:530968937ccb 119 int ret = FUNCTION(write)(&m_channel->i2c, address,(const char*)&_register, 1, 0);
humlet 13:530968937ccb 120 if(!ret) ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
humlet 13:530968937ccb 121 unlock();
humlet 13:530968937ccb 122 return ret;
humlet 3:967dde37e712 123 }
humlet 3:967dde37e712 124 int I2CDriver::readMaster(int ack)
humlet 1:90455d5bdd8c 125 {
humlet 13:530968937ccb 126 m_modeSlave = false;
humlet 13:530968937ccb 127 lockNconfig();
humlet 13:530968937ccb 128 int ret = i2cRtos_byte_read(&m_channel->i2c, (ack?0:1));
humlet 13:530968937ccb 129 unlock();
humlet 13:530968937ccb 130 return ret;
humlet 1:90455d5bdd8c 131 }
humlet 3:967dde37e712 132 int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
humlet 1:90455d5bdd8c 133 {
humlet 13:530968937ccb 134 m_modeSlave = false;
humlet 13:530968937ccb 135 lockNconfig();
humlet 13:530968937ccb 136 int ret = FUNCTION(write)(&m_channel->i2c, address, data, length, (repeated?0:1));
humlet 13:530968937ccb 137 unlock();
humlet 13:530968937ccb 138 return ret;
humlet 1:90455d5bdd8c 139 }
humlet 3:967dde37e712 140 int I2CDriver::writeMaster(int data)
humlet 1:90455d5bdd8c 141 {
humlet 13:530968937ccb 142 m_modeSlave = false;
humlet 13:530968937ccb 143 lockNconfig();
humlet 13:530968937ccb 144 int ret = i2cRtos_byte_write(&m_channel->i2c, data);
humlet 13:530968937ccb 145 unlock();
humlet 13:530968937ccb 146 return ret;
humlet 0:13c962fecb13 147 }
humlet 3:967dde37e712 148 void I2CDriver::startMaster(void)
humlet 1:90455d5bdd8c 149 {
humlet 13:530968937ccb 150 m_modeSlave = false;
humlet 13:530968937ccb 151 lockNconfig();
humlet 13:530968937ccb 152 i2c_start(&m_channel->i2c);
humlet 13:530968937ccb 153 unlock();
humlet 3:967dde37e712 154 }
humlet 13:530968937ccb 155 bool I2CDriver::stopMaster(void)
humlet 3:967dde37e712 156 {
humlet 13:530968937ccb 157 m_modeSlave = false;
humlet 13:530968937ccb 158 lockNconfig();
humlet 13:530968937ccb 159 bool ret=i2cRtos_stop(&m_channel->i2c);
humlet 13:530968937ccb 160 unlock();
humlet 13:530968937ccb 161 return ret;
humlet 3:967dde37e712 162 }
humlet 3:967dde37e712 163 void I2CDriver::stopSlave(void)
humlet 3:967dde37e712 164 {
humlet 13:530968937ccb 165 m_modeSlave = true;
humlet 13:530968937ccb 166 lockNconfig();
humlet 13:530968937ccb 167 i2c_stop(&m_channel->i2c);
humlet 13:530968937ccb 168 unlock();
humlet 3:967dde37e712 169 }
humlet 3:967dde37e712 170 int I2CDriver::receiveSlave(uint32_t timeout_ms)
humlet 3:967dde37e712 171 {
humlet 13:530968937ccb 172 m_modeSlave = true;
humlet 13:530968937ccb 173 lockNconfig();
humlet 13:530968937ccb 174 int ret = i2cRtos_slave_receive(&m_channel->i2c, timeout_ms);
humlet 13:530968937ccb 175 unlock();
humlet 13:530968937ccb 176 return ret;
humlet 3:967dde37e712 177 }
humlet 3:967dde37e712 178 int I2CDriver::readSlave(char* data, int length)
humlet 3:967dde37e712 179 {
humlet 13:530968937ccb 180 m_modeSlave = true;
humlet 13:530968937ccb 181 lockNconfig();
humlet 13:530968937ccb 182 int ret = i2cRtos_slave_read(&m_channel->i2c, data, length);
humlet 13:530968937ccb 183 unlock();
humlet 13:530968937ccb 184 return ret;
humlet 3:967dde37e712 185 }
humlet 3:967dde37e712 186 int I2CDriver::readSlave(void)
humlet 3:967dde37e712 187 {
humlet 13:530968937ccb 188 m_modeSlave = true;
humlet 13:530968937ccb 189 lockNconfig();
humlet 13:530968937ccb 190 int ret = i2cRtos_byte_read(&m_channel->i2c, 0);
humlet 13:530968937ccb 191 unlock();
humlet 13:530968937ccb 192 return ret;
humlet 3:967dde37e712 193 }
humlet 3:967dde37e712 194 int I2CDriver::writeSlave(const char *data, int length)
humlet 3:967dde37e712 195 {
humlet 13:530968937ccb 196 m_modeSlave = true;
humlet 13:530968937ccb 197 lockNconfig();
humlet 13:530968937ccb 198 int ret = i2cRtos_slave_write(&m_channel->i2c, data, length);
humlet 13:530968937ccb 199 unlock();
humlet 13:530968937ccb 200 return ret;
humlet 3:967dde37e712 201 }
humlet 3:967dde37e712 202 int I2CDriver::writeSlave(int data)
humlet 3:967dde37e712 203 {
humlet 13:530968937ccb 204 m_modeSlave = true;
humlet 13:530968937ccb 205 lockNconfig();
humlet 13:530968937ccb 206 int ret = i2cRtos_byte_write(&m_channel->i2c, data);
humlet 13:530968937ccb 207 unlock();
humlet 13:530968937ccb 208 return ret;
humlet 1:90455d5bdd8c 209 }
humlet 1:90455d5bdd8c 210
humlet 1:90455d5bdd8c 211
humlet 3:967dde37e712 212
humlet 3:967dde37e712 213