微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > CC2540串口无法收到数据

CC2540串口无法收到数据

时间:10-02 整理:3721RD 点击:

我们的业务场景:定期扫描所有蓝牙设备,收到串口请求后,发送蓝牙设备信息。

技术实现:在BLE-CC254x-1.4.0的Demo程序SimpleBLECentral的基础上,参考SimpleBLEPeripheral。使用UART DMA ,在配置里关掉POWER_SAVING,串口接收数据使用Poll模式。蓝牙发现间隔为200ms,发现周期为2000ms。上位机发送串口请求蓝牙设备的频率为1000ms一次。

调试的时候发现一个奇怪的问题,系统运行正常,串口会隔几分钟收不到来自上位机的数据,大约1分钟后自动恢复正常。如果关闭发现蓝牙设备,串口通讯就会很正常,从不出错。

看到有人说可以修改官方的DMA Buffer的处理,在http://blog.itpub.net/29285470/viewspace-1172403/ 找到一个例子,试验了一下发现没有效果。

大家有没有遇到过类似的问题呢?不胜感激。

===================================================================================================================

问题备忘录:

2014年7月18日,推测官方的DMA处理中,关于接收和发送的逻辑没有处理好,所以我就索性关闭了接收功能,定期把发现的蓝牙设备发送给上位机,再测试,没发现过死掉的情况。以后需要的话再继续研究DMA Buffer处理的函数。

非常感谢各位的回复。

Jiang,

请尝试一下在init里面把下面的代码注释掉

HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_divIDE_ON_HALT );

看看效果如何?

贴一个我的uart代码,请参考:

#include "bcomdef.h"
#include "OSAL.h"
#include "OSAL_PwrMgr.h"

#include "OnBoard.h"
#include "hal_adc.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_lcd.h"

#include "gatt.h"

#include "gapgattserver.h"
#include "gattservapp.h"
#include "devinfoservice.h"
#include "simpleGATTprofile.h"

#include "peripheral.h"

#include "gapbondmgr.h"

#include "serialAppPeripheral.h"

#include "serialAppUtil.h"
#include "hal_uart.h"


#define reportQEmpty() ( firstQIdx == lastQIdx )

/*********************************************************************
* CONSTANTS
*/
#define MAX_SAPP_PACKET_LEN 20
#define MAX_SAPP_NUM_ENTRIES 30


/*********************************************************************
* TYPEDEFS
*/


/*********************************************************************
* LOCAL VARIABLES
*/
static uint8 sendMsgTo_TaskID;

static uint8 firstQIdx = 0;
static uint8 lastQIdx = 0;
static attHandleValueNoti_t packetQ[MAX_SAPP_NUM_ENTRIES];


/*********************************************************************
* LOCAL FUNCTIONS
*/
static void SerialAppEnqueue( attHandleValueNoti_t* );
static attHandleValueNoti_t *packetDequeue( void );


/*********************************************************************
* PUBLIC FUNCTIONS
*/


/*********************************************************************
* @fn SerialApp_Init
*
* @brief Serial app initialization
*
* @param none
* @param none
*
*
* @return none
*/
void SerialApp_Init( uint8 taskID )
{

SerialAppInitTransport();

sendMsgTo_TaskID = taskID;
}

/*********************************************************************
* @fn SerialAppInitTransport
*
* @brief Initialize serial trans port
*
* @param none
* @param none
*
*
* @return none
*/
void SerialAppInitTransport(void)
{
halUARTCfg_t uartConfig;

/* configure UART */
uartConfig.configured = TRUE;
uartConfig.baudRate = SBP_UART_BR;
uartConfig.flowControl = SBP_UART_FC;
uartConfig.flowControlThreshold = SBP_UART_FC_THRESHOLD;
uartConfig.rx.maxBufSize = SBP_UART_RX_BUF_SIZE;
uartConfig.tx.maxBufSize = SBP_UART_TX_BUF_SIZE;
uartConfig.idleTimeout = SBP_UART_IDLE_TIMEOUT;
uartConfig.intEnable = SBP_UART_INT_ENABLE;
uartConfig.callBackFunc = SerialAppPacketParserCB;

(void)HalUARTOpen( SBP_UART_PORT, &uartConfig );

return;
}


