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
I2CDriver.cpp@1:90455d5bdd8c, 2013-04-14 (annotated)
- Committer:
- humlet
- Date:
- Sun Apr 14 06:39:04 2013 +0000
- Revision:
- 1:90455d5bdd8c
- Parent:
- 0:13c962fecb13
- Child:
- 2:514105beb343
no more smoke
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
humlet | 0:13c962fecb13 | 1 | #include "I2CDriver.h" |
humlet | 0:13c962fecb13 | 2 | #include "error.h" |
humlet | 0:13c962fecb13 | 3 | |
humlet | 1:90455d5bdd8c | 4 | using namespace mbed; |
humlet | 1:90455d5bdd8c | 5 | using namespace rtos; |
humlet | 0:13c962fecb13 | 6 | |
humlet | 1:90455d5bdd8c | 7 | #define ISR2DRV_SIG (1<<7) |
humlet | 1:90455d5bdd8c | 8 | #define DRV_USR_SIG (1<<6) |
humlet | 1:90455d5bdd8c | 9 | |
humlet | 1:90455d5bdd8c | 10 | const PinName I2CDriver::c_sdas[] = {p9,p28}; |
humlet | 1:90455d5bdd8c | 11 | const PinName I2CDriver::c_scls[] = {p10,p27}; |
humlet | 1:90455d5bdd8c | 12 | |
humlet | 1:90455d5bdd8c | 13 | I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0}; |
humlet | 0:13c962fecb13 | 14 | |
humlet | 0:13c962fecb13 | 15 | |
humlet | 0:13c962fecb13 | 16 | void I2CDriver::channel_0_ISR() |
humlet | 0:13c962fecb13 | 17 | { |
humlet | 1:90455d5bdd8c | 18 | osSignalSet( s_channels[0]->driver, ISR2DRV_SIG); |
humlet | 1:90455d5bdd8c | 19 | NVIC_DisableIRQ(I2C1_IRQn); |
humlet | 0:13c962fecb13 | 20 | } |
humlet | 0:13c962fecb13 | 21 | |
humlet | 0:13c962fecb13 | 22 | |
humlet | 0:13c962fecb13 | 23 | void I2CDriver::channel_1_ISR() |
humlet | 0:13c962fecb13 | 24 | { |
humlet | 1:90455d5bdd8c | 25 | osSignalSet( s_channels[1]->driver, ISR2DRV_SIG); |
humlet | 1:90455d5bdd8c | 26 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
humlet | 1:90455d5bdd8c | 27 | NVIC_DisableIRQ(I2C2_IRQn); |
humlet | 1:90455d5bdd8c | 28 | #elif defined(TARGET_LPC11U24) |
humlet | 1:90455d5bdd8c | 29 | NVIC_DisableIRQ(I2C_IRQn); |
humlet | 1:90455d5bdd8c | 30 | #endif |
humlet | 0:13c962fecb13 | 31 | } |
humlet | 0:13c962fecb13 | 32 | |
humlet | 0:13c962fecb13 | 33 | |
humlet | 1:90455d5bdd8c | 34 | void I2CDriver::threadFun(void const *args) |
humlet | 0:13c962fecb13 | 35 | { |
humlet | 0:13c962fecb13 | 36 | int channelIdx = (int)args; |
humlet | 0:13c962fecb13 | 37 | Channel channel; |
humlet | 0:13c962fecb13 | 38 | s_channels[channelIdx] = &channel; |
humlet | 0:13c962fecb13 | 39 | |
humlet | 0:13c962fecb13 | 40 | channel.driver = Thread::gettid(); |
humlet | 1:90455d5bdd8c | 41 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
humlet | 0:13c962fecb13 | 42 | if(channelIdx==0)NVIC_SetVector(I2C1_IRQn, (uint32_t)I2CDriver::channel_0_ISR); |
humlet | 0:13c962fecb13 | 43 | if(channelIdx==1)NVIC_SetVector(I2C2_IRQn, (uint32_t)I2CDriver::channel_1_ISR); |
humlet | 1:90455d5bdd8c | 44 | #elif defined(TARGET_LPC11U24) |
humlet | 1:90455d5bdd8c | 45 | NVIC_SetVector(I2C_IRQn, (uint32_t)I2CDriver::channel_1_ISR); |
humlet | 1:90455d5bdd8c | 46 | #endif |
humlet | 1:90455d5bdd8c | 47 | I2C i2c(c_sdas[channelIdx], c_scls[channelIdx]); |
humlet | 1:90455d5bdd8c | 48 | volatile Transfer& tr = channel.transfer; |
humlet | 0:13c962fecb13 | 49 | while(1) { |
humlet | 1:90455d5bdd8c | 50 | // wait for requests |
humlet | 1:90455d5bdd8c | 51 | osSignalWait(DRV_USR_SIG,osWaitForever); |
humlet | 1:90455d5bdd8c | 52 | // check and adapt frequency |
humlet | 1:90455d5bdd8c | 53 | if(channel.freq != tr.freq) { |
humlet | 1:90455d5bdd8c | 54 | channel.freq = tr.freq; |
humlet | 1:90455d5bdd8c | 55 | i2c.frequency(tr.freq); |
humlet | 1:90455d5bdd8c | 56 | } |
humlet | 1:90455d5bdd8c | 57 | // just doit |
humlet | 1:90455d5bdd8c | 58 | switch(tr.cmd) { |
humlet | 0:13c962fecb13 | 59 | case START: |
humlet | 0:13c962fecb13 | 60 | i2c.start(); |
humlet | 0:13c962fecb13 | 61 | break; |
humlet | 0:13c962fecb13 | 62 | case STOP: |
humlet | 0:13c962fecb13 | 63 | i2c.stop(); |
humlet | 0:13c962fecb13 | 64 | break; |
humlet | 1:90455d5bdd8c | 65 | case READ: |
humlet | 1:90455d5bdd8c | 66 | tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep); |
humlet | 1:90455d5bdd8c | 67 | break; |
humlet | 1:90455d5bdd8c | 68 | case READ_FROM_REGISTER: |
humlet | 1:90455d5bdd8c | 69 | tr.ret = i2c.write(tr.adr,(const char*)&(tr.reg), 1, true); |
humlet | 1:90455d5bdd8c | 70 | if(tr.ret)break; // error => bail out |
humlet | 1:90455d5bdd8c | 71 | tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep); |
humlet | 1:90455d5bdd8c | 72 | break; |
humlet | 1:90455d5bdd8c | 73 | case READ_BYTE: |
humlet | 1:90455d5bdd8c | 74 | tr.ret = i2c.read(tr.ack); |
humlet | 1:90455d5bdd8c | 75 | break; |
humlet | 1:90455d5bdd8c | 76 | case WRITE: |
humlet | 1:90455d5bdd8c | 77 | tr.ret = i2c.write(tr.adr, tr.wdta, tr.len, tr.rep); |
humlet | 1:90455d5bdd8c | 78 | break; |
humlet | 1:90455d5bdd8c | 79 | case WRITE_BYTE: |
humlet | 1:90455d5bdd8c | 80 | tr.ret = i2c.write(tr.ack); |
humlet | 1:90455d5bdd8c | 81 | break; |
humlet | 1:90455d5bdd8c | 82 | default: |
humlet | 1:90455d5bdd8c | 83 | error("call 911"); |
humlet | 0:13c962fecb13 | 84 | } |
humlet | 1:90455d5bdd8c | 85 | // inform the caller |
humlet | 1:90455d5bdd8c | 86 | osSignalSet( channel.transfer.caller, DRV_USR_SIG); |
humlet | 0:13c962fecb13 | 87 | } |
humlet | 0:13c962fecb13 | 88 | } |
humlet | 0:13c962fecb13 | 89 | |
humlet | 0:13c962fecb13 | 90 | |
humlet | 1:90455d5bdd8c | 91 | I2CDriver::I2CDriver(PinName sda, PinName scl):I2C(sda,scl) |
humlet | 0:13c962fecb13 | 92 | { |
humlet | 0:13c962fecb13 | 93 | // check pins and determine i2c channel |
humlet | 0:13c962fecb13 | 94 | int channel=0; |
humlet | 1:90455d5bdd8c | 95 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
humlet | 1:90455d5bdd8c | 96 | if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1 |
humlet | 1:90455d5bdd8c | 97 | else |
humlet | 1:90455d5bdd8c | 98 | #endif |
humlet | 1:90455d5bdd8c | 99 | if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C |
humlet | 1:90455d5bdd8c | 100 | else error("I2CDriver: Invalid I2C pinns selected"); |
humlet | 0:13c962fecb13 | 101 | if(s_channels[channel]==0) |
humlet | 0:13c962fecb13 | 102 | new Thread(threadFun,(void *)channel,osPriorityRealtime); |
humlet | 1:90455d5bdd8c | 103 | m_channel = s_channels[channel]; |
humlet | 0:13c962fecb13 | 104 | } |
humlet | 0:13c962fecb13 | 105 | |
humlet | 1:90455d5bdd8c | 106 | |
humlet | 1:90455d5bdd8c | 107 | void I2CDriver::sendNwait() |
humlet | 1:90455d5bdd8c | 108 | { |
humlet | 1:90455d5bdd8c | 109 | m_channel->transfer.freq = _hz; |
humlet | 1:90455d5bdd8c | 110 | m_channel->transfer.caller = Thread::gettid(); |
humlet | 1:90455d5bdd8c | 111 | osSignalSet( m_channel->driver, DRV_USR_SIG); |
humlet | 0:13c962fecb13 | 112 | osSignalWait(DRV_USR_SIG,osWaitForever); |
humlet | 0:13c962fecb13 | 113 | } |
humlet | 0:13c962fecb13 | 114 | |
humlet | 0:13c962fecb13 | 115 | |
humlet | 1:90455d5bdd8c | 116 | int I2CDriver::read(int address, char *data, int length, bool repeated) |
humlet | 1:90455d5bdd8c | 117 | { |
humlet | 0:13c962fecb13 | 118 | lock(); |
humlet | 1:90455d5bdd8c | 119 | m_channel->transfer.cmd = READ; |
humlet | 1:90455d5bdd8c | 120 | m_channel->transfer.adr = address; |
humlet | 1:90455d5bdd8c | 121 | m_channel->transfer.dta = data; |
humlet | 1:90455d5bdd8c | 122 | m_channel->transfer.len = length; |
humlet | 1:90455d5bdd8c | 123 | m_channel->transfer.rep = repeated; |
humlet | 0:13c962fecb13 | 124 | sendNwait(); |
humlet | 1:90455d5bdd8c | 125 | int ret = m_channel->transfer.ret; |
humlet | 1:90455d5bdd8c | 126 | unlock(); |
humlet | 1:90455d5bdd8c | 127 | return ret; |
humlet | 0:13c962fecb13 | 128 | } |
humlet | 0:13c962fecb13 | 129 | |
humlet | 0:13c962fecb13 | 130 | |
humlet | 1:90455d5bdd8c | 131 | int I2CDriver::read(int address, uint8_t regist, char *data, int length, bool repeated) |
humlet | 1:90455d5bdd8c | 132 | { |
humlet | 1:90455d5bdd8c | 133 | lock(); |
humlet | 1:90455d5bdd8c | 134 | m_channel->transfer.cmd = READ_FROM_REGISTER; |
humlet | 1:90455d5bdd8c | 135 | m_channel->transfer.adr = address; |
humlet | 1:90455d5bdd8c | 136 | m_channel->transfer.reg = regist; |
humlet | 1:90455d5bdd8c | 137 | m_channel->transfer.dta = data; |
humlet | 1:90455d5bdd8c | 138 | m_channel->transfer.len = length; |
humlet | 1:90455d5bdd8c | 139 | m_channel->transfer.rep = repeated; |
humlet | 1:90455d5bdd8c | 140 | sendNwait(); |
humlet | 1:90455d5bdd8c | 141 | int ret = m_channel->transfer.ret; |
humlet | 1:90455d5bdd8c | 142 | unlock(); |
humlet | 1:90455d5bdd8c | 143 | return ret; |
humlet | 1:90455d5bdd8c | 144 | } |
humlet | 1:90455d5bdd8c | 145 | |
humlet | 1:90455d5bdd8c | 146 | int I2CDriver::read(int ack) |
humlet | 1:90455d5bdd8c | 147 | { |
humlet | 1:90455d5bdd8c | 148 | lock(); |
humlet | 1:90455d5bdd8c | 149 | m_channel->transfer.cmd = READ_BYTE; |
humlet | 1:90455d5bdd8c | 150 | m_channel->transfer.ack = ack; |
humlet | 1:90455d5bdd8c | 151 | sendNwait(); |
humlet | 1:90455d5bdd8c | 152 | int ret = m_channel->transfer.ret; |
humlet | 1:90455d5bdd8c | 153 | unlock(); |
humlet | 1:90455d5bdd8c | 154 | return ret; |
humlet | 1:90455d5bdd8c | 155 | } |
humlet | 1:90455d5bdd8c | 156 | |
humlet | 1:90455d5bdd8c | 157 | int I2CDriver::write(int address, const char *data, int length, bool repeated) |
humlet | 1:90455d5bdd8c | 158 | { |
humlet | 0:13c962fecb13 | 159 | lock(); |
humlet | 1:90455d5bdd8c | 160 | m_channel->transfer.cmd = WRITE; |
humlet | 1:90455d5bdd8c | 161 | m_channel->transfer.adr = address; |
humlet | 1:90455d5bdd8c | 162 | m_channel->transfer.wdta = data; |
humlet | 1:90455d5bdd8c | 163 | m_channel->transfer.len = length; |
humlet | 1:90455d5bdd8c | 164 | m_channel->transfer.rep = repeated; |
humlet | 1:90455d5bdd8c | 165 | sendNwait(); |
humlet | 1:90455d5bdd8c | 166 | int ret = m_channel->transfer.ret; |
humlet | 1:90455d5bdd8c | 167 | unlock(); |
humlet | 1:90455d5bdd8c | 168 | return ret; |
humlet | 1:90455d5bdd8c | 169 | } |
humlet | 1:90455d5bdd8c | 170 | |
humlet | 1:90455d5bdd8c | 171 | int I2CDriver::write(int data) |
humlet | 1:90455d5bdd8c | 172 | { |
humlet | 1:90455d5bdd8c | 173 | lock(); |
humlet | 1:90455d5bdd8c | 174 | m_channel->transfer.cmd = WRITE_BYTE; |
humlet | 1:90455d5bdd8c | 175 | m_channel->transfer.ack = data; |
humlet | 0:13c962fecb13 | 176 | sendNwait(); |
humlet | 1:90455d5bdd8c | 177 | int ret = m_channel->transfer.ret; |
humlet | 1:90455d5bdd8c | 178 | unlock(); |
humlet | 1:90455d5bdd8c | 179 | return ret; |
humlet | 0:13c962fecb13 | 180 | } |
humlet | 1:90455d5bdd8c | 181 | |
humlet | 1:90455d5bdd8c | 182 | void I2CDriver::start(void) |
humlet | 1:90455d5bdd8c | 183 | { |
humlet | 1:90455d5bdd8c | 184 | lock(); |
humlet | 1:90455d5bdd8c | 185 | m_channel->transfer.cmd = START; |
humlet | 1:90455d5bdd8c | 186 | sendNwait(); |
humlet | 1:90455d5bdd8c | 187 | unlock(); |
humlet | 1:90455d5bdd8c | 188 | } |
humlet | 1:90455d5bdd8c | 189 | |
humlet | 1:90455d5bdd8c | 190 | |
humlet | 1:90455d5bdd8c | 191 | void I2CDriver::stop(void) |
humlet | 1:90455d5bdd8c | 192 | { |
humlet | 1:90455d5bdd8c | 193 | lock(); |
humlet | 1:90455d5bdd8c | 194 | m_channel->transfer.cmd = STOP; |
humlet | 1:90455d5bdd8c | 195 | sendNwait(); |
humlet | 1:90455d5bdd8c | 196 | unlock(); |
humlet | 1:90455d5bdd8c | 197 | } |