diff -r a179b74831c9 -r c1f20ce4abcf kerneltest/e32test/iic/iic_psl/i2c.cpp --- a/kerneltest/e32test/iic/iic_psl/i2c.cpp Thu Aug 19 11:14:22 2010 +0300 +++ b/kerneltest/e32test/iic/iic_psl/i2c.cpp Tue Aug 31 16:34:26 2010 +0300 @@ -20,7 +20,7 @@ #include #endif - +#ifndef STANDALONE_CHANNEL #if defined(MASTER_MODE) && !defined(SLAVE_MODE) const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster}; #elif defined(MASTER_MODE) && defined(SLAVE_MODE) @@ -30,6 +30,7 @@ #endif #define CHANNEL_TYPE(n) (KChannelTypeArray[n]) #define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex) +#endif/*STANDALONE_CHANNEL*/ #ifdef STANDALONE_CHANNEL _LIT(KPddNameI2c,"i2c_ctrless.pdd"); @@ -46,14 +47,15 @@ } #endif/*STANDALONE_CHANNEL*/ -#ifdef SLAVE_MODE +//Macros MASTER_MODE and SLAVE_MODE are intentionally omitted from this file +//This is for master and slave stubs to exercise the channel class, +//and we need these stubs for code coverage tests. LOCAL_C TInt16 AssignSlaveChanId() { static TInt16 iBaseSlaveChanId = KI2cSlaveChannelIdBase; I2C_PRINT(("I2C AssignSlaveChanId - on entry, iBaseSlaveChanId = 0x%x\n",iBaseSlaveChanId)); return iBaseSlaveChanId++; // Arbitrary, for illustration } -#endif/*SLAVE_MODE*/ NONSHARABLE_CLASS(DSimulatedI2cDevice) : public DPhysicalDevice { @@ -125,9 +127,10 @@ aDes.Copy((TUint8*)&caps,size); } +#ifndef STANDALONE_CHANNEL // supported channels for this implementation static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS]; - +#endif //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY) DECLARE_STANDARD_PDD() // I2c test driver to be explicitly loaded as an LDD, not kernel extension @@ -228,8 +231,6 @@ return new DSimulatedI2cDevice; } - -#ifdef MASTER_MODE #ifdef STANDALONE_CHANNEL EXPORT_C #endif @@ -251,6 +252,8 @@ if(r == KErrNone) SetDfcQ((TDfcQue*)iDynamicDfcQ); DSimulatedIicBusChannelMasterI2c::SetRequestDelayed(this,EFalse); + //Call to base class DoCreate(not strictly necessary) + DIicBusChannelMaster::DoCreate(); return r; } @@ -421,7 +424,8 @@ default: { Kern::Printf("aFunction %d is not recognised \n",aFunction); - r=KErrNotSupported; + //For default case call the base class method for consistent handling + r=DIicBusChannelMaster::StaticExtension(aFunction,NULL,NULL); } } @@ -431,22 +435,49 @@ return r; } -//#ifdef MASTER_MODE -#endif - -#ifdef SLAVE_MODE - void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr) { // To support simulating an asynchronous capture operation - // NOTE: this will be invoked in the context of DfcThread1 I2C_PRINT(("SlaveAsyncSimCallback\n")); DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr; - TInt r=KErrNone;// Just simulate successful capture + + // This will be invoked in the context of DfcThread1, so require + // synchronised access to iAsyncEvent and iRxTxTrigger + // Use local variables to enable early release of the spin lock + // + // If DfcThread1 runs on a separate core to the simulated I2C bus, the other core + // will have updated values, and since this core may cached copies, memory access + // should be observed. The spin lock mechanism is expected to incorpoate this. + TInt intState=__SPIN_LOCK_IRQSAVE(channel->iEventSpinLock); + + TAsyncEvent asyncEvent = channel->iAsyncEvent; + TInt rxTxTrigger = channel->iRxTxTrigger; + channel->iAsyncEvent = ENoEvent; + channel->iRxTxTrigger = 0; + __SPIN_UNLOCK_IRQRESTORE(channel->iEventSpinLock,intState); + + switch(asyncEvent) + { + case (EAsyncChanCapture): + { + TInt r=KErrNone;// Just simulate successful capture #ifdef IIC_INSTRUMENTATION_MACRO - IIC_SCAPTCHANASYNC_END_PSL_TRACE; + IIC_SCAPTCHANASYNC_END_PSL_TRACE; #endif - channel->ChanCaptureCb(r); + channel->ChanCaptureCb(r); + break; + } + case (ERxWords): + case (ETxWords): + case (ERxTxWords): + { + channel->ChanNotifyClient(rxTxTrigger); + break; + } + default: + { + } + } } #ifdef STANDALONE_CHANNEL @@ -454,8 +485,9 @@ #endif DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex) : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class - iBlockedTrigger(0),iBlockNotification(EFalse), - iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this) + iBlockedTrigger(0),iBlockNotification(EFalse),iAsyncEvent(ENoEvent),iRxTxTrigger(0), + iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this), + iEventSpinLock(TSpinLock::EOrderGenericIrqHigh2) // Semi-arbitrary, high priority value (NTimer used) { I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex)); #ifndef STANDALONE_CHANNEL @@ -488,7 +520,10 @@ IIC_SCAPTCHANASYNC_START_PSL_TRACE; #endif // To simulate an asynchronous capture operation, just set a timer to expire - iSlaveTimer.OneShot(1000, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 + TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); + iAsyncEvent = EAsyncChanCapture; + __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); + iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 } else { @@ -600,7 +635,7 @@ void DSimulatedIicBusChannelSlaveI2c::ProcessData(TInt aTrigger, TIicBusSlaveCallback* aCb) { - I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::ProcessData\n")); + I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::ProcessData trigger=0x%x\n",aTrigger)); // fills in iReturn, iRxWords and/or iTxWords // if(aTrigger & ERxAllBytes) @@ -631,7 +666,6 @@ iRxTxUnderOverRun&= ~ETxOverrun; } } - aCb->SetTrigger(aTrigger); } @@ -709,8 +743,13 @@ if(iBlockNotification == EFalse) { // - // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback - NotifyClient(trigger); + // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback + TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); + // Tx may already have been requested, to add to the existing flags set in iRxTxTrigger + iRxTxTrigger |= trigger; + iAsyncEvent = ERxWords; + __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); + iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 } else { @@ -784,8 +823,14 @@ if(iBlockNotification == EFalse) { // - // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback - NotifyClient(trigger); + // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback + TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); + // Rx may already have been requested, to add to the existing flags set in iRxTxTrigger + iRxTxTrigger |= trigger; + iAsyncEvent = ETxWords; + __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); + iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 + // No effect if OneShot already invoked } else { @@ -868,8 +913,13 @@ if(iBlockNotification == EFalse) { // - // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback - NotifyClient(trigger); + // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback + TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); + // Rx or Tx may already have been requested, to add to the existing flags set in iRxTxTrigger + iRxTxTrigger |= trigger; + iAsyncEvent = ERxTxWords; + __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); + iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 } else { @@ -989,7 +1039,8 @@ default: { Kern::Printf("aFunction %d is not recognised \n",aFunction); - r=KErrNotSupported; + //For default case call the base class method for consistent handling + r=DIicBusChannelSlave::StaticExtension(aFunction,NULL,NULL); } } #ifdef IIC_INSTRUMENTATION_MACRO @@ -998,12 +1049,6 @@ return r; } - - -//#ifdef MASTER_MODE -#endif - -#if defined(MASTER_MODE) && defined(SLAVE_MODE) #ifdef STANDALONE_CHANNEL EXPORT_C #endif @@ -1035,7 +1080,7 @@ #ifndef STANDALONE_CHANNEL r=DIicBusController::DeRegisterChannel(this); #else - return KErrNotSupported; + r = KErrNotSupported; #endif break; } @@ -1054,15 +1099,13 @@ default: { Kern::Printf("aFunction %d is not recognised \n",aFunction); - r=KErrNotSupported; + //For default case call the base class method for consistent handling + r=DIicBusChannelMasterSlave::StaticExtension(aFunction,NULL,NULL); } } return r; } -//#if defined(MASTER_MODE) && defined(SLAVE_MODE) -#endif -