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
Revision 11:8c1d44595620, committed 2013-05-09
- Comitter:
- humlet
- Date:
- Thu May 09 20:52:07 2013 +0000
- Parent:
- 10:e3d6c92ff222
- Child:
- 12:6ddadcbbdca2
- Commit message:
- seem to work without tweaked mbed lib
Changed in this revision
--- a/I2CDriver.cpp Wed May 08 19:22:45 2013 +0000 +++ b/I2CDriver.cpp Thu May 09 20:52:07 2013 +0000 @@ -24,7 +24,7 @@ else error("I2CDriver: Invalid I2C pins selected\n"); if(s_channels[channel]==0) { - new Thread(threadFun,(void *)channel,osPriorityRealtime,512); // evillive + new Thread(threadFun,(void *)channel,osPriorityRealtime,1024); // evillive } m_channel = s_channels[channel]; } @@ -79,12 +79,9 @@ tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); break; case READ_MST_REG: - //printf("drv00\n"); tr.ret = i2cRtos_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0); - //printf("drv01\n"); if(tr.ret)break; // error => bail out tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); - //printf("drv02\n"); break; case READ_SLV: tr.ret = i2cRtos_slave_read(&i2c, tr.dta, tr.len); @@ -119,7 +116,7 @@ m_callerID = osThreadGetId(); m_callerPrio = osThreadGetPriority(m_callerID); m_channel->mutex.lock(osWaitForever); - osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock + osThreadSetPriority(m_callerID, c_drvPrio); // evillive hopefully not interrupted since the lock } void I2CDriver::unlock()
--- a/I2CDriverTest02.h Wed May 08 19:22:45 2013 +0000 +++ b/I2CDriverTest02.h Thu May 09 20:52:07 2013 +0000 @@ -4,10 +4,10 @@ #include "I2CSlaveRtos.h" const int freq = 400000; -const int adr = 42; -const int len=42; -const char* mstMsg="We are mbed, resistance is futile"; -const char* slvMsg="Fine with me, let's get addicted"; +const int adr = 42<<1; +const int len=34; +const char mstMsg[len]="We are mbed, resistance is futile"; +const char slvMsg[len]="Fine with me, let's get addicted "; static void slvRxMsg(I2CSlaveRtos& slv) {
--- a/I2CDriverTest04.h Wed May 08 19:22:45 2013 +0000 +++ b/I2CDriverTest04.h Thu May 09 20:52:07 2013 +0000 @@ -3,7 +3,7 @@ #include "I2CMasterRtos.h" #include "stdint.h" -DigitalOut osci(p16); +//DigitalOut osci(p16); volatile int g_disco=0; volatile int g_len=0; @@ -27,7 +27,7 @@ config(i2c); while(true) { - osci.write(0); + //osci.write(0); i2c.frequency(g_freq); Thread::signal_wait(1<<5,osWaitForever); // read back srf08 echo times (1+16 words) @@ -38,7 +38,7 @@ uint32_t dt=us_ticker_read()-t1; if(stat!=0) { - osci.write(1); + //osci.write(1); printf("\n%x %d %d %d\n",stat,g_freq,g_len,dt); exit(0); }
--- a/i2cRtos_api.c Wed May 08 19:22:45 2013 +0000 +++ b/i2cRtos_api.c Thu May 09 20:52:07 2013 +0000 @@ -11,7 +11,7 @@ #define I2C_DAT(x) (x->i2c->I2DAT) #include "gpio_api.h" -gpio_t gpio; // evillive +static gpio_t gpio[2]; // evillive enum I2cIsrCmd { readMst, @@ -23,7 +23,6 @@ struct I2cIsrTransfer { i2c_t* obj; enum I2cIsrCmd cmd; - int adr; int len; int cnt; int stat; @@ -35,7 +34,6 @@ struct IsrIrqSem { IRQn_Type irq; - //uint32_t isr; osSemaphoreId sem; }; static struct IsrIrqSem isrIrqSem[2]; @@ -65,111 +63,85 @@ return I2C_STAT(obj); } - // ISR stuff static void i2cRtos_isr(uint32_t ch) { - //printf("isr01\n"); - volatile struct I2cIsrTransfer* tr=&(i2c_transfer[ch]); - - if(tr->cmd==waitSI) { + struct I2cIsrTransfer* tr=&(i2c_transfer[ch]); + if(tr->cmd==waitSI){ osSemaphoreRelease(isrIrqSem[ch].sem); NVIC_DisableIRQ(isrIrqSem[ch].irq); return; } - int stat=i2c_status(tr->obj); int stay = 0; - switch(tr->cmd) { - case readMst: { - int cnt = (tr->cnt)++; - if(cnt==-1) { - if(stat==0x40) { - if(cnt != tr->len-2) { + case readMst: + switch(stat) { + case 0x50: + (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff); + case 0x40: + ++(tr->cnt); + if(tr->cnt != tr->len-1) i2c_conset(tr->obj, 0, 0, 0, 1); - } else { + else i2c_conclr(tr->obj, 0, 0, 0, 1); - } stay = 1; - } - } else if(cnt < tr->len-1) { - if(stat==0x50) { - (tr->rData)[cnt] = (char)(I2C_DAT(tr->obj) & 0xff); - if(cnt != tr->len-2) { - i2c_conset(tr->obj, 0, 0, 0, 1); - } else { - i2c_conclr(tr->obj, 0, 0, 0, 1); - } - stay = 1; - } - } else { - if(stat==0x58) { - (tr->rData)[cnt] = (char)(I2C_DAT(tr->obj) & 0xff); - stat = 0; - } + break; + case 0x58: + (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff); + stat=0; + break; } break; - } - case writeMst: { - int cnt = ++(tr->cnt); - if(cnt==0) { - if(stat==0x18) { - I2C_DAT(tr->obj) = (tr->wData)[cnt]; - stay = 1; - } - } else if(cnt < tr->len) { - if(stat==0x28) { - I2C_DAT(tr->obj) = (tr->wData)[cnt]; - stay = 1; - } - } else { - if(stat==0x28) { - stat = 0; - } + case writeMst: + switch(stat) { + case 0x18: + case 0x28: + if(++(tr->cnt)!=tr->len) { // evillive + I2C_DAT(tr->obj) = (tr->wData)[tr->cnt]; + stay=1; + } else { + stat=0; + } } break; - } - case readSlv: { - int cnt = ++(tr->cnt); + case readSlv: + ++(tr->cnt); if(stat==0x80 || stat==0x90) - (tr->rData)[cnt] = I2C_DAT(tr->obj) & 0xFF; - stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (cnt < tr->len-1); + (tr->rData)[tr->cnt] = I2C_DAT(tr->obj) & 0xFF; + stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (tr->cnt < tr->len-1); break; - } - case writeSlv: { - int cnt = ++(tr->cnt); - stay = cnt<tr->len && stat==0xb8; + case writeSlv: + ++(tr->cnt); + stay = tr->cnt<tr->len && stat==0xb8; if(stay) - I2C_DAT(tr->obj) = tr->wData[cnt]; + I2C_DAT(tr->obj) = tr->wData[tr->cnt]; break; - } - default: - error("Dial911 i2cRtos_isr\n"); } if(stay) { i2c_clear_SI(tr->obj); } else { - //i2c_clear_SI(tr->obj); tr->stat = stat; osSemaphoreRelease(isrIrqSem[ch].sem); NVIC_DisableIRQ(isrIrqSem[ch].irq); } } -void static i2cRtos_isr_ch0() // evillive +static void i2cRtos_isr_ch0() { + //gpio_write(&gpio[0], 1); i2cRtos_isr(0); + //gpio_write(&gpio[0], 0); } -void static i2cRtos_isr_ch1() +static void i2cRtos_isr_ch1() { - gpio_write(&gpio, 1); + //gpio_write(&gpio[1], 1); i2cRtos_isr(1); - gpio_write(&gpio, 0); + //gpio_write(&gpio[1], 0); } // determine channel -static inline uint32_t i2c_get_channel(i2c_t *obj) +static inline uint32_t i2c_get_channel(const i2c_t *obj) { #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) switch((I2CName)(obj->i2c)) { @@ -180,117 +152,72 @@ default: error("Dial911 i2c_get_channel: Invaid I2CName \n"); } -#elif defined(TARGET_LPC11U24) - return 1; -#else -#error "Dial911 i2c_get_channel: Unsupported HW" #endif return 1; } // wait for ISR finished -static inline void i2cRtos_wait_and_see(i2c_t *obj, int channel, uint32_t tmOut) +static void i2cRtos_wait_and_see(i2c_t *obj, int ch, uint32_t tmOut) //evillive { - struct IsrIrqSem* iis = &(isrIrqSem[channel]); - gpio_write(&gpio, 1); + struct IsrIrqSem* iis = &(isrIrqSem[ch]); __disable_irq(); i2c_clear_SI(obj); - NVIC_ClearPendingIRQ(iis->irq); // evillive + NVIC_ClearPendingIRQ(iis->irq); NVIC_EnableIRQ(iis->irq); __enable_irq(); - gpio_write(&gpio, 0); - if(osSemaphoreWait(iis->sem, tmOut)!=1) { - NVIC_DisableIRQ(iis->irq); - printf("Ouch!\n"); - } + if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq); +} + +static inline void i2cRtos_waitSI(i2c_t *obj, uint32_t tmOut){ + int ch = i2c_get_channel(obj); + i2c_transfer[ch].cmd = waitSI; + i2cRtos_wait_and_see(obj, ch, tmOut); } -// setup semaphores and hook in ISRs -void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl) -{ - gpio_init(&gpio, p15, PIN_OUTPUT); - - i2c_init(obj,sda,scl); - uint32_t ch = i2c_get_channel(obj); -#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) - static osSemaphoreDef(i2cIsrDrvSem_ch0); - static osSemaphoreDef(i2cIsrDrvSem_ch1); - switch(ch) { - case 0: - isrIrqSem[ch].irq = I2C1_IRQn; - //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch0; - NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0); - isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1); - osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever); - break; - case 1: - //printf("apicfg\n"); - isrIrqSem[ch].irq = I2C2_IRQn; - //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1; - NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1); - //NVIC_DisableIRQ(I2C2_IRQn); - isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1); - osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever); - break; - } -#elif defined(TARGET_LPC11U24) - static osSemaphoreDef(i2cIsrDrvSem_ch1); - isrIrqSem[ch].irq = I2C_IRQn; - //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1; - NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1); - isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1); - osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever); -#else -#error "Dial911 i2cRtos_init: Unsupported HW" -#endif -} - int i2cRtos_read(i2c_t *obj, int address, char *data, int length, int stop) { - gpio_write(&gpio, 1); - int status = i2c_start(obj); - if ((status != 0x10) && (status != 0x08)) { + gpio_write(&gpio[1], 1); + int stat = i2c_start(obj); + if ((stat != 0x10) && (stat != 0x08)) { i2c_stop(obj); - //printf("start Ouch read\n"); - return status; + return stat; } - gpio_write(&gpio, 0); + gpio_write(&gpio[1], 0); int ch = i2c_get_channel(obj); - volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? + struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? tr->obj=obj; tr->cmd=readMst; tr->len=length; tr->cnt=-1; tr->rData=data; I2C_DAT(obj) = address | 0x01; - i2cRtos_wait_and_see(obj, ch,2);// 1+(length>>2)); // timeout (1+len/4)ms - status = tr->stat; - if(status || stop) i2c_stop(obj); - return status; + i2cRtos_wait_and_see(obj, ch,2+(length>>2)); // timeout (2+len/4)ms + stat = tr->stat; + if(stat || stop) i2c_stop(obj); + return stat; } int i2cRtos_write(i2c_t *obj, int address, const char *data, int length, int stop) { + gpio_write(&gpio[1], 1); int status = i2c_start(obj); if ((status != 0x10) && (status != 0x08)) { i2c_stop(obj); - printf("start Ouch write\n"); return status; } + gpio_write(&gpio[1], 0); int ch = i2c_get_channel(obj); - volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? + struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? tr->obj=obj; tr->cmd=writeMst; tr->len=length; tr->cnt=-1; tr->wData=data; I2C_DAT(obj) = address & 0xfe; - //printf("api01\n"); - i2cRtos_wait_and_see(obj, ch,2);// 2+(length>>2)); // timeout (1+len/4)ms - //printf("api02\n"); - //i2c_clear_SI(obj); // ... why? Also in official lib + i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (2+len/4)ms + i2c_clear_SI(obj); // ... why? Also in official lib ... I guess this is the "write instead of start" bug status = tr->stat; if(status || stop) i2c_stop(obj); return status; @@ -303,19 +230,14 @@ } else { i2c_conset(obj, 0, 0, 0, 1); // send a ACK } - int ch = i2c_get_channel(obj); - i2c_transfer[ch].cmd = waitSI; - i2cRtos_wait_and_see(obj, ch, 2); + i2cRtos_waitSI(obj, 2); return (I2C_DAT(obj) & 0xff); - } int i2cRtos_byte_write(i2c_t *obj, int data) { I2C_DAT(obj) = (data & 0xff); - int ch = i2c_get_channel(obj); - i2c_transfer[ch].cmd = waitSI; - i2cRtos_wait_and_see(obj, ch, 2); + i2cRtos_waitSI(obj, 2); int stat=i2c_status(obj); return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8); } @@ -329,11 +251,8 @@ int retval = i2c_slave_receive(obj); //check for pending requests if(retval)return retval; // there is one => bail out - // No request? Wait for it! - int ch = i2c_get_channel(obj); - i2c_transfer[ch].cmd = waitSI; - i2cRtos_wait_and_see(obj, ch, tmOut); + i2cRtos_waitSI(obj, tmOut); // check again for pending requests return i2c_slave_receive(obj); } @@ -341,7 +260,7 @@ int i2cRtos_slave_read(i2c_t *obj, char *data, int length) { int ch = i2c_get_channel(obj); - volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? + struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? tr->obj=obj; tr->cmd=readSlv; tr->len=length; @@ -351,7 +270,7 @@ if(tr->stat != 0xa0) { i2c_stop(obj); } - i2c_clear_SI(obj); // ... why? Also in official lib + i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low return tr->cnt; // same weird return as in official lib } @@ -361,21 +280,62 @@ return(0); } int ch = i2c_get_channel(obj); - volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? + struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem? tr->obj=obj; tr->cmd=writeSlv; tr->len=length; tr->cnt=0; tr->wData=data; I2C_DAT(obj) = data[0]; - i2cRtos_wait_and_see(obj, ch, 1+(length>>2)); // timeout (1+len/4)ms + i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (1+len/4)ms int status = tr->stat; if(status!=0xC0 && status!=0xC8) { i2c_stop(obj); } - i2c_clear_SI(obj); // ... why? Also in official lib + i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low return tr->cnt; } + +// setup semaphores and hook in ISRs +void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl) +{ + static int called=0; + if(!called) { + gpio_init(&gpio[0], p15, PIN_OUTPUT); + gpio_init(&gpio[1], p16, PIN_OUTPUT); + } + called = 1; + gpio_write(&gpio[0], 0); + gpio_write(&gpio[1], 0); + + i2c_init(obj,sda,scl); + uint32_t ch = i2c_get_channel(obj); +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) + static osSemaphoreDef(i2cIsrDrvSem_ch0); + static osSemaphoreDef(i2cIsrDrvSem_ch1); + switch(ch) { + case 0: + isrIrqSem[ch].irq = I2C1_IRQn; + NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0); + isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1); + break; + case 1: + isrIrqSem[ch].irq = I2C2_IRQn; + NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1); + isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1); + break; + } + osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever); +#elif defined(TARGET_LPC11U24) + static osSemaphoreDef(i2cIsrDrvSem_ch1); + isrIrqSem[ch].irq = I2C_IRQn; + NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1); + isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1); + osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever); +#else +#error "Dial911 i2cRtos_init: Unsupported HW" +#endif +} #endif #endif
--- a/mbed-NXP.lib Wed May 08 19:22:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/humlet/code/mbed-NXP/#692b566d83bf
--- a/mbed-src.lib Wed May 08 19:22:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/humlet/code/mbed-src/#49923059ddc8