/*******************************************************************************
* @fn SerialAppPacketParserCB
*
* @brief UART回调函数 从串口接收一个BLE命令或者数据包(由数据类型决定).
*
* SAPP command packet format:
* Packet Type + Command opcode + lengh + command payload
* | 1 octet | 2 | 1 | n |
*
* SAPP data packet format:
* Packet Type + Conn Handle + lengh + data payload
* | 1 octet | 2 | 2 | n |
*
* input parameters
*
* @param port - UART callback serial port.
* @param event - UART callback event number.
*
* output parameters
*
* @param None.
*
* @return None.
*/
void SerialAppPacketParserCB( uint8 port,uint8 event )
{
static uint8 sappPktState = SAPP_PARSER_STATE_PKT_TYPE;

static uint8 pktType;
static uint16 param1;
static uint16 pktLen;

uint16 numBytes;

(void)event;

/* 检查是否有串口数据等待处理 */
if ( (numBytes = Hal_UART_RxBufLen(port)) > 0 )
{
/* 检查是否开始处理一个新的数据包 */
if ( sappPktState == SAPP_PARSER_STATE_PKT_TYPE )
{
/* 读取数据包类型 */
(void)HalUARTRead (port, &pktType, 1);

numBytes -= 1;

/* 在数据包类型的基础上设置下一个状态 */
switch( pktType )
{
/* 数据包类型是命令 */
case SAPP_CMD_PACKET:
sappPktState = SAPP_CMD_PARSER_STATE_OPCODE;
break;

/* 数据包类型是数据 */
case SAPP_ACL_DATA_PACKET:
case SAPP_SCO_DATA_PACKET:
sappPktState = SAPP_DATA_PARSER_STATE_HANDLE;
break;

default:

return;

}
}

/* 处理串口字节建立命令或者数据包 */
switch( sappPktState )
{
/* 命令操作码 */
case SAPP_CMD_PARSER_STATE_OPCODE:
if (numBytes < 2) break;

/* 读取操作码 */
(void)HalUARTRead (port, (uint8 *)&param1, 2);

numBytes -= 2;

sappPktState = SAPP_CMD_PARSER_STATE_LENGTH;

/* 命令长度 */
case SAPP_CMD_PARSER_STATE_LENGTH:
if (numBytes < 1) break;

/* 在设置之前清除 */
pktLen = 0;

/* 读取长度 */
(void)HalUARTRead (port, (uint8 *)&pktLen, 1);

numBytes -= 1;

sappPktState = SAPP_CMD_PARSER_STATE_DATA;

/* 有效命令 */
case SAPP_CMD_PARSER_STATE_DATA:

/* 检查是否有足够的串口数据来填充命令包 */
if ( numBytes >= pktLen )
{
sappPacket_t *pMsg;

/* 判断有足够的串口数据来填充命令包, 分配内存 */
pMsg = (sappPacket_t *)osal_msg_allocate( sizeof (sappPacket_t) + SAPP_CMD_MIN_LENGTH + pktLen );

/* 是否有一个分配的内存块, 有则填充 */
if ( pMsg )
{
/* 填充pMsg命令 */
pMsg->pData = (uint8*)(pMsg+1);
pMsg->pData[0] = pktType;
pMsg->pData[1] = ((uint8 *)&param1)[0]; // opcode (LSB)
pMsg->pData[2] = ((uint8 *)&param1)[1]; // opcode (MSB)
pMsg->pData[3] = ((uint8 *)&pktLen)[0]; // one byte of length for cmd

/* 拷贝串口数据到pMsg */
(void)HalUARTRead (port, &pMsg->pData[4], pktLen);

/* 设置特定标志 */
pMsg->hdr.status = 0xFF;

/* 检查是否是一个链路层命令 */
if ( ((param1 >> 10) == VENDOR_SPECIFIC_OGF) &&
(((param1 >> 7) & 0x07) != SAPP_OPCODE_CSG_LINK_LAYER) )
{
/* 这是一个供应商的特定命令 */
pMsg->hdr.event = SAPP_EXT_CMD_EVENT;

/* 提取OGF */
pMsg->pData[2] &= 0x03;

(void)osal_msg_send( sendMsgTo_TaskID, (uint8 *)pMsg );

}

else
{
/* 这是一个普通的主机控制器事件 */
pMsg->hdr.event = SAPP_HOST_TO_CTRL_CMD_EVENT;

/* 发送SAPP处理程序 */
(void)osal_msg_send( sendMsgTo_TaskID, (uint8 *)pMsg );
}

/* 准备开始下一个数据包的处理 */
sappPktState = SAPP_PARSER_STATE_PKT_TYPE;
}
}

break;

case SAPP_DATA_PARSER_STATE_HANDLE:
if (numBytes < 2) break;

/* 读取数据连接句柄 */
(void)HalUARTRead (port, (uint8 *)&param1, 2);

numBytes -= 2;

sappPktState = SAPP_DATA_PARSER_STATE_LENGTH;

case SAPP_DATA_PARSER_STATE_LENGTH:
if (numBytes < 1) break;

pktLen = 0;

/* 读取长度 */
(void)HalUARTRead (port, (uint8 *)&pktLen, 1);

/* 验证数据包的长度被SBP_UART_RX_BUF_SIZE允许 */
if ( pktLen >= SBP_UART_RX_BUF_SIZE )
{
/* 出错 重新开始 */
sappPktState = SAPP_PARSER_STATE_PKT_TYPE;
break;
}

numBytes -= 1;

sappPktState = SAPP_DATA_PARSER_STATE_DATA;

case SAPP_DATA_PARSER_STATE_DATA:

/* 检查是否有足够的串口数据来填充数据包 */
if ( numBytes >= pktLen )
{
sappDataPacket_t *pMsg;

/* 有足够的串口数据来填充命令包, 分配内存 */
pMsg = (sappDataPacket_t *)osal_msg_allocate( sizeof(sappDataPacket_t) );

/* 是否有一个分配的内存块, 有则填充 */
if ( pMsg )
{
pMsg->hdr.event = SAPP_HOST_TO_CTRL_DATA_EVENT;
pMsg->hdr.status = 0xFF;

/* 填充pMsg数据 */
pMsg->pktType = pktType;
pMsg->connHandle = param1 & 0x0FFF;
pMsg->pbFlag = (param1 & 0x3000) >> 12;
pMsg->pktLen = pktLen;
pMsg->pData = osal_mem_alloc(pktLen);

if ( pMsg->pData )
{
/* 拷贝串口数据到pMsg */
(void)HalUARTRead (port, pMsg->pData, pktLen);

/* 发送消息 */
(void)osal_msg_send( sendMsgTo_TaskID, (uint8 *)pMsg );

(void)osal_msg_deallocate( (uint8 *)pMsg );

(void)osal_mem_free( pMsg->pData );

}
else
{
/* 释放消息 */
(void)osal_msg_deallocate( (uint8 *)pMsg );

(void)osal_mem_free( pMsg->pData );
}

/* 准备开始下一个数据包处理 */
sappPktState = SAPP_PARSER_STATE_PKT_TYPE;
}
}

break;

default:

break;
}
}
return;
}

