文章目录
- 前言
- 链接文件
- APP软件
- 检查预编程条件
- 停止DTC设置
- 禁止无关通讯
- 定义APP_INFO
- 调试输出
- hex处理
- 总结
前言
在之前的文章中,介绍了STM32 UDS Bootloader开发需求和bootloader软件开发的修改点。本文继续介绍APP软件关于UDS的部分。APP主要实现预编程阶段的部分内容。
链接文件
LR_IROM1 0x0800E000 0x00032000 { ; load region size_regionER_IROM1 0x0800E000 0x00032000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x0000BFF0 { ; RW data.ANY (+RW +ZI)}RW_IRAM2 0x2000BFF0 UNINIT 0x00000010 {.ANY (+RW +ZI)}
}LR_IROM2 0x0800D800 0x0000800 { ; load region size_regionER_IROM2 0x0800D800 0x0000800 { ; load address = execution address*(.APP_INFO) .ANY (+RO).ANY (+XO)}}
此处按需求定义APP_INFO的flash区域为起始地址0x0800D800,大小0x800。
RW_IRAM2区域定义UNINIT,保证在APP跳boot复位后,对应ram区域的内容不被初始化
APP软件
检查预编程条件
static void RoutineControl(struct UDSServiceInfo *i_pstUDSServiceInfo, tUdsAppMsgInfo *m_pstPDUMsg)
{uint8 Ret = FALSE;uint32 ReceivedCrc = 0u;ASSERT(NULL_PTR == m_pstPDUMsg);ASSERT(NULL_PTR == i_pstUDSServiceInfo);RestartS3Server();if(TRUE == IsCheckPreProgrammingCondition(m_pstPDUMsg)){m_pstPDUMsg->aDataBuf[0u] = i_pstUDSServiceInfo->SerNum + 0x40u;m_pstPDUMsg->xDataLen = 4u;}#ifdef UDS_PROJECT_FOR_BOOTLOADER/* Is erase memory routine control? */else if (TRUE == IsEraseMemoryRoutineControl(m_pstPDUMsg)){/* Request client timeout time */SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SERVICE_BUSY, m_pstPDUMsg);m_pstPDUMsg->pfUDSTxMsgServiceCallBack = &DoEraseFlash;}/* Is check sum routine control? */else if (TRUE == IsCheckSumRoutineControl(m_pstPDUMsg)){ReceivedCrc = m_pstPDUMsg->aDataBuf[4u];ReceivedCrc = (ReceivedCrc << 8u) | m_pstPDUMsg->aDataBuf[5u];/* TODO Bootloader: #04 SID_31 Uncomment this 2 lines when CRC32 used */#ifdef EN_CRC32_SOFTWAREReceivedCrc = (ReceivedCrc << 8u) | m_pstPDUMsg->aDataBuf[6u];ReceivedCrc = (ReceivedCrc << 8u) | m_pstPDUMsg->aDataBuf[7u];#endifFlash_SavedReceivedCheckSumCrc(ReceivedCrc);/* Request client timeout time */SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SERVICE_BUSY, m_pstPDUMsg);m_pstPDUMsg->pfUDSTxMsgServiceCallBack = &DoCheckSum;}/* Is check programming dependency? */else if (TRUE == IsCheckProgrammingDependency(m_pstPDUMsg)){/* Write application information in flash. */(void)Flash_WriteFlashAppInfo();/* Do check programming dependency */Ret = DoCheckProgrammingDependency();if (TRUE == Ret){m_pstPDUMsg->aDataBuf[0u] = i_pstUDSServiceInfo->SerNum + 0x40u;m_pstPDUMsg->xDataLen = 4u;}else{/* Don't have this routine control ID */SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SUBFUNCTION_NOT_SUPPORTED, m_pstPDUMsg);}}#endifelse{/* Don't have this routine control ID */SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SUBFUNCTION_NOT_SUPPORTED, m_pstPDUMsg);}
}
此处正常检查预编程条件应该判断车速,蓄电池电压这些,这里直接返回的true.
停止DTC设置
static void ControlDTCSetting(struct UDSServiceInfo *i_pstUDSServiceInfo, tUdsAppMsgInfo *m_pstPDUMsg)
{uint8 RequestSubfunction = 0u;ASSERT(NULL_PTR == m_pstPDUMsg);ASSERT(NULL_PTR == i_pstUDSServiceInfo);RequestSubfunction = m_pstPDUMsg->aDataBuf[1u];switch (RequestSubfunction){case 0x01u :case 0x02u :m_pstPDUMsg->aDataBuf[0u] = i_pstUDSServiceInfo->SerNum + 0x40u;m_pstPDUMsg->aDataBuf[1u] = RequestSubfunction;m_pstPDUMsg->xDataLen = 2u;break;case 0x81u :case 0x82u :m_pstPDUMsg->xDataLen = 0u;break;default :SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SUBFUNCTION_NOT_SUPPORTED, m_pstPDUMsg);break;}
}
此处正常应该调用停止DTC诊断的API函数,本APP没有做诊断,所以没有,直接返回的true
禁止无关通讯
static void CommunicationControl(struct UDSServiceInfo *i_pstUDSServiceInfo, tUdsAppMsgInfo *m_pstPDUMsg)
{uint8 RequestSubfunction = 0u;ASSERT(NULL_PTR == m_pstPDUMsg);ASSERT(NULL_PTR == i_pstUDSServiceInfo);RequestSubfunction = m_pstPDUMsg->aDataBuf[1u];switch (RequestSubfunction){case 0x0u :case 0x03u :m_pstPDUMsg->aDataBuf[0u] = i_pstUDSServiceInfo->SerNum + 0x40u;m_pstPDUMsg->aDataBuf[1u] = RequestSubfunction;m_pstPDUMsg->xDataLen = 2u;break;case 0x80u :case 0x83u :/* Don't transmit UDS message. */m_pstPDUMsg->aDataBuf[0u] = 0u;m_pstPDUMsg->xDataLen = 0u;break;default :SetNegativeErroCode(i_pstUDSServiceInfo->SerNum, NRC_SUBFUNCTION_NOT_SUPPORTED, m_pstPDUMsg);break;}
}
此处应该停止发送应用报文和网络管理报文,本APP没有其他报文发送,此处直接返回true
定义APP_INFO
__attribute__((used)) __attribute__((section (".APP_INFO"))) const tAppFlashStatus gs_stAppFlashStatusInfo =
{.appStartAddr = APP_A_START_ADDR,.isFlashErasedSuccessfull = 0x00,.isFlashProgramSuccessfull = 0x00,.isFlashStructValid = 0x00,
};
定义该flash区域为APP_INFO,配置appStartAddr为0x0800E000.
调试输出
为了确认BOOT和APP跳转是否成功,设置了Bootloader软件中LED1闪烁,APP软件中LED0闪烁
boolean TIMER_HAL_Is100msTickTimeout(void)
{boolean result = FALSE;if (gs_100msCnt >= 1000u){result = TRUE;gs_100msCnt -= 1000u;#ifdef UDS_PROJECT_FOR_APPLED0=!LED0;#endif}timerTickCnt++;return result;
}
hex处理
此处编译出来hex有两块
使用hexview+bat脚本填充间隔
..\..\..\HexTools\hexview.exe /G /s .\STM32_UDS_APP.hex /S /FA: /AF:0xFF /XI:32 -o STM32_UDS_APP_Fill.hex /e:errorfile
创建单个区域文件(/FA)
此选项可用于创建单个块文件。在这种情况下,HexView将使用第一个块的起始地址和最后一个块的结束地址,并使用/AFxx参数给定的填充字符填充其间的所有剩余byte。
/AF:0xFF表示填充使用0xFF
/XI:32指定输出行的字节数为32
总结
到此,APP软件开发就完成了。后面有时间会介绍上位机的开发
丐版刷写界面如下: