首页
社区
课程
招聘
[原创]修改某款lora固件库以支持接收错误数据包
2019-5-23 20:51 10633

[原创]修改某款lora固件库以支持接收错误数据包

2019-5-23 20:51
10633

LoRa 固件

目前有一个 需求,为了研究lora 在不同干扰情况下数据包字节错误的情况,我必须将错误的数据包也记录下来,即没有通过CRC校验的数据包。但是现有的lora固件,会直接将没有通过CRC的数据包丢弃,无法查看错误的情况。因此,有了这个记录。

针对的芯片

研究的是lora 2.4的通信,因此针对的芯片是sx1280的,这里就不把集成了该芯片的厂商说出来了。下面主要介绍一些思路。
整体过程为:

  1. 提取共享库
  2. 结合网上开源的代码,找到关键位置,思考修改的方案
  3. 找到最优的修改方案,执行修改,并重新打包测试。

提取共享库

厂商提供的是一个封装起来的LIB库,利用ubuntu 的file工具发现是一个AR格式的打包文件,搜索的解包的方式:(参考AR解压缩

 

ar x name.lib

修改之后,可以用下面的方式打包回来:

ar cr dest.lib src1.o src2.o src3.o

其中后面的src1.o src2.o src3.o就是共享库。dest.lib是最终打包的文件名。

 

之后,我发现其中的sx1280.0的库比较关键,就尝试专注分析该库。
还有另外两个厂商提供的封装库,提供了一些MAC层的操作。这里就叫manufactory.o.

找到关键位置

我初步分析时,首先尝试分析manufactory.o.里面和MAC消息有关的操作。
我分析到两个关键的位置,1,正确接收到lora的消息时的操作

else if ( a2 & 0x40 ) 
   clear_event((unsigned __int8)s_phy_layer_task_id, 4);
    stop_timerEx((unsigned __int8)s_phy_layer_task_id, 4);
radio_raw_data = (unsigned __int8 *)msg_allocate(255);
    if ( radio_raw_data )
    {
      *(_DWORD *)radio_raw_data_len = 0;
      SX1280Hal::SetDirDisable((SX1280Hal *)&Radio);
      clear_event((unsigned __int8)s_phy_layer_task_id, 76);
      SX1280::GetPayload((SX1280 *)&Radio, radio_raw_data, radio_raw_data_len, 0xFFu);
      SX1280::GetPacketStatus(&Radio, &PacketStatus);
      SX1280Hal::SetDirEnable((SX1280Hal *)&Radio);
     }

可以发现几个关键的步骤就是利用SX1280的库来获取payload并且存储起来。
另一个方面,我发现了几个处理lora接收错误情况的流程:

else if ( !s_PeriodBaseCount_flag )
        {
          SetRcMode();
          send_cmd(9u);               // RX_ERROR_CMD
        }
 else if ( a2 & 8 )                            // SAMPLE_MSG_RX_TIMEOUT_EVNT
  {
    clear_event((unsigned __int8)s_phy_layer_task_id, 4);
    stop_timerEx((unsigned __int8)s_phy_layer_task_id, 4);
    if ( s_tx_confirm_flag == 1 )
    {
      s_tx_confirm_flag = 0;
      v24 = msg_allocate(32);
      if ( v24 )
      {
        *(_BYTE *)v24 = 2;
        *(_BYTE *)(v24 + 2) = 6;                // MAC_EVENT_TX_TIMEOUT_CMD
        *(_BYTE *)(v24 + 3) = s_phy_layer_task_id;
        *(_BYTE *)(v24 + 4) = Radio_packet_type;
        *(_DWORD *)(v24 + 28) = 0;
        *(_DWORD *)(v24 + 24) = 0;
        msg_send((unsigned __int8)g_sample_task_id, v24);
      }
    }
    else
    {
      v25 = msg_allocate(32);
      if ( v25 )
      {
        *(_BYTE *)v25 = 2;
        *(_BYTE *)(v25 + 2) = 9;                // MAC_EVNT_RX_ERROR_CMD
        *(_BYTE *)(v25 + 3) = s_phy_layer_task_id;
        *(_BYTE *)(v25 + 4) = Radio_packet_type;
        *(_DWORD *)(v25 + 28) = 0;
        *(_DWORD *)(v25 + 24) = 0;
        msg_send((unsigned __int8)g_sample_task_id, v25);
      }
    }
    result = v4 ^ 8;
  }

,那么基本的思路,就是在上述所有反馈了lora rx error的地方,仍然将上述SX1280获取和拷贝数据的操作添加在逻辑里面。但是操作起来很复杂,拷贝payload的汇编代码整理一下有这些。而且对于某些条件跳转的地址,还得仔细的修改:

MOVS    R1, #4
LDR     R0, =s_phy_layer_task_id
LDRB    R0, [R0]
BL      osal_clear_event
MOVS    R1, #4
LDR     R0, =s_phy_layer_task_id
LDRB    R0, [R0]
BL      osal_stop_timerEx
MOVS    R0, #0xFF
BL      osal_msg_allocate
MOV     R9, R0
CMP.W   R9, #0
BEQ     loc_123C
MOVS    R0, #0
STR     R0, [SP,#0x28+radio_raw_data_len]
LDR     R0, =Radio      ; this
BL      _ZN9SX1280Hal13SetDirDisableEv ; SX1280Hal::SetDirDisable(void)
MOVS    R1, #0x4C ; 'L'
LDR     R0, =s_phy_layer_task_id
LDRB    R0, [R0]
BL      osal_clear_event
MOVS    R3, #0xFF       ; unsigned __int8
ADD     R2, SP, #0x28+radio_raw_data_len ; unsigned __int8 *
MOV     R1, R9          ; unsigned __int8 *
LDR     R0, =Radio      ; this
BL      _ZN6SX128010GetPayloadEPhS0_h ; SX1280::GetPayload(uchar *,uchar *,uchar)
LDR     R1, =PacketStatus
LDR     R0, =Radio
BL      _ZN6SX128015GetPacketStatusEP14PacketStatus_t ; SX1280::GetPacketStatus(PacketStatus_t *)
LDR     R0, =Radio      ; this
BL      _ZN9SX1280Hal12SetDirEnableEv ; SX1280Hal::SetDirEnable(void)

看到上述都是基于sx1280的操作,那么我想能不能直接在sx1280找到一些突破口。
然后发现sx1280的库实现时开源的。sx1280
这是非常幸运的。我直接就搜索CRC有关的位置,发现在SX1280::ProcessIrqs( void )的这个函数里面,有这样一个逻辑:

if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
    {
        if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )// 如果收到底层CRC不通过的ERROR,就向上层汇报IRQ_CRC_ERROR_CODE。那么MAC层就会根据这个error进行相应的处理,也即是上面看到的丢包处理。理论上,我们只要使得该语句永远为False就会一直跳转到下面的rxDone中,始终汇报数据包接收成功即可。
        {
            if( rxError != NULL )
            {
                rxError( IRQ_CRC_ERROR_CODE );
            }
        }
        else
        {
            if( rxDone != NULL ) //这条基本都会true,因为rxDone是一个指针函数。
            {
                rxDone( );
            }
        }
    }

正如代码中分析的,只要if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )永远为真,那么就可以上报数据包成功接收消息,那么就可以把错误的数据包保留。
如果收到底层CRC不通过的ERROR,就向上层汇报IRQ_CRC_ERROR_CODE。那么MAC层就会根据这个error进行相应的处理,也即是上面看到的丢包处理。理论上,我们只要使得该语句永远为False就会一直跳转到下面的rxDone中,始终汇报数据包接收成功即可。

