请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号:MSP430F5529 主题中讨论的其他部件:MSPDRIVERLIB
工具/软件:TI-RTOS
您好,
我正在尝试实施非常规I2C读取事务:
在TI-RTOS中,是否可以修改I2CUSCIB.c文件,以便在等待从从属设备读取数据之前先发送读取,然后发送寄存器地址?
/*
版权所有(c) 2015,Texas Instruments Incorporated
*保留所有权利。
*
**
允许以源代码和二进制格式重新发布和使用,无论是否进行*修改,只要
满足以下条件*:
*
****重新发布源代码必须保留上述版权
*声明,此条件列表和以下免责声明。
*
***以二进制格式重新分发时,必须在
随分发提供的*文档和/或其他材料中复制上述版权*声明,此条件列表和以下免责声明。
*
***
未经事先书面许可,不得使用德州仪器(TI)公司的名称或*其贡献者的名称来支持或促销由本软件衍生的产品*。
*
*本软件由版权所有者和贡献者"按原样"提供
*,
不提供任何明示或暗示的担保,包括但不限于*对适销性和特定*用途适用性的暗示担保。 在任何情况下,版权所有者或
*贡献者均不对任何直接,间接,附带,特殊,
*示范, 或后果性损害(包括但不限于
*购买替代商品或服务;使用,数据或利润损失;
(*或业务中断),但根据任何责任理论
,*无论是合同,严格责任还是侵权行为(包括疏忽或
*其他),均因使用本软件而导致*
,即使已被告知此类损害的可能性。
*/
#include <stdint.h>
#include <stdbool.h>
#include <xDC/runtime
/Error.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/state.h>#include <xdcc/runtime/diags.h>#sysb_interrupt/<sysb>
#sysb><sci_luth /lib_列<leck/lib_列<luth /lib_列
<b>#sysb><sci/sim_列/lib_列/<leck/<b>列<b>列<luth
<b>列/<sci>
列/<sci_列/<b>列/<b>列/<sci>列/b>列<列/b>列/b>列<列/b>列/<列/<列/b>列/b>列/b>列/<sim_列/<sb>
USCI_B_I2C_ARBIRTIONLOST_INTERRUPT)
#define all_interrupts (USI_B_I2C_RECEIVE_INTERRUPT |\
USI_B_I2C_Transmit_Interrupt |\
ERROR_Interrupts)
外部连接I2C_Config I2C_CONFIG[];
/*原型*/
void I2CUSCIB_CLOSE (I2C_HANDLE手柄);
内部 I2CUSCIB_CONTROL (I2C_HANDLE句柄,unsigned int cmd,void *arg);
void I2CUSCIB_INIT (I2C_HANDLE句柄);
I2C_HANDLE I2CUSCIB_OPEN (I2C_HANDLE句柄,I2C_PARAMS *参数);
静态空I2CUSCIB_PRIMETransfer (I2CUSCIB_Object *对象,
I2CUSCIB_HWAttrs const *hwAttrs,
I2C_Transaction *TransferMessage);
布尔 I2CUSCIB_TRANSFER (I2C_HANDLE手柄,
I2C_Transaction *TRANSACTILE);
静态void I2CUSCIB_blockingCallback (I2C_HANDLE句柄,
I2C_Transaction *msg,
bool transferStatus);
静态void I2CUSCIB_completeTransfer (I2C_handle handle);
/* I2CI2CUSCIB实现的I2C函数表*/
const I2C_Fxn表I2CUSCIB_fxnTable ={
I2CUSCIB_CLOSE,
I2CUSCIB_CONTROL,
I2CUSCIB_INIT,
I2CUSCIB_OPEN,
I2CUSCIB_TRANSFER
};
静态连接UINT32_t比特率[]={
USI_B_I2C_SET_DATA_RATE_100KBPS,/* I2C_100kHz = 0 */
USI_B_I2C_SET_DATA_RATE_400KBPS /* I2C_400kHz = 1 */
};/*
默认I2C参数*/
外部连接I2C_Params I2C_defaultParams;
/*
========= I2CUSCIB_CLOSE =========
*/
void I2CUSCIB_CLOSE (I2C_HANDLE手柄)
{
I2CUSCIB_Object *object =句柄->对象;
I2CUSCIB_HWAttrs const *hwAttrs = handl->hwAttrs;
/*检查I2C事务是否正在进行*/
Assert _isTrue (object->headPtr == NULL,NULL);
/*屏蔽I2C中断*/
USI_B_I2C_DisableInterrupt (hwAttrs->baseAddr,all_interrupts);
/*禁用I2C主控*/
USI_B_I2C_DISABLE (hwAttrs->baseAddr);
semaphore_析 构函数(&(object->mutex));
如果(object->transferMode == I2C_MODE_blocking){
semaphore_析 构函数(&(object->transferComplete);
}
object->isOpen =假;
Log_Print1 (Diags_User1,"I2C:对象关闭0x%x",hwAttrs->baseAddr);
返回;
}/*
==== I2CUSCIB_CONTROL =========
*@PRE函数假定句柄不是NULL
*/
int I2CUSCIB_CONTROL (I2C_句 柄,无符号int cmd,void *arg)
{
/*尚未实施*/
返回(I2C_STATUS_UNDEFINEDCMD);
}/*
========= I2CUSCIB_hwiIntFxn =========
*为I2C外设提供服务的HWI中断处理程序
*
*该处理程序是I2C对象的通用处理程序。
*/
void I2CUSCIB_hwiIntFxn (UArg索引)
{
无符号int 密钥;
UINT8_t intStatus;
I2CUSCIB_Object *object =(&I2C_CONFIG[index])->对象;
I2CUSCIB_HWAttrs const *hwAttrs =(&I2C_CONFIG[index])->hwAttrs;
/*获取I2C控制器的中断状态*/
intStatus = USI_B_I2C_getInterruptStatus (hwAttrs->baseAddr,all_interrupts);
Log_Print1 (Diags_User2,"Status Reg:0x%x",intStatus);
/*清除中断源*/
USI_B_I2C_clearInterrupt (hwAttrs->baseAddr,all_interrupts);
/*检查I2C错误*/
如果(intStatus & error_interrupts)||(object->mode == I2CUSCIB_error)){
/*发生了某种错误! */
object->mode = I2CUSCIB_error;
/*尝试发送停止位以立即结束所有I2C通信
*
* USI_B_I2C_masterReceiveMultiByteStop只发送停止条件
*此处需要
*/
USI_B_I2C_masterReceiveMultiByteStophwAttrs->baseAddr;
log_print2 (Diags_User1,"I2C:(%p) ISR I2C总线故障(状态注册器:0x%x)",
hwAttrs->baseAddr,
intStatus);
}
/*没有错误,现在检查我们接下来需要做什么*/
开关(对象->模式){
/*
*错误情况正常,因为如果检测到错误,则停止位为
*已发送;这又将调用另一个中断。 此中断
*呼叫随后将发布transferComplete信号以解除阻止
* I2C_TRANSFER函数
*/
案例I2CUSCIB_ERROR:
案例I2CUSCIB_IDLE_MODE:
I2CUSCIB_completeTransfer ((I2C_handle)&I2C_CONFIG[index]);
中断;
案例I2CUSCIB_WRITE_MODE:
如果(object->writeCountIdx){
/*如果我们在要写入的最后一个字节上,并且有要读取的数据*/
如果(object->writeCountIdx ==1)&&(!object->readCountIdx)){
/*下一个状态:空闲模式*/
object->mode = I2CUSCIB_IDLE_MODE;
/*发送最后一个带停止位的字节*/
USI_B_I2C_masterSendMultiByteFinishhwAttrs->baseAddr,
*(object->writeBufIdx);
USI_B_I2C_clearInterrupt (hwAttrs->baseAddr,
USI_B_I2C_Transmit_Interrupt);
log_print2 (Diags_User2,"I2C:(%p) ISR I2CUSCIB_write_mode:"
"要写入的数据:0x%x;
"使用停止位写入",
hwAttrs->baseAddr,
*(object->writeBufIdx);
I2CUSCIB_completeTransfer((I2C_handl)&I2C_CONFIG[index]);
}
否则{
/*将数据内容写入数据寄存器*/
USI_B_I2C_masterSendMultiByteNexthwAttrs->baseAddr,
*(object->writeBufIdx);
log_print3 (Diags_User2,
"I2C:(%p) ISR I2CUSCIB_write_mode:"
"要写入的数据:0x%x;"
"至从属设备:0x%x",
hwAttrs->baseAddr,
*(object->writeBufIdx),
object->currentTransaction->slaveAddress);
object->writeBufIdx+;
object->writeCountIdx--;}
}
/*
*已将数据写入I2C从属设备。 如果不需要读取数据,
* ISR不会到达此处,因为它已经完成了I2C
*以上逻辑检查中的传输。
*/
否则{
/*下一个状态:接收模式*/
object->mode = I2CUSCIB_READ_MODE;
/*切换到接收模式*/
USI_B_I2C_setMode (hwAttrs->baseAddr,USI_B_I2C_Receive_mode);
如果(object->readCountIdx >1){
/*发送重复启动而不停止*/
USI_B_I2C_masterReceiveMultiByteStarthwAttrs->baseAddr;
Log_Print1 (Diags_User2,"I2C:(%p) ISR"
"I2CUSCIB_write_mode:-> I2CUSCIB_READ_MODE;"
"通过重新启动读取",
hwAttrs->baseAddr);
}
否则{
/*
*发送重复的启动并停止,因为它是
*要读取的最后一个字节。
*/
USSCI_B_I2C_masterReceiveSingleStart(fwAttrs->baseAddr,*(object->writeBufIdx));
Log_Print1 (Diags_User2,"I2C:(%p) ISR"
"I2CUSCIB_write_mode:-> I2CUSCIB_READ_MODE;"
"通过重启和停止读取",
hwAttrs->baseAddr);
}
}
Break;/* I2CUSCIB_write_mode */
案例I2CUSCIB_READ_MODE:
/*从XBUF读取的数据和下一个字节已移位*/
object->readCountIdx--;
如果(object->readCountIdx ==1){
/*不可简化的计时关键块-开始*/
密钥= HWI_DISABLE();
USI_B_I2C_masterReceiveMultiByteStophwAttrs->baseAddr;
*(object->readBufIdx)=
USI_B_I2C_masterReceiveMultiByteNexthwAttrs->baseAddr;
HWI_RESTORE (密钥);
/*不能简化的计时关键块-结束*/
log_print2 (Diags_User2,"I2C:(%p) ISR I2CUSCIB_READ_MODE:"
"读取数据字节:0x%x",hwAttrs->baseAddr,
*(object->readBufIdx);
object->readBufIdx+;}
否则{
*(object->readBufIdx)=
USI_B_I2C_masterReceiveMultiByteNexthwAttrs->baseAddr;
log_print2 (Diags_User2,"I2C:(%p) ISR I2CUSCIB_READ_MODE:"
"读取数据字节:0x%x",hwAttrs->baseAddr,
*(object->readBufIdx);
如果(object->readCountIdx){
/*增量缓冲区指针*/
object->readBufIdx+;}
否则{
/*下一个状态:空闲模式*/
object->mode = I2CUSCIB_IDLE_MODE;
I2CUSCIB_completeTransfer((I2C_handl)&I2C_CONFIG[index]);
}
}
Break;/* I2CUSCIB_READ_MODE */
默认:
object->mode = I2CUSCIB_error;
中断;
}
返回;
}/*
==== I2CUSCIB_completeTransfer ====
*/
静态void I2CUSCIB_completeTransfer (I2C_handle手柄)
{
I2CUSCIB_Object *对象=句柄->对象;
Log_Print1 (Diags_User2,"I2C:(%p) ISR传输完成",
(I2CUSCIB_HWAttrs const *)(handle ->hwAttrs)->baseAddr);
/*
*在HWI上下文中执行回调,从而执行任何任务或SWI
*准备运行的操作在中断完成之前不会启动
*已完成
*/
object->transferCallbackFxn (句柄,
object->currentTransaction,
!(bool)object->mode);
/*查看我们是否需要处理任何其他交易*/
如果(object->headPtr == object->tailPtr){
/*不需要发生其他事务*/
object->currentTransaction =空;
object->headPtr =空;
Log_Print1 (Diags_User2,"I2C:(%p) ISR队列中没有其他I2C事务",
(I2CUSCIB_HWAttrs const *)(handl->hwAttrs)->baseAddr);
}
否则{
/*需要进行另一个传输*/
object->headPtr = object->headPtr ->nextPtr;
log_print2 (Diags_User2,"I2C:(%p) ISR Priming next I2C transaction "
"(%p)来自队列",
((I2CUSCIB_HWAttrs const *)(handle->hwAttrs)->baseAddr,
(UArg) object->headPtr);
I2CUSCIB_primeTransfer (对象,
(I2CUSCIB_HWAttrs const *)(handle->hwAttrs),
object->headPtr);
}
返回;
}/*
==== I2CUSCIB_INIT =========
*/
void I2CUSCIB_INIT (I2C_HANDLE句柄)
{
/*将对象标记为可用*/
(I2CUSCIB_Object *)(handle->object)->isOpen = FALSE;
}/*
========= I2CUSCIB_OPEN ==========
*/
I2C_HANDLE I2CUSCIB_OPEN (I2C_HANDLE HANDLE,I2C_PARAMS *参数)
{
无符号int 密钥;
UINT32_t 时钟频率;
USSCI_B_I2C_initMasterParam usciI2cParams;
信号量参数 SemParams;
I2CUSCIB_Object *object =句柄->对象;
I2CUSCIB_HWAttrs连接 *hwAttrs = handl->hwAttrs;
/*确定设备索引是否已打开*/
密钥= HWI_DISABLE();
如果(object->isOpen == true){
HWI_RESTORE (密钥);
返回(NULL);
}
/*将手柄标记为正在使用*/
object->isOpen =真;
HWI_RESTORE (密钥);
/*存储I2C参数*/
如果(参数== NULL){
/*没有参数传入,因此使用默认值*/
Params =(I2C_Params *)&I2C_defaultParams;
}
/*保存参数*/
object->transferMode =参数->transferMode;
object->transferCallbackFxn =参数->transferCallbackFxn;
/*
*为此I2C外设创建线程安全句柄
*信号灯,提供对I2C外设的独占访问
*/
semaphore_Params_init(&semParams);
semParams.mode = semaphore_Mode_binary;
semaphore_construct (&(object->mutex),1,&semParams);
/*
*存储一个回调函数,该函数可将转接完成
*同步模式的信号
*/
如果(object->transferMode == I2C_MODE_blocking){
/*
*信号导致等待任务为I2C阻塞
*结束
*/
semaphore_construct (&(object->transferComplete),0,&semParams);
/*存储内部回调函数*/
object->transferCallbackFxn = I2CUSCIB_blockingCallback;
}
否则{
/*检查是否为异步模式*/定义了回调函数
Assert _isTrue (object->transferCallbackFxn != NULL,NULL);
}
/*获取I2C时钟输入频率*/
交换机(hwAttrs->clockSource){
案例USI_B_I2C_CLOCKSOURCE_ACLK:
ClockFreq = ClockFreqs_getFrequency (ClockFreqs_Clock_ACLK);
Log_Print1 (Diags_User1,"ClockFreqs_getFrequency ACLK:%d",clockFreq);
中断;
案例USI_B_I2C_CLOCKSOURCE_SMCLK:
ClockFreq = ClockFreqs_getFrequency(ClockFreqs_Clock_SMCLK);
Log_Print1 (Diags_User1,"ClockFreqs_getFrequency SMCLK:%d",clockFreq);
中断;
默认:
log_error0 ("I2C:确定时钟源时出错");
I2CUSCIB_CLOSE (手柄);
返回(NULL);
}
/*指定此I2C外设的空闲状态*/
object->mode = I2CUSCIB_IDLE_MODE;
/*清除头指针*/
object->headPtr =空;
object->tailPtr =空;
Log_Print1 (Diags_User1,"I2C:对象已创建0x%x",hwAttrs->baseAddr);
usciI2cParams.selectClockSource = hwAttrs->clockSource;
usciI2cParams.i2cClk = clockFreq;
usciI2cParams.datarate =比特率[帕拉姆->比特率];
USSCI_B_I2C_INITMaster (hwAttrs->baseAddr,&usciI2cParams);
/*清除所有挂起的中断*/
USI_B_I2C_clearInterrupt (hwAttrs->baseAddr,all_interrupts);
/*启用I2CUSCIB模块以开始操作*/
USI_B_I2C_ENABLE (hwAttrs->baseAddr);
/*取消屏蔽I2CUSCIB中断*/
USI_B_I2C_enableInterrupt (hwAttrs->baseAddr,all_interrupts);
/*返回句柄*/
返回(句柄);
}/*
==== I2CUSCIB_primeTransfer ====
*/
静态void I2CUSCIB_primeTransfer(I2CUSCIB_Object *对象,
I2CUSCIB_HWAttrs const *hwAttrs,
I2C_Transaction *交易)
{
/*存储新的内部计数器和指针*/
object->currentTransaction =事务;
object->writeBufIdx = transaction->writeBuf;
object->writeCountIdx = transaction->writeCount;
object->readBufIdx =事务->readBuf;
object->readCountIdx = transaction->ReadCount;
log_print2 (Diags_User1,"I2C:(%p) Starting transaction to slave:0x%x",
hwAttrs->baseAddr,
object->currentTransaction->slaveAddress);
/*指定I2C从属地址*/
USI_B_I2C_setSlaveAddresshwAttrs->baseAddr,
object->currentTransaction->slaveAddress);
/*在传输模式下开始传输*/
如果(object->writeCountIdx){
/*更新I2C模式*/
object->mode = I2CUSCIB_write_mode;
USI_B_I2C_setMode (hwAttrs->baseAddr,USI_B_I2C_Transmit_mode);
/*通过发送起始位*开始I2C传输
USI_B_I2C_masterSendStarthwAttrs->baseAddr;
Log_Print1 (Diags_User2,"I2C:(%p) I2CUSCIB_IDLE_MODE:-> I2CUSCIB_WRIT_MODE;"
"正在写入且已启动",
hwAttrs->baseAddr);
}
/*在接收模式下开始传输*/
否则{
/*更新I2C模式*/
object->mode = I2CUSCIB_READ_MODE;
USI_B_I2C_setMode (hwAttrs->baseAddr,USI_B_I2C_Receive_mode);
如果(object->readCountIdx >1){
/*在主接收模式下启动I2C传输*/
USI_B_I2C_masterReceiveMultiByteStarthwAttrs->baseAddr;
Log_Print1 (Diags_User2,"I2C:(%p) I2CUSCIB_IDLE_MODE:-> I2CUSCIB_READ_MODE;"
"使用ACK读取",
hwAttrs->baseAddr);
}
否则{
/*
*通过发送启动在主接收模式下启动I2C传输
*和停止位
*/
USSCI_B_I2C_masterReceiveSingleStart(fwAttrs->baseAddr,*(object->writeBufIdx));
Log_Print1 (Diags_User2,"I2C:(%p) I2CUSCIB_IDLE_MODE:-> I2CUSCIB_READ_MODE;"
"读数,带nack ",
hwAttrs->baseAddr);
}
}
}/*
==== I2CUSCIB_TRANSFER ==========
*/
布尔I2CUSCIB_TRANSFER (I2C_HANDLE手柄,
I2C_Transaction *交易)
{
无符号int 密钥;
布尔 RET =假;
I2CUSCIB_Object *object =句柄->对象;
I2CUSCIB_HWAttrs const *hwAttrs = handl->hwAttrs;
/*检查是否需要写入或读取*/
如果(!transaction->writeCount)&&(!transaction->ReadCount)){
/*没有要写入或读取的内容*/
返回(ret);
}
如果(object->transferMode == I2C_MODE_callback){
/*检查传输是否正在进行*/
密钥= HWI_DISABLE();
如果(object->headPtr){
/*正在传输*/
/*
*更新尾部指向的消息以指向下一个
队列中的*消息
*/
object->tailPt->nextPtr =事务;
/*更新tailPtr以指向最后一条消息*/
object->tailPtr =事务;
/* I2C仍在使用*/
HWI_RESTORE (密钥);
返回(true);
}
否则{
/*存储表示I2C正在使用的HeadPtr */
object->headPtr =事务;
object->tailPtr =事务;
}
hwi_restore(key);
}
/*获取此特定I2C句柄的锁*/
semaphore_pend (semaphore_handle (&(object->mutex)),bios_wait_forever);
/*
* I2CUSCIB_primeTransfer是一个较长的过程
*需要对I2C中断提供保护
*/
USI_B_I2C_DisableInterrupt (hwAttrs->baseAddr,all_interrupts);
I2CUSCIB_primeTransfer (object,hwAttrs,transaction);
USI_B_I2C_enableInterrupt (hwAttrs->baseAddr,all_interrupts);
如果(object->transferMode == I2C_MODE_blocking){
Log_Print1 (Diags_User1,"I2C:(%p)等待转接完成信号",
hwAttrs->baseAddr);
/*
*在此处等待传输完成。
*可以从这里阻止,因为I2C的Hwi将取消阻止
*出错时
*/
semaphore_pend(semaphore_handl(&(object->transferComplete)),
BIOS_WAY_Forever);
Log_Print1 (Diags_User1,"I2C:(%p)事务已完成",
hwAttrs->baseAddr);
/* Hwi句柄已发布'transferComplete'错误检查*/
如果(object->mode == I2CUSCIB_IDLE_MODE){
Log_Print1 (Diags_User1,"I2C:(%p) Transfer OK",hwAttrs->baseAddr);
RET =真;
}
}
否则{
/*如果处于异步模式*/,则始终返回true
RET =真;
}
/*释放此特定I2C手柄的锁*/
semaphore_post(semaphore_handl(&(object->mutex));
/*返回I2C */传输的字节数
Return (ret);
}/*
==== I2CUSCIB_blockingCallback =========
*/
静态void I2CUSCIB_blockingCallback (I2C_handle句柄,
I2C_Transaction *msg,
布尔转移状态)
{
I2CUSCIB_Object *object =句柄->对象;
Log_Print1 (Diags_User1,"I2C:(%p) postingtransferComplete semaphore",
(I2CUSCIB_HWAttrs const *)(handle ->hwAttrs)->baseAddr);
/*表示传输完成*/
semaphore_post(semaphore_handl(&(object->transferComplete));
}