Hi!
I want to I2C bus of Wavecom Fastrack Supreme (Q2687G, R74_00-cus-q26-01_.wpk ) module to communicate with a sensors. Software is Open AT Software Suite v2.30 (M2M Studio 1.0, Application OS 6.30) (with site wavecom.com/modules/movie/sc … ck_Supreme).
I using example “ExternalStorage_IIC” from library.
Then, I try to send test data to the slave device by using adl_busWrite() function or get data by using adl_busRead() function. But, it will return error code: -2 (ADL_RET_ERR_PARAM), I checked my parameters and can not figure out the error. Can anyone help me with this problem?
The below is my log and test code:
Start I2C
Create_I2C
DRV_HANDLE=403446544
at+write=12,2b2b2b
Writing=-2
DRV_HANDLE=403446544
I2CBus_Access.Address=1179648
I2CBus_Access.Opcode=0
WriteBuff->Length=3
WriteBuff->Data=+++
OK
/********************************************************************************************/
/* ext_storage_iic.c - Copyright Wavecom S.A. (c) 2004 */
/********************************************************************************************/
/***************************************************************************/
/* File : ext_storage_iic.c */
/*-------------------------------------------------------------------------*/
/* Object : Customer application */
/* */
/* contents : ADL External Storage Sample */
/* */
/*
$LogWavecom: U:\projet\mmi\pvcsarch\archives\open-at\SAMPLES\adl\External_Storage\src\ext_storage.c-arc $
* --------------------------------------------------------------------------
* Date | Author | Revision | Description
* ----------+--------+----------------+-------------------------------------
* 19.12.05 | DPO | 1.1 | * Resolution for 31871: External
* | | | storage sample update
* ----------+--------+----------------+-------------------------------------
* 24.08.04 | DPO | 1.0 | Initial revision.
* ----------+--------+----------------+-------------------------------------
*/
/****************************************************************************/
/* includes */
#include "adl_global.h"
#include "drv_m24cxx.h"
/***************************************************************************/
/* Mandatory variables */
/*-------------------------------------------------------------------------*/
/* wm_apmCustomStackSize */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
const u16 wm_apmCustomStackSize = 1024;
const u32 wm_apmIRQLowLevelStackSize = 1024;
const u32 wm_apmIRQHighLevelStackSize = 1024;
/* consts */
// Commands string
static const ascii * ES_STR_READ_CMD = "at+READ";
static const ascii * ES_STR_WRITE_CMD = "at+WRITE";
static const ascii * ES_SET_MODE = "at+SETMODE";
// Used I2C E2P chip
#define USED_E2P_I2C_CHIP DRV_I2C_E2P_M24C64
// MAX data length
#define MAX_DATA_LENGTH 128
// Max address sizes
static const u32 ChipMaxSizes = DRV_I2C_E2P_M24CXX_READ_MAX_LENGTH(USED_E2P_I2C_CHIP);
// Max write sizes
static const u32 ChipMaxWriteSizes = DRV_I2C_E2P_M24CXX_WRITE_MAX_LENGTH;
adl_busAccess_t *I2CBus_Access;
// Read buffer
drv_Read_I2C_E2P_M24CXX_t *ReadBuff;
// Write buffer
drv_Write_I2C_E2P_M24CXX_t *WriteBuff;
// Asynchronous Reading Context
AsyncReadCtxt_t * AsyncReadCtxt;
// IIC Bus Driver Handle
u32 DRV_HANDLE;
// Is asynchrnous reading result awaited ?
bool AsyncReadRes;
// low level IRQ Handle for asynchronous bus mode
s32 appBusLowIrqHandle;
// High level IRQ Handle for asynchronous bus mode
s32 appBusHighIrqHandle;
// mode : synchronous by default
static u16 mode = 1;
// Trace level
u8 drv_TraceLevel;
/***************************************************************************/
/* Function : es_SETMODE_CmdHandler */
/*-------------------------------------------------------------------------*/
/* Objet : Change mode between Synchronous and Asynchronous using */
/* properly ADL_BUS_CMD_SET_ASYNC_MODE */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* paras | | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void es_SETMODE_CmdHandler ( adl_atCmdPreParser_t *paras )
{
u8 sReturn = ADL_STR_OK;
s32 retval;
adl_busEvt_t busEvt;
adl_busEvt_t Param;
// Switch on CmdType
switch(paras->Type)
{
case ADL_CMD_TYPE_READ :
{
// Possible values
ascii result[100];
if (!mode)
{
wm_sprintf ( result, "\r\n %d : Mode is asynchronous\r\n", mode );
TRACE ((drv_TraceLevel, "Asynchronous mode is set"));
}
else
{
wm_sprintf ( result, "\r\n %d : Mode is synchronous\r\n", mode );
TRACE ((drv_TraceLevel, "Synchronous mode is set"));
}
adl_atSendResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), result );
}
break;
case ADL_CMD_TYPE_TEST :
sReturn = ADL_STR_ERROR;
break;
case ADL_CMD_TYPE_PARA :
{
ascii * P0 = ADL_GET_PARAM ( paras, 0 );
mode = wm_atoi(P0);
if (mode == 0)
{
busEvt.LowLevelIrqHandle = appBusLowIrqHandle;
busEvt.HighLevelIrqHandle = appBusHighIrqHandle;
// Set asynchronous mode
retval = adl_busIOCtl ( DRV_HANDLE,
ADL_BUS_CMD_SET_ASYNC_MODE,
&busEvt );
if (retval < 0)
{
TRACE ((drv_TraceLevel, "Setting asynchronous mode failed : %d", retval));
sReturn = ADL_STR_ERROR;
}
else
{
// Check if asynchronous mode is set
retval = adl_busIOCtl ( DRV_HANDLE,
ADL_BUS_CMD_GET_ASYNC_MODE,
&Param );
if ( (retval < 0)
|| (Param.LowLevelIrqHandle != appBusLowIrqHandle)
|| (Param.HighLevelIrqHandle != appBusHighIrqHandle) )
{
TRACE ((drv_TraceLevel, "Getting asynchronous mode failed : %d (handles %d,%d)", retval, Param.LowLevelIrqHandle, Param.HighLevelIrqHandle));
sReturn = ADL_STR_ERROR;
}
else
{
TRACE ((drv_TraceLevel, "Asynchronous mode is correctly set"));
}
}
}
else if (mode == 1)
{
busEvt.LowLevelIrqHandle = 0;
busEvt.HighLevelIrqHandle = 0;
// Set synchronous mode
retval = adl_busIOCtl ( DRV_HANDLE,
ADL_BUS_CMD_SET_ASYNC_MODE,
&busEvt );
if (retval < 0)
{
TRACE ((drv_TraceLevel, "Setting synchronous mode failed : %d", retval));
sReturn = ADL_STR_ERROR;
}
else
{
// Check if synchronous mode is set
retval = adl_busIOCtl ( DRV_HANDLE,
ADL_BUS_CMD_GET_ASYNC_MODE,
&Param );
if ( (retval < 0)
|| (Param.LowLevelIrqHandle != 0)
|| (Param.HighLevelIrqHandle != 0) )
{
TRACE ((drv_TraceLevel, "Getting synchronous mode failed : %d (handles %d,%d)", retval, Param.LowLevelIrqHandle, Param.HighLevelIrqHandle));
sReturn = ADL_STR_ERROR;
}
else
{
TRACE ((drv_TraceLevel, "Synchronous mode is correctly set"));
}
}
}
}
break;
}
adl_atSendStdResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), sReturn );
}
/***************************************************************************/
/* Function : es_READ_CmdHandler */
/*-------------------------------------------------------------------------*/
/* Objet : External Storage read command */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* paras | | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void es_READ_CmdHandler ( adl_atCmdPreParser_t *paras )
{
u8 sReturn = ADL_STR_OK;
// Switch on CmdType
switch(paras->Type)
{
case ADL_CMD_TYPE_TEST :
{
// Possible values
ascii result[100];
wm_sprintf ( result, "\r\n%s: (0-%X),(1-%d)\r\n",
ES_STR_READ_CMD + 2,
ChipMaxSizes - 1,
MAX_DATA_LENGTH - 1 );
adl_atSendResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), result );
}
break;
case ADL_CMD_TYPE_PARA :
{
ascii * P0 = ADL_GET_PARAM ( paras, 0 ),
* P1 = ADL_GET_PARAM ( paras, 1 );
// Get Byte length
u16 ByteLength = P1 ? wm_atoi ( P1 ) : 1;
if ( ByteLength >= MAX_DATA_LENGTH )
{
TRACE (( drv_TraceLevel, "Parameters error " ));
sReturn = ADL_STR_ERROR;
}
else
{
if (ReadBuff)
{
adl_memRelease ( ReadBuff );
}
if (AsyncReadCtxt)
{
adl_memRelease ( AsyncReadCtxt );
}
ReadBuff = adl_memGet ( sizeof ( drv_Read_I2C_E2P_M24CXX_t ) + ByteLength );
AsyncReadCtxt = adl_memGet ( sizeof ( AsyncReadCtxt_t ) );
ReadBuff->Length = ByteLength ? ByteLength : 1;
ReadBuff->Address = P0 ? wm_hexatoi ( P0 , wm_strlen ( P0 ) ) % ChipMaxSizes : 0;
AsyncReadCtxt->ByteLength = ByteLength ? ByteLength : 1;
AsyncReadCtxt->Port = paras->Port;
if (!mode)
{
// in asynchronous mode
// set global variable to get reading result in high irq handler
AsyncReadRes = TRUE;
}
// Read from driver
if ( !drv_I2C_E2P_M24CXX_Read ( ReadBuff, AsyncReadCtxt ) )
{
// if mode is synchronous reading result is synchronously available
if (mode)
{
// Build response string
ascii * StrResult = adl_memGet ( ByteLength * 2 + 30 );
// I2C chip: 4 digits address
wm_sprintf ( StrResult, "\r\n%s: %.4X,\"", ES_STR_READ_CMD + 2, ReadBuff->Address );
wm_ibuftohexa ( StrResult + wm_strlen ( StrResult ), ReadBuff->Data, ByteLength );
wm_strcat ( StrResult, "\"\r\n" );
adl_atSendResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), StrResult );
adl_memRelease ( StrResult );
adl_memRelease ( ReadBuff );
}
}
else
{
if (!mode)
{
// in asynchronous mode
// reset global variable since reading failed
AsyncReadRes = FALSE;
}
}
}
}
break;
}
adl_atSendStdResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), sReturn );
}
/***************************************************************************/
/* Function : es_WRITE_CmdHandler */
/*-------------------------------------------------------------------------*/
/* Objet : External Storage write command */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* paras | | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void es_WRITE_CmdHandler ( adl_atCmdPreParser_t *paras )
{
u8 sReturn = ADL_STR_OK;
// Switch on CmdType
switch(paras->Type)
{
case ADL_CMD_TYPE_TEST :
{
// Possible values
ascii result[100];
int MaxWriteSizes = ChipMaxWriteSizes * 2 ;
wm_sprintf ( result, "\r\n%s: (0-%X),(1-%d)\r\n",
ES_STR_WRITE_CMD + 2,
ChipMaxSizes - 1,
MaxWriteSizes );
adl_atSendResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), result );
}
break;
case ADL_CMD_TYPE_PARA :
{
ascii * P0 = ADL_GET_PARAM ( paras, 0 );
ascii * P1 = ADL_GET_PARAM ( paras, 1 );
u16 DataLength = wm_strlen ( P1 ) / 2;
// Fill write buffer
WriteBuff = adl_memGet ( sizeof ( drv_Write_I2C_E2P_M24CXX_t ) + DataLength );
WriteBuff->Address = wm_hexatoi ( P0 , wm_strlen ( P0 ) ) % ChipMaxSizes;
WriteBuff->Length = DataLength ?
( DataLength > ChipMaxWriteSizes ?
ChipMaxWriteSizes :
DataLength ) :
1;
wm_hexatoibuf ( WriteBuff->Data, P1 );
if ( ( P1 == NULL )
|| ( WriteBuff->Length < 1 )
|| ( WriteBuff->Length > MAX_DATA_LENGTH ) )
{
TRACE (( drv_TraceLevel, "Parameters error " ));
sReturn = ADL_STR_ERROR;
}
else
{
// Write from driver
if ( !drv_I2C_E2P_M24CXX_Write ( WriteBuff ) )
{
// All is OK, nothing to do
}
}
adl_memRelease ( WriteBuff );
}
break;
}
adl_atSendStdResponse ( ADL_AT_PORT_TYPE ( paras->Port, ADL_AT_RSP ), sReturn );
}
/***************************************************************************/
/* Function : busLowIrqHandler */
/*-------------------------------------------------------------------------*/
/* Objet : IRQ low level handler for Bus asynchronous operation */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* Source | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/* NotificationLevel | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/* Data | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
bool busLowIrqHandler(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel,
adl_irqEventData_t *Data)
{
adl_busAsyncInfo_t *info = (adl_busAsyncInfo_t*)Data->SourceData;
TRACE (( drv_TraceLevel, "Low level Bus handler" ));
// Check result
if (info->Result!=OK)
{
TRACE (( drv_TraceLevel, "Wrong result : %d (expected %d)", info->Result, OK));
}
return TRUE;
}
/***************************************************************************/
/* Function : busHighIrqHandler */
/*-------------------------------------------------------------------------*/
/* Objet : IRQ high level handler for Bus asynchronous operation */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* Source | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/* NotificationLevel | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/* Data | X | | | holding command parameter */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
bool busHighIrqHandler(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel,
adl_irqEventData_t *Data)
{
AsyncReadCtxt = (AsyncReadCtxt_t*)Data->Context;
TRACE (( drv_TraceLevel, "High level Bus handler" ));
if (AsyncReadRes)
{
// asynchronous reading result is awaited and now availble
// Build response string
ascii * StrResult = adl_memGet ( AsyncReadCtxt->ByteLength * 2 + 30 );
// I2C chip: 4 digits address
wm_sprintf ( StrResult, "\r\n%s: %.4X,\"", "at+READ" + 2, ReadBuff->Address );
wm_ibuftohexa ( StrResult + wm_strlen ( StrResult ), ReadBuff->Data, AsyncReadCtxt->ByteLength );
wm_strcat ( StrResult, "\"\r\n" );
adl_atSendResponse ( ADL_AT_PORT_TYPE ( AsyncReadCtxt->Port, ADL_AT_RSP ), StrResult );
adl_memRelease ( StrResult );
// reset variable
AsyncReadRes = FALSE;
}
return FALSE;
}
/***************************************************************************/
/* Function : drv_I2C_E2P_M24CXX_Init */
/*-------------------------------------------------------------------------*/
/* Object : Subscribe to the peripheral IIC bus */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
u32 drv_I2C_E2P_M24CXX_Init ( void )
{
u32 length = 16;
adl_busI2CSettings_t I2CSettings =
{
0x50, // ChipAddress
ADL_BUS_I2C_CLK_STD // Clk_Speed
};
/* Open I2C bus */
DRV_HANDLE = adl_busSubscribe ( ADL_BUS_I2C,
1,
&I2CSettings );
// Initialize IRQ for asynchronous bus mode test
appBusLowIrqHandle = adl_irqSubscribe ( busLowIrqHandler, ADL_IRQ_NOTIFY_LOW_LEVEL,
ADL_IRQ_PRIORITY_LOW_LEVEL, ADL_IRQ_OPTION_AUTO_READ );
appBusHighIrqHandle = adl_irqSubscribe ( busHighIrqHandler,ADL_IRQ_NOTIFY_HIGH_LEVEL,
ADL_IRQ_PRIORITY_HIGH_LEVEL, ADL_IRQ_OPTION_AUTO_READ );
adl_busIOCtl(DRV_HANDLE, ADL_BUS_CMD_SET_ADD_SIZE, &length);
return DRV_HANDLE;
}
/***************************************************************************/
/* Function : drv_I2C_E2P_M24CXX_Close */
/*-------------------------------------------------------------------------*/
/* Object : Unsubscribe to the peripheral IIC bus */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void drv_I2C_E2P_M24CXX_Close ( void )
{
TRACE (( drv_TraceLevel, "M24CXX Driver unsubscription" ));
/* Close I2C bus */
adl_busUnsubscribe ( DRV_HANDLE );
DRV_HANDLE = ERROR;
}
// Bus access structure compute function
static adl_busAccess_t * drv_I2C_E2P_M24CXX_ComputeBusAccess ( u32 Address )
{
// Compute Bus Access structure from provided opcode & address
static adl_busAccess_t iicBus_Access = { 0, 0 };
u8 AddressMax = 32;
u8 length = 16;
// Check if address is required
if ( Address != 0xFFFF )
{
// Set address
iicBus_Access.Address = Address << ( AddressMax - length );
}
else
{
// Reset address
length = iicBus_Access.Address = 0;
}
TRACE (( drv_TraceLevel, "[M24CXX Driver] compute access (address : %x (length %d))", iicBus_Access.Address, length ));
// Return structure
return &iicBus_Access;
}
/***************************************************************************/
/* Function : drv_I2C_E2P_M24CXX_Read */
/*-------------------------------------------------------------------------*/
/* Object : Read on the the peripheral IIC bus */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* pRead | x | | | Reading buffer */
/*--------------------+---+---+---+----------------------------------------*/
/* AsyncReadCtxt | x | | | Asynchronous Reading Context */
/*--------------------+---+---+---+----------------------------------------*/
/* sRet | x | | | Reading result OK / ERRROR */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
u32 drv_I2C_E2P_M24CXX_Read ( drv_Read_I2C_E2P_M24CXX_t * pRead,
AsyncReadCtxt_t * AsyncReadCtxt )
{
u32 sRet;
ReadBuff = pRead;
I2CBus_Access = drv_I2C_E2P_M24CXX_ComputeBusAccess ( ReadBuff->Address );
TRACE (( drv_TraceLevel, "M24CXX Driver read" ));
/* I2C bus read */
sRet = adl_busReadExt ( DRV_HANDLE,
I2CBus_Access,
ReadBuff->Length,
ReadBuff->Data,
AsyncReadCtxt );
return sRet;
}
/***************************************************************************/
/* Function : drv_I2C_E2P_M24CXX_Write */
/*-------------------------------------------------------------------------*/
/* Object : Write on the the peripheral IIC bus */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* pWrite | x | | | Writing buffer */
/*--------------------+---+---+---+----------------------------------------*/
/* sRet | x | | | Writing result OK / ERRROR */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
u32 drv_I2C_E2P_M24CXX_Write ( drv_Write_I2C_E2P_M24CXX_t * pWrite )
{
u32 sRet;
WriteBuff = pWrite;
I2CBus_Access = drv_I2C_E2P_M24CXX_ComputeBusAccess ( WriteBuff->Address );
TRACE (( drv_TraceLevel, "M24CXX Driver write" ));
DUMP ( drv_TraceLevel, WriteBuff->Data, WriteBuff->Length );
/* I2C bus write */
sRet = adl_busWrite ( DRV_HANDLE,
I2CBus_Access,
WriteBuff->Length,
WriteBuff->Data );
return sRet;
}
/***************************************************************************/
/* Function : adl_main */
/*-------------------------------------------------------------------------*/
/* Objet : Customer ADL application initialisation */
/* */
/* Return : */
/* */
/*-------------------------------------------------------------------------*/
/* Variable Name |IN |OUT|GLB| Utilisation */
/*--------------------+---+---+---+----------------------------------------*/
/* adlInitType | | | | Application starting mode */
/***************************************************************************/
void adl_main(adl_InitType_e adlInitType)
{
drv_TraceLevel = 2;
TRACE (( drv_TraceLevel, "External Storage sample init" ));
TRACE (( drv_TraceLevel, __DATE__ ));
TRACE (( drv_TraceLevel, __TIME__ ));
// Init external memory driver
if ( drv_I2C_E2P_M24CXX_Init() )
{
TRACE (( drv_TraceLevel, "External Memory driver subscribed" ));
TRACE (( drv_TraceLevel, "at+SETMODE=X : 0 for Asynchronous mode OR 1 for Synchronous mode " ));
// Subscribe to READ/WRITE/SET MODE commands
adl_atCmdSubscribe ( (ascii *)ES_STR_READ_CMD, es_READ_CmdHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_PARA | 0x22 );
adl_atCmdSubscribe ( (ascii *)ES_STR_WRITE_CMD, es_WRITE_CmdHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_PARA | 0x22 );
adl_atCmdSubscribe ( (ascii *)ES_SET_MODE, es_SETMODE_CmdHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_PARA | ADL_CMD_TYPE_READ | 0x11 );
}
}