/*********************************************************************
* @fn Send GATT Notification
*
* @brief 发送GATT通知
*
* @param OSAL定期调用该函数
* @param none
*
*
* @return none
*/

void SerialAppSendNotification(void)
{
uint8 i = 0;
static attHandleValueNoti_t *pReport= NULL;
static volatile uint16 counterOut=0;

if ( pReport == NULL)
{
pReport = packetDequeue();

if ( pReport == NULL )
{
return;
}
}

/* 每一个连接事件尝试发送3个package */
for ( i = 0; i<3 ; i++)
{
if ( GATT_Notification( 0, pReport, FALSE )==SUCCESS)
{
HalUARTWrite(SBP_UART_PORT, "DOUT:", 5);
++counterOut;
char hex[] = "0123456789";
char buf[4];
buf[0] = hex[counterOut/1000];
buf[1] = hex[counterOut%1000/100];
buf[2] = hex[counterOut%100/10];
buf[3] = hex[counterOut%10];
HalUARTWrite(SBP_UART_PORT, (uint8 *)buf, 4);
HalUARTWrite(SBP_UART_PORT, "\r\n", 2);
LCD_WRITE_STRING_VALUE( "DOUT ", ++counterOut, 10,2 );
pReport = packetDequeue();

if ( pReport == NULL )
{
i=3;
}

}
else
{
pReport = NULL;
i=3;
}
}
}


/*********************************************************************
* @fn SerialAppSendData
*
* @brief Send Gatt notifications
*
* @param pPkt - Gatt notification
* @param none
*
*
* @return none
*/

void SerialAppSendData2( sappExtCmd_t *pPkt )
{
static uint16 counter=0;

counter++;

attHandleValueNoti_t noti;
noti.len = pPkt->len;
noti.handle = 0;
osal_memcpy( &noti.value, &pPkt->pData[0], noti.len );

SerialAppEnqueue( &noti );

}

