#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#define SBL_SUCCESS 0
#define SBL_ERROR 1
#define SBL_CC2650_MAX_BYTES_PER_TRANSFER 254
#define SBL_CC2650_BL_CONFIG_ENABLED_BM 0xFF
// 定义一个结构体来存储数据传输的详情
typedef struct {
uint32_t startAddr;
uint32_t byteCount;
uint32_t startOffset;
bool bExpectAck;
} tTransfer;
// 函数原型声明
uint32_t getBootloaderEnableAddress() {
// 此函数应返回引导加载程序启用地址的值,这里是一个占位实现
return 0x0000FFFF;
}
void setState(uint32_t code, const char *message, …) {
// 该函数应该设置状态并可能打印消息,这里是一个占位实现
va_list args;
va_start(args, message);
vprintf(message, args);
va_end(args);
}
uint32_t cmdDownload(uint32_t address, uint32_t byteCount) {
// 此函数应该发送一个下载命令,这里是一个占位实现
return SBL_SUCCESS;
}
uint32_t readStatus(uint32_t *status) {
// 此函数应读取设备状态,这里是一个占位实现
*status = SBL_SUCCESS;
return SBL_SUCCESS;
}
const char* getCmdStatusString(uint32_t status) {
// 此函数应返回状态字符串,这里是一个占位实现
return “Success”;
}
void setProgress(uint32_t progress) {
// 此函数应设置进度,这里是一个占位实现
printf(“Progress: %d%%\n”, progress);
}
uint32_t cmdSendData(const char* data, uint32_t byteCount) {
// 此函数应发送数据,这里是一个占位实现
return SBL_SUCCESS;
}
uint32_t addressToPage(uint32_t address) {
// 此函数应返回地址所在的页码,这里是一个占位实现
return address / 4096; // 假设页大小为4096字节
}
// 主函数
uint32_t writeFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount, const char *pcData) {
// … 与之前的代码相同 …
// (从这里继续)计算BL配置地址(取决于flash大小)
uint32_t ui32BlCfgAddr = getBootloaderEnableAddress();
// 计算BL配置缓冲区索引
uint32_t ui32BlCfgDataIdx = ui32BlCfgAddr - ui32StartAddress;
// BL配置是否为缓冲区的一部分?
if(ui32BlCfgDataIdx <= ui32ByteCount) {
if((pcData[ui32BlCfgDataIdx] & 0xFF) != SBL_CC2650_BL_CONFIG_ENABLED_BM) {
bBlToBeDisabled = true;
setState(SBL_SUCCESS, "Warning: Bootloader will be disabled.\n");
}
}
// 如果BL被禁用,则分为两次传输
if(bBlToBeDisabled) {
// ... 与之前的代码相同 ...
} else {
// ... 与之前的代码相同 ...
}
// 对每个传输进行循环
for(uint32_t i = 0; i < (bBlToBeDisabled ? 2 : 1); i++) {
// ... 与之前的代码相同 ...
}
return SBL_SUCCESS;
}
// 主函数的测试
int main() {
char data[500]; // 假设有500个字节的数据
writeFlashRange(0x0000, 500, data);
return 0;
}
在原始代码中,我们可以看到根据特定的条件创建了一个或两个传输。这与引导加载程序(bootloader)配置区域是否被写入有关。
这里是一些关键点和逻辑的详细解释:
Bootloader Configuration Address(引导加载程序配置地址): 这是一个特殊的地址,其中存储了有关引导加载程序的配置信息。在我们的案例中,它通过getBootloaderEnableAddress函数获得。
Check for Bootloader Disabling(检查是否禁用引导加载程序): 代码首先检查是否正在尝试更改引导加载程序的配置。如果是,它将发出警告,因为这通常是一个危险的操作,可能会使设备无法再次启动。
Creating Transfers(创建传输):
如果尝试更改引导加载程序配置(禁用它),代码将创建两个传输:
第一个传输将写入直到引导加载程序配置地址的所有数据(不包括该地址)。
第二个传输将专门用于写入引导加载程序配置地址,且不期望收到确认。
如果不更改引导加载程序配置,代码将创建一个传输,其中包含所有要写入的数据,而不会分开处理引导加载程序配置数据。
这样做的目的是,如果引导加载程序配置正在更改(即,它被禁用),它被视为一个特殊的情况,并且需要单独处理,以避免不必要的错误或问题。它也提供了一种机制,以在不触及引导加载程序配置的情况下安全地写入数据。
段代码的主要目的是检查是否正在尝试修改引导加载程序的配置。让我们一步一步地分解这段代码来理解它的工作原理:
if(ui32BlCfgDataIdx <= ui32ByteCount)
这一行代码首先检查引导加载程序配置数据的索引是否在我们准备写入的数据范围内。换句话说,它检查我们是否正在写入涉及引导加载程序配置地址的数据。
if((pcData[ui32BlCfgDataIdx] & 0xFF) != SBL_CC2650_BL_CONFIG_ENABLED_BM)
如果上面的条件为真,我们进一步检查该特定索引处的数据是否不等于启用引导加载程序的位掩码(SBL_CC2650_BL_CONFIG_ENABLED_BM)。位与操作& 0xFF是为了仅比较字节数据的低8位。
这里的pcData是一个指向字符数组的指针,包含我们准备写入的所有数据,而ui32BlCfgDataIdx是引导加载程序配置数据在这个数组中的索引。
bBlToBeDisabled = true;
如果上述所有条件都为真,这意味着我们正在尝试更改引导加载程序的配置(更具体地说,我们正在尝试禁用它)。因此,我们将bBlToBeDisabled标志设置为true。
setState(SBL_SUCCESS, “Warning: Bootloader will be disabled.\n”);
我们还调用setState函数来发出警告,指出引导加载程序将被禁用,这是一个重要的更改,可能会影响设备的正常操作。
综合上述分析,这段代码的目的是在尝试禁用引导加载程序时发出警告,并据此修改后续的数据传输行为。