最优方案的选择,修改测试

我们发现,直接修改sx1280是最简单的。
在这里插入图片描述
在0x228的代码位置,如果上述比较不等于0才会跳转执行下面的0x238的操作,即rxDone操作。因此,只要将BNE loc_238修改成无条件跳转B loc_238即可。汇编中D1是BNE跳转,E0是无条件跳转即B。因此在对应位置如下修改:
在这里插入图片描述
修改的工具路径是:edit->patch program->change byte,(IDA pro 7.0)。
修改完之后,再看看程序逻辑已经被修改:
在这里插入图片描述
因此,我们修改一个字节就能够达到效果了。
保存修改。edit->patch program-> apply patched to input file ,就可以保存修改了。
再重新利用AR打包回来,测试效果。
发现错误的数据包也可以接受了。

 

本文仅供学习交流,如作他用所承受的法律责任一概与作者无关。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-5-28 10:30 被二当家a编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (13)
雪    币: 32410
活跃值: (18720)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2019-5-26 21:48
2
0
图片丢失了,希望能补上。
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2019-5-28 10:33
3
0
kanxue 图片丢失了,希望能补上。
ok.已更正
雪    币: 11
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
誰源 2020-1-14 16:01
4
0
大佬可以加个好友不,我最近在调试1280发现资料较少而且第一次接触lora模块,有一些疑惑很想向你请教。
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2020-1-15 10:40
5
0
誰源 大佬可以加个好友不,我最近在调试1280发现资料较少而且第一次接触lora模块,有一些疑惑很想向你请教。[em_51]
恩,可以看我的主页发邮件。
雪    币: 11
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
誰源 2020-1-15 15:01
6
0
二当家a 恩,可以看我的主页发邮件。
我还是LV1,我在想要怎么升级= =
其实我就想问问如果想用1280的lora模块进行通讯,初始配置有哪些是必须的?
我这样配顺序是对的么?我就想模式是0xff一个一直发,一个一直收。
用的是STM32,引脚,SPI都设置好了,就是1280的设置流程不是很明白,有是有官方的demo,不过我用的是标准库不是hal库所以就比较麻烦
1:RADIO_nRESET_PIN 0→1
2:SX1280SetRegulatorMode(USE_DCDC);
3:modulationParams.PacketType = PACKET_TYPE_LORA;这个是Lora的配置4+6行的
接下来就不是很懂了,大概理解是这样设置
4:
       SX1280SetStandby( STDBY_RC );
        SX1280SetPacketType

       SX1280SetRfFrequency( );
       SX1280SetBufferBaseAddresses( 0x00, 0x00 );← 这个看手册,睡眠后保留信息好像要设置(0x80,0x00)还是倒过来不过我先测试一个收发所以就都设置0x00了
       SX1280SetPayload( Buffer, BufferSize );
       SetRx( RX_TX_CONTINUOUS);