/*********************************************************************
* @fn SerialAppSendData
*
* @brief Send Gatt notifications
*
* @param pPkt - Gatt notification
* @param none
*
*
* @return none
*/

void SerialAppSendData1( sappDataPacket_t *pPkt )
{
static uint16 counter=0;

counter++;

attHandleValueNoti_t noti;
noti.len = pPkt->pktLen;
noti.handle = pPkt->connHandle;
osal_memcpy( &noti.value, &pPkt->pData[0], noti.len );

SerialAppEnqueue( &noti );

}


/*********************************************************************
* @fn SerialAPpEnqueue
*
* @brief Enqueue a report te be sent later
*
* @param pData
* @param none
*
*
* @return none
*/

static void SerialAppEnqueue( attHandleValueNoti_t *pData )
{
static volatile uint16 counterIn = 0;

/* 更新最后的索引 */
lastQIdx = ( lastQIdx + 1 ) % MAX_SAPP_NUM_ENTRIES;

if ( lastQIdx == firstQIdx )
{
/* 队列溢出 丢弃最旧的报告*/
firstQIdx = ( firstQIdx + 1 ) % MAX_SAPP_NUM_ENTRIES;
}

/* 存储为 Notification */
packetQ[lastQIdx].len =pData->len;
osal_memcpy( &packetQ[lastQIdx], pData, pData->len+3 );

HalUARTWrite(SBP_UART_PORT, "DIN:", 4);
++counterIn;
char hex[] = "0123456789";
char buf[4];
buf[0] = hex[counterIn/1000];
buf[1] = hex[counterIn%1000/100];
buf[2] = hex[counterIn%100/10];
buf[3] = hex[counterIn%10];
HalUARTWrite(SBP_UART_PORT, (uint8 *)buf, 4);
HalUARTWrite(SBP_UART_PORT, "\r\n", 2);

LCD_WRITE_STRING_VALUE( "DIN ", ++counterIn, 10,3 );

}

/*********************************************************************
* @fn packetDequeue
*
* @brief Dequeue a report to be sent out.
*
* @param none
* @param none
*
* @return None.
*/
static attHandleValueNoti_t *packetDequeue(void)
{
if ( reportQEmpty() )
{
return NULL;
}

/* 更新最先的索引 */
firstQIdx = ( firstQIdx + 1 ) % MAX_SAPP_NUM_ENTRIES;

return ( &(packetQ[firstQIdx]) );
}


头文件

#ifndef SERIALAPPUTIL_H
#define SERIALAPPUTIL_H

