--- 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 <drivers/iic_trace.h>
#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
-