这样对么?我感觉应该缺少了一些配置,我邮箱是suyf@live.com,实在抱歉打扰你,先谢谢大佬了
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2020-1-15 15:40
7
0
誰源 我还是LV1,我在想要怎么升级= = 其实我就想问问如果想用1280的lora模块进行通讯,初始配置有哪些是必须的? 我这样配顺序是对的么?我就想模式是0xff一个一直发,一个一直收。 用的是S ...
好,邮箱回复你了。
雪    币: 5325
活跃值: (206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
w霸气侧漏 2020-2-11 09:31
8
0
大神  
话说mdk生成的lib文件要怎么弄成C呢
ubuntu 的file工具有什么作用
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2020-2-11 10:25
9
0
w霸气侧漏 大神 话说mdk生成的lib文件要怎么弄成C呢 ubuntu 的file工具有什么作用
"话说mdk生成的lib文件要怎么弄成C呢"-> 不太懂表达的意思,你是说反编译成C吗?
file是查看文件类型相关信息的。
雪    币: 5325
活跃值: (206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
w霸气侧漏 2020-2-12 15:40
10
0
二当家a "话说mdk生成的lib文件要怎么弄成C呢"-> 不太懂表达的意思,你是说反编译成C吗? file是查看文件类型相关信息的。
对的   想把lib生成C语言    Cortex-M内核的单片机上面用的  ide是mdk  keil
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2020-2-13 09:55
11
0
w霸气侧漏 对的 想把lib生成C语言 Cortex-M内核的单片机上面用的 ide是mdk keil
直接 IDA f5一梭子?
雪    币: 5325
活跃值: (206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
w霸气侧漏 2020-2-14 08:40
12
0
二当家a 直接 IDA f5一梭子?
也行  不错这个准确度不高
雪    币: 5911
活跃值: (1641)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
二当家a 2 2020-2-14 09:45
13
0
w霸气侧漏 也行 不错这个准确度不高
自动+手动结合呗。
雪    币: 5325
活跃值: (206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
w霸气侧漏 2020-2-18 09:06
14
0
二当家a 自动+手动结合呗。
也只能这样  用汇编来弄
游客
登录 | 注册 方可回帖
返回