#ifdef __cplusplus
extern "C"
{
#endif

/* UART port */
#define SBP_UART_PORT HAL_UART_PORT_0
#define SBP_UART_FC FALSE
#define SBP_UART_FC_THRESHOLD 48
#define SBP_UART_RX_BUF_SIZE 128
#define SBP_UART_TX_BUF_SIZE 128
#define SBP_UART_IDLE_TIMEOUT 6
#define SBP_UART_INT_ENABLE TRUE
#define SBP_UART_BR HAL_UART_BR_57600


#define SAPP_EXT_LL_SUBGRP 0x00
#define SAPP_EXT_L2CAP_SUBGRP 0x01
#define SAPP_EXT_ATT_SUBGRP 0x02
#define SAPP_EXT_GATT_SUBGRP 0x03
#define SAPP_EXT_GAP_SUBGRP 0x04
#define SAPP_EXT_UTIL_SUBGRP 0x05
#define SAPP_EXT_PROFILE_SUBGRP 0x07

#define SAPP_EXT_UTIL_RESET 0x00
#define SAPP_EXT_UTIL_NV_READ 0x01
#define SAPP_EXT_UTIL_NV_WRITE 0x02
#define SAPP_EXT_UTIL_FORCE_BOOT 0x03


/* HCI - Messages IDs (0x90 - 0x9F) */
#define SAPP_DATA_EVENT 0x90 //!< HCI Data Event message
#define SAPP_GAP_EVENT_EVENT 0x91 //!< GAP Event message
#define SAPP_SMP_EVENT_EVENT 0x92 //!< SMP Event message
#define SAPP_EXT_CMD_EVENT 0x93 //!< HCI Extended Command Event message

/*
Minimum length for CMD packet is 1+2+1
| Packet Type (1) | OPCode(2) | Length(1) |
*/
#define SAPP_CMD_MIN_LENGTH 4

/*
Minimum length for DATA packet is 1+2+1
| Packet Type (1) | Handle(2) | Length(1) |
*/
#define SAPP_DATA_MIN_LENGTH 4

/* States for Command and Data packet parser */
#define SAPP_PARSER_STATE_PKT_TYPE 0

#define SAPP_CMD_PARSER_STATE_OPCODE 1
#define SAPP_CMD_PARSER_STATE_LENGTH 2
#define SAPP_CMD_PARSER_STATE_DATA 3
#define SAPP_DATA_PARSER_STATE_HANDLE 4
#define SAPP_DATA_PARSER_STATE_LENGTH 5
#define SAPP_DATA_PARSER_STATE_DATA 6

#define SAPP_OPCODE_CSG_LINK_LAYER 0
#define SAPP_OPCODE_CSG_CSG_L2CAP 1
#define SAPP_OPCODE_CSG_CSG_ATT 2
#define SAPP_OPCODE_CSG_CSG_GATT 3
#define SAPP_OPCODE_CSG_CSG_GAP 4
#define SAPP_OPCODE_CSG_CSG_SM 5
#define SAPP_OPCODE_CSG_CSG_Reserved 6
#define SAPP_OPCODE_CSG_CSG_USER_PROFILE 7

/* Vendor Specific OGF */
#define VENDOR_SPECIFIC_OGF 0x3F

/* Event Mask Default Values */
#define BT_EVT_MASK_BYTE0 0xFF
#define BT_EVT_MASK_BYTE1 0xFF
#define BT_EVT_MASK_BYTE2 0xFF
#define BT_EVT_MASK_BYTE3 0xFF
#define BT_EVT_MASK_BYTE4 0xFF
#define BT_EVT_MASK_BYTE5 0x9F
#define BT_EVT_MASK_BYTE6 0x00
#define BT_EVT_MASK_BYTE7 0x20

#define LE_EVT_MASK_DEFAULT 0x1F


/* SAPP Packet Types */
#define SAPP_CMD_PACKET 0x01
#define SAPP_ACL_DATA_PACKET 0x02
#define SAPP_SCO_DATA_PACKET 0x03
#define SAPP_EVENT_PACKET 0x04

/* Serial Events */
#define SAPP_CONTROLLER_TO_HOST_EVENT 0x01
#define SAPP_HOST_TO_CTRL_CMD_EVENT 0x02
#define SAPP_HOST_TO_CTRL_DATA_EVENT 0x04

#define SAPP_BDADDR_LEN 6


#if HAL_LCD == TRUE
#define LCD_WRITE_STRING(str, option) HalLcdWriteString( (str), (option))
#define LCD_WRITE_SCREEN(line1, line2) HalLcdWriteScreen( (line1), (line2) )
#define LCD_WRITE_STRING_VALUE(title, value, format, line) HalLcdWriteStringValue( (title), (value), (format), (line) )
#else
#define LCD_WRITE_STRING(str, option)
#define LCD_WRITE_SCREEN(line1, line2)
#define LCD_WRITE_STRING_VALUE(title, value, format, line)
#endif


typedef struct
{
uint8 pktType;
uint16 opCode;
uint8 len;
uint8 *pData;
} sappExtCmd_t;

typedef struct
{
osal_event_hdr_t hdr;
uint8 *pData;
} sappPacket_t;


typedef struct
{
osal_event_hdr_t hdr;
uint8 pktType;
uint16 connHandle;
uint8 pbFlag;
uint8 pktLen;
uint8 *pData;
} sappDataPacket_t;

extern void SerialApp_Init( uint8 taskID );
extern void SerialAppPacketParserCB( uint8 port, uint8 event );
extern void SerialAppInitTransport(void);
extern void SerialAppSendData1( sappDataPacket_t *pPkt );
extern void SerialAppSendData2( sappExtCmd_t *pMsg );
extern void SerialAppSendNotification(void);
extern void SerialAppSendOutUART( attHandleValueNoti_t *noti) ;
extern uint8 ProcessExtMsg1( sappDataPacket_t *pMsg );
extern uint8 ProcessExtMsg2( sappPacket_t *pMsg );

#ifdef __cplusplus
}
#endif

#endif

你好,并没有找到有本段代码。不过问题已经解决了,还是谢谢你。

非常感谢你的回复,我的问题已经间接的解决了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top