我把ieee802154的通信例程移植到RT_Thread操作系统,在接收回调函数中使用RTT的信号量通知对接收的数据帧进行处理,发送端每几秒发送一次数据,然后发现接收端每接收几次都可能会报错Instruction access fault并重启。报错重启的位置都在debug_print_packet中。请问是什么原因?
报错如下:
[10:23:22.552]收←◆Guru Meditation Error: Core 0 panic'ed (Instruction access fault). Exception was unhandled.
Core 0 register dump:
MEPC : 0x00000080 RA : 0x40022d60 SP : 0x408157c0 GP : 0x40804dd0
TP : 0xdeadbeef T0 : 0x00000080 T1 : 0x10000000 T2 : 0xdeadbeef
S0/FP : 0x40835464 S1 : 0x00000041 A0 : 0x00000000 A1 : 0x00000035
A2 : 0x40835424 A3 : 0x00000041 A4 : 0x00000001 A5 : 0x00000000
A6 : 0xa0000000 A7 : 0x0000000a S2 : 0x40835465 S3 : 0x40835424
S4 : 0x40815960 S5 : 0x00000001 S6 : 0x42041a3f S7 : 0x00000000
S8 : 0x00000001 S9 : 0x00000000 S10 : 0x40815974 S11 : 0x00000002
T3 : 0x00000000 T4 : 0x00006f48 T5 : 0x00000050 T6 : 0xdeadbeef
MSTATUS : 0x00001880 MTVEC : 0x40800001 MCAUSE : 0x00000001 MTVAL : 0x00000080
MHARTID : 0x00000000
代码如下:
/*
这个例子是基于ieee802154的点对点通信(接收端)
*/
#include <string.h>
#include <esp_ieee802154.h>
#include <esp_log.h>
#include "rtthread.h"
#include "802154_proto.h"
#define RADIO_TAG "main"
#define PANID 0x4242
#define CHANNEL 19
#define SHORT_NOT_CONFIGURED 0xFFFE
#define SHORT_TEST_RECEIVER 0x2222
static rt_thread_t tid1 = RT_NULL;
static struct rt_semaphore sem;
static uint8_t shared_frame[257]; // 共享缓冲区,用于存储接收到的帧
static void debug_handler_task(void *parameter);
static void debug_print_packet(uint8_t *packet, uint8_t packet_length);
/*********************************
函数名:esp_ieee802154_receive_done
函数功能:接收回调函数,当接收到一个帧时调用
**********************************/
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info)
{
ESP_EARLY_LOGI(RADIO_TAG, "rx OK, received %d bytes", frame[0]);
for (uint8_t idx = 1; idx < frame[0]; idx += 8)
{
ESP_EARLY_LOGI(RADIO_TAG, "%02x %02x %02x %02x %02x %02x %02x %02x",
frame[idx], frame[idx + 1], frame[idx + 2], frame[idx + 3],
frame[idx + 4], frame[idx + 5], frame[idx + 6], frame[idx + 7]);
}
// 将接收到的帧存储到共享缓冲区
memcpy(shared_frame, frame, frame[0] + 1);
// 通过信号量通知线程处理数据
rt_sem_release(&sem);
esp_ieee802154_receive_handle_done(frame);
}
/*********************************
函数名:esp_ieee802154_receive_failed
函数功能:接收回调函数,当接收失败时调用
**********************************/
void esp_ieee802154_receive_failed(uint16_t error)
{
ESP_EARLY_LOGI(RADIO_TAG, "rx failed, error %d", error);
}
/*********************************
函数名:esp_ieee802154_receive_sfd_done
函数功能:接收回调函数,当接收到SFD时调用
**********************************/
void esp_ieee802154_receive_sfd_done(void)
{
ESP_EARLY_LOGI(RADIO_TAG, "rx sfd done, Radio state: %d", esp_ieee802154_get_state());
}
int main(void)
{
// 初始化信号量
static rt_err_t result ;
result = rt_sem_init(&sem, "sem", 0, RT_IPC_FLAG_PRIO);
if (result != RT_EOK)
{
rt_kprintf("init semaphore failed.\n");
}
tid1 = rt_thread_create("debug_handler_task",debug_handler_task, RT_NULL,4096,25, 5);
/* 如果获得线程控制块,启动这个线程 */
if (tid1 != RT_NULL)
{rt_thread_startup(tid1);}
ESP_LOGI(TAG, "start");
ESP_ERROR_CHECK(esp_ieee802154_enable());
ESP_ERROR_CHECK(esp_ieee802154_set_coordinator(false));
ESP_ERROR_CHECK(esp_ieee802154_set_promiscuous(false));
ESP_ERROR_CHECK(esp_ieee802154_set_rx_when_idle(true));
// esp_ieee802154_set_extended_address needs the MAC in reversed byte order
uint8_t eui64[8] = {0};
esp_read_mac(eui64, ESP_MAC_IEEE802154);
uint8_t eui64_rev[8] = {0};
for (int i = 0; i < 8; i++)
{
eui64_rev[7 - i] = eui64;
}
esp_ieee802154_set_extended_address(eui64_rev);
esp_ieee802154_set_short_address(SHORT_TEST_RECEIVER);
ESP_ERROR_CHECK(esp_ieee802154_set_panid(PANID));
ESP_ERROR_CHECK(esp_ieee802154_set_channel(CHANNEL));
ESP_ERROR_CHECK(esp_ieee802154_receive());
uint8_t extended_address[8];
esp_ieee802154_get_extended_address(extended_address);
ESP_LOGI(TAG, "Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x",
esp_ieee802154_get_panid(), esp_ieee802154_get_channel(),
extended_address[0], extended_address[1], extended_address[2], extended_address[3],
extended_address[4], extended_address[5], extended_address[6], extended_address[7],
esp_ieee802154_get_short_address());
// All done, the rest is up to handlers
while (true)
{
rt_thread_mdelay(2000);
}
}
/*********************************
函数名:debug_handler_task
函数功能:一个线程任务,它从消息队列中接收数据包
**********************************/
static void debug_handler_task(void *parameter)
{
static rt_err_t result;
while (1)
{
// 等待信号量
result = rt_sem_take(&sem, RT_WAITING_FOREVER);
if ( result == RT_EOK)
{
// 处理共享缓冲区中的数据
debug_print_packet(&shared_frame[1], shared_frame[0]);
}
}
}
static void debug_print_packet(uint8_t *packet, uint8_t packet_length)
{
if (packet_length < sizeof(mac_fcs_t))
return; // Can't be a packet if it's shorter than the frame control field
uint8_t position = 0;
mac_fcs_t *fcs = (mac_fcs_t *)&packet[position];
position += sizeof(uint16_t);
ESP_LOGI(RADIO_TAG, "Frame type: %x", fcs->frameType);
ESP_LOGI(RADIO_TAG, "Security Enabled: %s", fcs->secure ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Frame pending: %s", fcs->framePending ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Acknowledge request: %s", fcs->ackReqd ? "True" : "False");
ESP_LOGI(RADIO_TAG, "PAN ID Compression: %s", fcs->panIdCompressed ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Reserved: %s", fcs->rfu1 ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Sequence Number Suppression: %s", fcs->sequenceNumberSuppression ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Information Elements Present: %s", fcs->informationElementsPresent ? "True" : "False");
ESP_LOGI(RADIO_TAG, "Destination addressing mode: %x", fcs->destAddrType);
ESP_LOGI(RADIO_TAG, "Frame version: %x", fcs->frameVer);
ESP_LOGI(RADIO_TAG, "Source addressing mode: %x", fcs->srcAddrType);
if (fcs->rfu1)
{
ESP_LOGE(RADIO_TAG, "Reserved field 1 is set, ignoring packet");
return;
}
switch (fcs->frameType)
{
case FRAME_TYPE_BEACON:
{
ESP_LOGI(RADIO_TAG, "Beacon");
break;
}
case FRAME_TYPE_DATA:
{
uint8_t sequence_number = packet[position];
position += sizeof(uint8_t);
ESP_LOGI(RADIO_TAG, "Data (%u)", sequence_number);
uint16_t pan_id = 0;
uint8_t dst_addr[8] = {0};
uint8_t src_addr[8] = {0};
uint16_t short_dst_addr = 0;
uint16_t short_src_addr = 0;
bool broadcast = false;
switch (fcs->destAddrType)
{
case ADDR_MODE_NONE:
{
ESP_LOGI(RADIO_TAG, "Without PAN ID or address field");
break;
}
case ADDR_MODE_SHORT:
{
pan_id = *((uint16_t *)&packet[position]);
position += sizeof(uint16_t);
short_dst_addr = *((uint16_t *)&packet[position]);
position += sizeof(uint16_t);
if (pan_id == 0xFFFF && short_dst_addr == 0xFFFF)
{
broadcast = true;
pan_id = *((uint16_t *)&packet[position]); // srcPan
position += sizeof(uint16_t);
ESP_LOGI(RADIO_TAG, "Broadcast on PAN %04x", pan_id);
}
else
{
ESP_LOGI(RADIO_TAG, "On PAN %04x to short address %04x", pan_id, short_dst_addr);
}
break;
}
case ADDR_MODE_LONG:
{
pan_id = *((uint16_t *)&packet[position]);
position += sizeof(uint16_t);
for (uint8_t idx = 0; idx < sizeof(dst_addr); idx++)
{
dst_addr[idx] = packet[position + sizeof(dst_addr) - 1 - idx];
}
position += sizeof(dst_addr);
ESP_LOGI(RADIO_TAG, "On PAN %04x to long address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", pan_id, dst_addr[0],
dst_addr[1], dst_addr[2], dst_addr[3], dst_addr[4], dst_addr[5], dst_addr[6], dst_addr[7]);
break;
}
default:
{
ESP_LOGE(RADIO_TAG, "With reserved destination address type, ignoring packet");
return;
}
}
switch (fcs->srcAddrType)
{
case ADDR_MODE_NONE:
{
ESP_LOGI(RADIO_TAG, "Originating from the PAN coordinator");
break;
}
case ADDR_MODE_SHORT:
{
short_src_addr = *((uint16_t *)&packet[position]);
position += sizeof(uint16_t);
ESP_LOGI(RADIO_TAG, "Originating from short address %04x", short_src_addr);
break;
}
case ADDR_MODE_LONG:
{
for (uint8_t idx = 0; idx < sizeof(src_addr); idx++)
{
src_addr[idx] = packet[position + sizeof(src_addr) - 1 - idx];
}
position += sizeof(src_addr);
ESP_LOGI(RADIO_TAG, "Originating from long address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", src_addr[0], src_addr[1],
src_addr[2], src_addr[3], src_addr[4], src_addr[5], src_addr[6], src_addr[7]);
break;
}
default:
{
ESP_LOGE(RADIO_TAG, "With reserved source address type, ignoring packet");
return;
}
}
uint8_t *header = &packet[0];
uint8_t header_length = position;
uint8_t *data = &packet[position];
uint8_t data_length = packet_length - position - sizeof(uint16_t);
position += data_length;
ESP_LOGI(RADIO_TAG, "Data length: %u", data_length);
uint16_t checksum = *((uint16_t *)&packet[position]);
ESP_LOGI(RADIO_TAG, "Checksum: %04x", checksum);
ESP_LOGI(RADIO_TAG, "PAN %04x S %04x %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X to %04x %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X %s", pan_id,
short_src_addr, src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5], src_addr[6], src_addr[7],
short_dst_addr, dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3], dst_addr[4], dst_addr[5], dst_addr[6], dst_addr[7],
broadcast ? "BROADCAST" : "");
if (broadcast)
for (uint8_t idx = 0; idx < 8; idx++)
dst_addr[idx] = 0xFF;
break;
}
case FRAME_TYPE_ACK:
{
uint8_t sequence_number = packet[position++];
ESP_LOGI(RADIO_TAG, "Ack (%u)", sequence_number);
break;
}
default:
{
ESP_LOGE(RADIO_TAG, "Packet ignored because of frame type (%u)", fcs->frameType);
break;
}
}
ESP_LOGI(RADIO_TAG, "-----------------------");
}
ieee802154通信报错Instruction access fault
Who is online
Users browsing this forum: No registered users and 3 guests