📄 i2c_hal.c
字号:
/**
*@file i2c_hal.c
*@author Zlatan Stanojevic
*/
#ifdef __ADSPBF537__
#include <services/services.h>
#include <cdefBF537.h>
#include "i2c_framing_layer.h"
//#define CLKIN 25000000
//#include "../../misc/clock_query.h"
/**
* Controls the IVG for TWI interrupts.
*/
//#define INT_LEVEL 14 // use default
static enum
{
I2C_UNCONFIGURED,
I2C_IDLE,
I2C_SCANBUS,
I2C_READ,
I2C_WRITE,
I2C_GET,
I2C_SET,
} state = I2C_UNCONFIGURED;
u16 fast_flag;
static I2CScanCallback scan_callback;
static I2CCallback msg_callback;
static unsigned char *msg_start;
static unsigned char *msg_buffer;
static unsigned char msg_size;
unsigned char xmt_counter = 0;
unsigned char rcv_counter = 0;
static void load( void );
static ADI_INT_HANDLER( TWI_HANDLER )
{
u16 irq = *pTWI_INT_STAT;
if( irq )
{
u16 stat = *pTWI_MASTER_STAT;
u16 addr = *pTWI_MASTER_ADDR;
switch( state )
{
case I2C_SCANBUS:
{
if( ! addr )
{
*pTWI_INT_MASK = 0;
state = I2C_IDLE;
*pTWI_MASTER_STAT = 0x003f;
*pTWI_INT_STAT = 0x00ff;
}
else
{
*pTWI_MASTER_STAT = 0x003f;
( *pTWI_MASTER_ADDR )--;
*pTWI_MASTER_CTL = MEN | fast_flag;
*pTWI_INT_STAT = 0x00ff;
}
if( ( ! ( stat & ANAK ) ) && scan_callback )
scan_callback( (u8)addr );
break;
}
case I2C_WRITE:
case I2C_SET:
{
if( irq & XMTSERV )
{
*pTWI_XMT_DATA8 = *(msg_buffer++);
xmt_counter++;
}
if( irq & MCOMP )
{
if( msg_callback )
msg_callback( xmt_counter, msg_start );
*pTWI_FIFO_CTL = 0x0001; //flush fifo
asm( "ssync;" );
*pTWI_FIFO_CTL = 0;
*pTWI_INT_MASK = 0;
state = I2C_IDLE;
}
*pTWI_INT_STAT = 0x00ff;
break;
}
case I2C_GET:
{
if( irq & MCOMP )
{
*pTWI_INT_MASK = RCVSERV | MCOMP;
*pTWI_MASTER_CTL = msg_size << 6 | MDIR | MEN | fast_flag;
state = I2C_READ;
}
*pTWI_INT_STAT = 0x00ff;
break;
}
case I2C_READ:
{
if( irq & RCVSERV )
{
*(msg_buffer++) = *pTWI_RCV_DATA8;
rcv_counter++;
}
else if( irq & MCOMP )
{
if( msg_callback )
msg_callback( rcv_counter, msg_start );
*pTWI_INT_MASK = 0;
state = I2C_IDLE;
}
*pTWI_INT_STAT = 0x00ff;
break;
}
case I2C_IDLE:
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = 0;
break;
}
return ADI_INT_RESULT_PROCESSED;
}
return ADI_INT_RESULT_NOT_PROCESSED;
}
void I2CInitHAL( unsigned long pa_lFrequency, unsigned long pa_lSystemClk)
{
unsigned long nIVG;
adi_int_SICGetIVG(ADI_INT_TWI, &nIVG);
// adi_int_SICSetIVG( ADI_INT_TWI, INT_LEVEL );
adi_int_CECHook( nIVG/*INT_LEVEL*/, TWI_HANDLER, 0, FALSE );
adi_int_SICEnable( ADI_INT_TWI );
*pTWI_CLKDIV = 5000000 / pa_lFrequency; //set SCL freq
*pTWI_CLKDIV |= *pTWI_CLKDIV << 8;
*pTWI_CONTROL = 1 << 7 | (u16)( pa_lSystemClk / 10000000. ); //enable twi and set clk ref.
fast_flag = 0;
state = I2C_IDLE;
if( pa_lFrequency > 100000 )
fast_flag = FAST;
}
void I2CScanbus( I2CScanCallback callback )
{
state = I2C_SCANBUS;
scan_callback = callback;
*pTWI_FIFO_CTL = 0;
*pTWI_MASTER_ADDR = 128;
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = MCOMP;
*pTWI_MASTER_CTL = MEN;
while( state != I2C_IDLE );
}
void _I2CRead_non_blocking( unsigned char hwid, unsigned char *message,
unsigned char msg_length, I2CCallback callback )
{
while( state != I2C_IDLE );
state = I2C_READ;
msg_callback = callback;
msg_start = message;
msg_buffer = message;
msg_size = msg_length;
*pTWI_MASTER_ADDR = hwid;
*pTWI_FIFO_CTL = 0;
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = RCVSERV | MCOMP;
*pTWI_MASTER_CTL = ( msg_length ) << 6 | MDIR | MEN | fast_flag;
}
void _I2CWrite_non_blocking( unsigned char hwid, unsigned char *message,
unsigned char msg_length, I2CCallback callback )
{
while( state != I2C_IDLE );
state = I2C_WRITE;
msg_callback = callback;
msg_start = message;
msg_buffer = message + 1;
msg_size = msg_length;
*pTWI_MASTER_ADDR = hwid;
*pTWI_XMT_DATA8 = *message;
*pTWI_FIFO_CTL = 0;
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = XMTSERV | MCOMP;
*pTWI_MASTER_CTL = ( msg_length ) << 6 | MEN | fast_flag;
}
void _I2CSet_non_blocking( unsigned char hwid, unsigned char start_addr,
unsigned char *values, unsigned char vals_length, I2CCallback callback )
{
while( state != I2C_IDLE );
state = I2C_SET;
msg_callback = callback;
msg_buffer = msg_start = values;
msg_size = vals_length;
*pTWI_MASTER_ADDR = hwid;
*pTWI_XMT_DATA8 = start_addr;
*pTWI_FIFO_CTL = 0;
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = XMTSERV | MCOMP;
*pTWI_MASTER_CTL = ( vals_length + 1 ) << 6 | MEN | fast_flag;
}
void _I2CGet_non_blocking( unsigned char hwid, unsigned char start_addr,
unsigned char *values, unsigned char vals_length, I2CCallback callback )
{
while( state != I2C_IDLE );
state = I2C_GET;
msg_callback = callback;
msg_buffer = values;
msg_size = vals_length;
*pTWI_MASTER_ADDR = hwid;
*pTWI_XMT_DATA8 = start_addr;
*pTWI_FIFO_CTL = 0;
*pTWI_INT_STAT = 0x00ff;
*pTWI_INT_MASK = MCOMP;
*pTWI_MASTER_CTL = 1 << 6 | RSTART | MEN | fast_flag;
}
void _I2CRead_blocking( unsigned char hwid, unsigned char *message,
unsigned char msg_length )
{
_I2CRead_non_blocking( hwid, message, msg_length, 0 );
while( state != I2C_IDLE );
}
void _I2CWrite_blocking( unsigned char hwid, unsigned char *message,
unsigned char msg_length )
{
_I2CWrite_non_blocking( hwid, message, msg_length, 0 );
while( state != I2C_IDLE );
}
void _I2CSet_blocking( unsigned char hwid, unsigned char start_addr,
unsigned char *values, unsigned char vals_length )
{
_I2CSet_non_blocking( hwid, start_addr, values, vals_length, 0 );
while( state != I2C_IDLE );
}
void _I2CGet_blocking( unsigned char hwid, unsigned char start_addr,
unsigned char *values, unsigned char vals_length )
{
_I2CGet_non_blocking( hwid, start_addr, values, vals_length, 0 );
while( state != I2C_IDLE );
}
#else //__ADSPBF537__
//#warning i2c_hal.c: No BF537 target specified. Compilation of i2c_hal.c omitted.
#endif //__ADSPBF537__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -