前言
在之前的文章中,介绍了STM32 UDS Bootloader开发需求和bootloader软件开发的修改点。本文继续介绍APP软件关于UDS的部分。APP主要实现预编程阶段的部分内容。
链接文件
LR_IROM1 0x0800E000 0x00032000 { ; load region size_region
ER_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_region
ER_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_SOFTWARE
ReceivedCrc = (ReceivedCrc << 8u) | m_pstPDUMsg->aDataBuf[6u];
ReceivedCrc = (ReceivedCrc << 8u) | m_pstPDUMsg->aDataBuf[7u];
#endif
Flash_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);
}
}
#endif
else
{
/* 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_APP
LED0=!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软件开发就完成了。后面有时间会介绍上位机的开发
丐版刷写界面如下:文章来源:https://www.toymoban.com/news/detail-513468.html
文章来源地址https://www.toymoban.com/news/detail-513468.html
到了这里,关于STM32 UDS Bootloader开发-下位机篇-App软件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!