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 10:e3d6c92ff222, committed 2013-05-08
- Comitter:
- humlet
- Date:
- Wed May 08 19:22:45 2013 +0000
- Parent:
- 9:65aae53a34de
- Child:
- 11:8c1d44595620
- Commit message:
- less smoke, actually it seems to work
Changed in this revision
--- a/I2CDriver.cpp Sat May 04 16:47:56 2013 +0000 +++ b/I2CDriver.cpp Wed May 08 19:22:45 2013 +0000 @@ -79,10 +79,12 @@ tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); break; case READ_MST_REG: - //printf("Disco\n"); + //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);
--- a/I2CDriverTest04.h Sat May 04 16:47:56 2013 +0000 +++ b/I2CDriverTest04.h Wed May 08 19:22:45 2013 +0000 @@ -3,6 +3,8 @@ #include "I2CMasterRtos.h" #include "stdint.h" +DigitalOut osci(p16); + volatile int g_disco=0; volatile int g_len=0; volatile int g_freq=100000; @@ -18,20 +20,28 @@ void highPrioThreadFun(void const *args) { + //printf("tst01\n"); i2cDrvThrdID = Thread::gettid(); I2CMasterRtos i2c(p28, p27); - + //printf("tst02\n"); config(i2c); while(true) { + osci.write(0); i2c.frequency(g_freq); Thread::signal_wait(1<<5,osWaitForever); // read back srf08 echo times (1+16 words) const char reg= 0x3a; char result[64]; uint32_t t1=us_ticker_read(); - i2c.read(i2cAdr, reg, result, g_len); + int stat = i2c.read(i2cAdr, reg, result, g_len); + uint32_t dt=us_ticker_read()-t1; + if(stat!=0) { + osci.write(1); + printf("\n%x %d %d %d\n",stat,g_freq,g_len,dt); + exit(0); + } uint16_t tm=((static_cast<uint16_t>(result[0])<<8)|static_cast<uint16_t>(result[1])); if(--g_disco>0) printf("tm=%8d dt=%4dus\n",tm,dt); @@ -45,11 +55,11 @@ Thread::wait(100); highPrioTicker.start(1); - + #if defined(TARGET_LPC1768) const int nTest=7; const int freq[nTest]= {1e5, 1e5, 1e5, 4e5, 4e5, 4e5, 4e5}; - const int len[nTest]= {1, 4, 6, 1, 6, 12, 30}; + const int len[nTest]= {1, 4, 6, 1, 6, 12, 36}; #elif defined(TARGET_LPC11U24) const int nTest=5; const int freq[nTest]= {1e5, 1e5, 4e5, 4e5, 4e5 }; @@ -81,9 +91,11 @@ } void readModWrite(I2CMasterRtos& i2c, uint8_t reg, uint8_t dta) -{ +{ + //printf("rmw01\n"); char rd1; int rStat1 = i2c.read(i2cAdr, reg, &rd1, 1); + //printf("rmw02\n"); char data[2]; data[0]=(char)reg; data[1]=(char)dta; @@ -107,7 +119,7 @@ regs[cnt]=0x19; vals[cnt++]=0; // sample rate divider reg // sapmle rate = gyro rate / (1+x) regs[cnt]=0x1a; - vals[cnt++]=0;// conf reg // no ext frame sync / no dig low pass set to 1 => 8kHz Sampling + vals[cnt++]=0;// conf reg // no ext frame sync / no dig low pass set to 1 => 8kHz Sampling regs[cnt]=0x1b; vals[cnt++]=0;// gyro conf reg // no test mode and gyro range 250°/s regs[cnt]=0x1c;
--- a/i2cRtos_api.c Sat May 04 16:47:56 2013 +0000 +++ b/i2cRtos_api.c Wed May 08 19:22:45 2013 +0000 @@ -10,6 +10,9 @@ #define I2C_STAT(x) (x->i2c->I2STAT) #define I2C_DAT(x) (x->i2c->I2DAT) +#include "gpio_api.h" +gpio_t gpio; // evillive + enum I2cIsrCmd { readMst, writeMst, @@ -27,12 +30,12 @@ char* rData; const char* wData; }; -volatile static struct I2cIsrTransfer i2c_transfer[2]; // evillive: dare to get rid of volatile? +static struct I2cIsrTransfer i2c_transfer[2]; // evillive: dare to get rid of volatile? struct IsrIrqSem { IRQn_Type irq; - uint32_t isr; + //uint32_t isr; osSemaphoreId sem; }; static struct IsrIrqSem isrIrqSem[2]; @@ -64,8 +67,9 @@ // ISR stuff -static inline void i2cRtos_isr(uint32_t ch) +static void i2cRtos_isr(uint32_t ch) { + //printf("isr01\n"); volatile struct I2cIsrTransfer* tr=&(i2c_transfer[ch]); if(tr->cmd==waitSI) { @@ -82,7 +86,11 @@ int cnt = (tr->cnt)++; if(cnt==-1) { if(stat==0x40) { - i2c_conset(tr->obj, 0, 0, 0, 1); + 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(cnt < tr->len-1) { @@ -142,18 +150,21 @@ 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); } } -static inline void i2cRtos_isr_ch0() +void static i2cRtos_isr_ch0() // evillive { i2cRtos_isr(0); } -static inline void i2cRtos_isr_ch1() +void static i2cRtos_isr_ch1() { + gpio_write(&gpio, 1); i2cRtos_isr(1); + gpio_write(&gpio, 0); } @@ -172,9 +183,9 @@ #elif defined(TARGET_LPC11U24) return 1; #else - #error "Dial911 i2c_get_channel: Unsupported HW" +#error "Dial911 i2c_get_channel: Unsupported HW" #endif -return 1; + return 1; } @@ -182,16 +193,25 @@ static inline void i2cRtos_wait_and_see(i2c_t *obj, int channel, uint32_t tmOut) { struct IsrIrqSem* iis = &(isrIrqSem[channel]); - //NVIC_ClearPendingIRQ(iis->irq); // evillive + gpio_write(&gpio, 1); + __disable_irq(); i2c_clear_SI(obj); + NVIC_ClearPendingIRQ(iis->irq); // evillive NVIC_EnableIRQ(iis->irq); - if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq); + __enable_irq(); + gpio_write(&gpio, 0); + if(osSemaphoreWait(iis->sem, tmOut)!=1) { + NVIC_DisableIRQ(iis->irq); + printf("Ouch!\n"); + } } // 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) @@ -200,13 +220,17 @@ switch(ch) { case 0: isrIrqSem[ch].irq = I2C1_IRQn; - isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch0; + //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; + //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; @@ -214,21 +238,25 @@ #elif defined(TARGET_LPC11U24) static osSemaphoreDef(i2cIsrDrvSem_ch1); isrIrqSem[ch].irq = I2C_IRQn; - isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1; - isrIrqSem[1].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1); - osSemaphoreWait(isrIrqSem[0].sem, osWaitForever); + //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" +#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)) { i2c_stop(obj); + //printf("start Ouch read\n"); return status; } + gpio_write(&gpio, 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? tr->obj=obj; @@ -237,7 +265,7 @@ tr->cnt=-1; tr->rData=data; I2C_DAT(obj) = address | 0x01; - i2cRtos_wait_and_see(obj, ch, 1+(length>>2)); // timeout (1+len/4)ms + 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; @@ -248,6 +276,7 @@ int status = i2c_start(obj); if ((status != 0x10) && (status != 0x08)) { i2c_stop(obj); + printf("start Ouch write\n"); return status; } int ch = i2c_get_channel(obj); @@ -258,8 +287,10 @@ tr->cnt=-1; tr->wData=data; I2C_DAT(obj) = address & 0xfe; - i2cRtos_wait_and_see(obj, ch, 1+(length>>2)); // timeout (1+len/4)ms - i2c_clear_SI(obj); // ... why? Also in official lib + //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 status = tr->stat; if(status || stop) i2c_stop(obj); return status; @@ -274,9 +305,9 @@ } int ch = i2c_get_channel(obj); i2c_transfer[ch].cmd = waitSI; - i2cRtos_wait_and_see(obj, ch, 1); + i2cRtos_wait_and_see(obj, ch, 2); return (I2C_DAT(obj) & 0xff); - + } int i2cRtos_byte_write(i2c_t *obj, int data) @@ -284,7 +315,7 @@ I2C_DAT(obj) = (data & 0xff); int ch = i2c_get_channel(obj); i2c_transfer[ch].cmd = waitSI; - i2cRtos_wait_and_see(obj, ch, 1); + i2cRtos_wait_and_see(obj, ch, 2); int stat=i2c_status(obj); return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8); } @@ -316,7 +347,7 @@ tr->len=length; tr->cnt=-1; tr->rData=data; - 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 if(tr->stat != 0xa0) { i2c_stop(obj); }