This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC2340R5:蓝牙固件通过uart串口烧录时失败 Ω

Guru**** 2611705 points
Other Parts Discussed in Thread: CC2340R5, UNIFLASH, SYSCONFIG

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1562575/cc2340r5-uart

器件型号:CC2340R5
Thread 中讨论的其他器件: UNIFLASHSYSCONFIG

工具/软件:

通过串行端口升级 CC2340R5 蓝牙固件时、即使之前闪存擦除和写入操作成功、该过程在 CRC 验证步骤中也会失败。 应如何解决此问题?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Mike:

    使用 TI_CC2340_Linux_SBL 工具时、必须确保 创建自定义 bin 文件 、并确保固件二进制文件与扇区大小 (0x800) 对齐。  映像的“Byte Count“(0x64db4) 意味着未遵守这些指令。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您能否告知我 CC2340R5RGE 蓝牙固件的标准二进制文件格式、或者如何通过 Uniflash 工具中的存储器选项生成该文件? 或者、您能直接给我发送一份副本吗? 谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    下面是我共享的 URL 的屏幕截图:

    我建议您使用  在线提供的默认 TI_CC2340_Linux_SBL 工具。   即使 CRC 检查失败、您的升级也可能非常成功。  您应该在尝试升级之前和之后检查您对应用程序所做的更改。  如果您不需要对默认 CCFG 设置进行任何更改、还可以选择从二进制输出生成中删除 CCFG 区域。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、TI 工程师

    我目前有以下问题:

    1.  ccfg 文件  已通过导出  Uniflash 工具  从地址开始、 0x4e020000 到地址结束 0x4e0207ff。 无法将其导出到 0x4e020800。 如何使其兼容?

    2. 在下面的屏幕截图中、 out 从开始的文件大小  数据  如图所示。 当我们刻录文件时、该过程在开始写入闪存时失败。 在实际计算后、文件大小不是 2048 字节的整数倍。 应该如何配置? 请提供指导。

    3. 在下面的屏幕截图中、 out 从开始的文件大小  UART  如图所示。 当我们刻录文件时、进程在期间失败  写入闪存后的 CRC 校验 。 在实际计算后、文件大小不是 2048 字节的整数倍。 应该如何配置? 请提供指导。

    4. 指向的链接  TI_CC2340_Linux_SBL 工具  无法访问您的公司提供的信息。 请您再次提供链接吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.0x4e0207ff 是 CCFG 的最后一个字节、应该是从 Uniflash 中读取 CCFG 的最后一个字节
    2.不应将.out 文件与 Linux SBL 工具一起使用、因为它只接受二进制文件。  您应该从与 0x800 扇区大小对齐的 Uniflash 中以二进制格式读取存储器。  这将需要使用.out 文件对 CC2340R5 器件进行一次编程(不必是最终目标)
    4.如果您无法访问 GitHub ,则附加副本

    e2e.ti.com/.../TI_5F00_CC2340_5F00_Linux_5F00_SBL.zip

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan、
    我有几个问题需要与您确认:

    1. 之前,当我们通过仿真器执行蓝牙固件升级时,只需要 FCFG 文件。 但是、通过 UART 升级现在还需要 CCFG 文件。 是否有办法在不进入引导加载程序模式的情况下更新 CCFG 文件、以启用编程并继续 UART 蓝牙固件升级?
    2. 在编程期间、如果出现随机电源故障(未对 CCFG 进行编程)、器件是否可能无法进入引导加载程序模式?
    3. UART 编程是否支持加密? 如果是、我们应如何继续?
    4. 已编程的闪存中是否有错误的块检测机制? 如果是、我们应该采取哪些步骤来防止生成坏块?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    请务必阅读 TRM 的第 8 章(器件引导和引导加载程序)

    1. 您可能不是指 FCFG、因为这是一种工厂配置、用户无法更改。  如果使用默认的 FCFG 设置、则通过 UART 进行升级不需要 CCFG 文件(由 TI 默认发货器件的空白 CCFG 指示)。  CCFG 存储在闪存中、不建议用户在运行时擦除和写入该闪存、因为如果发生电源事件或器件复位、CCFG 可能会失效。
    2. BLDR_CMD_CHIP_ERASE 命令会使 CCFG 无效、然后擦除 CCFG、因此、如果您使用的是从默认 FCFG 引导的自定义 CCFG、则可以执行此操作。 除非在 CCFG 编程期间发生电源故障、否则不会发生这种情况。
    3. ROM 串行引导加载程序不会、这需要使用自定义引导加载程序。  您可以从 MCUBoot 开始 并从中进行开发。
    4. 这是通过 BLDR_CMD_CRC32 命令进行寻址的。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    您能否提供有关使用自定义引导加载程序进行加密编程的演示或相关指导文档?

    2.什么是  BLDR_CMD_CRC32  写入命令? 我们如何自己验证它? 在相应的 SBL 源代码或固件程序中、此命令在哪里处理?

    3.在固件编程过程中、坏块检测机制的具体解决方案是什么? 我们能否自行验证? 如何在相应的源代码中处理该问题?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.可以从 SysConfig 中选择“User Specific Bootloader“及其引导加载程序矢量表。  加密 TI 驱动程序 和 示例 可供您参考、但目前 TI 并未公开提供全功能自定义引导加载程序解决方案。

    2.  TRM 的第 8 章(器件引导和引导加载程序)全面介绍了所有引导 加载程序命令、便于用户完全操作 ROM 串行引导加载程序、以升级其应用中的器件。

     3. CRC32(循环冗余校验 32)是 一种 32 位错误检测代码、可从数据块生成固定长度校验和以验证其完整性。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    1.使用 IDE 编译自定义引导加载程序后,如何将其写入相应的位置,如何验证修改是否生效?
    2.除了上次所作的修改外、是否还有其他需要修改的地方?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.您的自定义引导加载程序工程应具有自己的命令链接器文件 (CCS 中的*。cmd)、您将为其设置 resetVecs 和闪存的其他扇区。  您可以通过单步执行代码(请参阅  SLA 中的调试 OAD 代码部分)或添加可调试的输出(如 GPIO 或 UART)来验证它们是否生效。
    2.我不知道在这一点上还有什么要说的,否则我已经这样做了。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    非常感谢您的帮助、升级蓝牙固件时、是否可以在不修改 CCFG 的情况下仅更新固件? 我自己尝试了此操作、虽然闪存成功编程、但之后无法读取相应的蓝牙版本号。 此外、无法使用 Uniflash 工具访问存储器、调试端口已经启用。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    BLDR_CMD_CHIP_ERASE 命令会擦除 CCFG

    因此、您要么必须使用默认的 FCFG 设置(即空白 CCFG)、要么在每个引导加载程序编程序列中对新的 CCFG 进行编程。  根据 Uniflash 反馈、似乎错误地写入了 CCFG、这可能导致 CCFG 无效。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    更新蓝牙固件时、我只在不更新 CCFG 文件的情况下擦除和更新 512K 闪存、以保持其与之前版本的一致。 执行此操作后、无法再读取蓝牙版本号、也无法访问存储器中的任何内容。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Mike:

    我很抱歉、因为我认为我造成了一些我需要纠正的困惑。  空白 CCFG 设置仅对应于空白器件、由于您要对新的闪存存储器进行编程、因此还需要对 CCFG 进行编程以保持匹配。  您无法继续使用以前的 CCFG 设置、因为它们已通过引导加载程序擦除命令失效和擦除。  我已经修改了我以前的答复。  为了进行清除、预期的 ROM 串行引导加载程序过程期望闪存和 CCFG 内容都将被写入、因为在序列开始时必须擦除这两个内容。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    我还有几个问题:

    1.通过串行端口升级时、是否对 CCFG 和蓝牙固件的编程顺序有严格的要求? 在固件之前对 CCFG 进行编程是否可以接受?

    2.目前、我们的主机对闪存进行编程的默认波特率是 115200。 如果我们将其更改为另一个值、则升级失败。 如果我们要将其更改为 921600 以缩短擦除和编程时间、究竟应该在哪里修改? 此外、使用主机计算机对固件进行编程时可以设置的最大波特率是多少、在最大波特率下的近似误码率是多少?

    3.在对 CCFG 区域进行非初始升级期间、主机计算机程序是否可以设置为不擦除或重写 CCFG、并继续使用以前版本的 CCFG 文件? 还是在引导加载程序中实现、导致我们无法修改?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.虽然 TRM 中没有任何内容表明您无法或不应这样做、但 CCFG 是最后编程的闪存更有意义、因为它会验证 ROM 串行引导加载程序的完整性。  否则、如果在固件编程期间进行复位或下电上电并且 CCFG 已经完成、则可能会导致器件启动至不完整的固件应用程序。

    2.以下是来自 TRM 的摘录。  我不知道您为什么发现 921600 无效、因为这应该是一个可接受的值。  您能否澄清一下到底是什么失败、以及它是如何指示的?  460800 是否成功?   如果使用定制硬件、则可能需要检查 UART 线路的完整性。  任何位错误都应通过 CRC 校验捕获。

    8.5.1.2.1.1 UART 波特率自动检测 引导加载程序提供了一种自动检测用于与其通信的 UART 波特率的方法。 若要与主机同步、引导加载程序必须接收值为 0x55 的 2 个字节。 如果同步成功、引导加载程序将返回一个由 2 个字节组成的确认、其值为 0x00 和 0xCC。 如果同步失败、引导加载程序会等待同步尝试。 在自动检测功能中、使用 GPIO 中断来监测 UART0 RX 引脚是否存在边沿。 当检测到足够的边沿时、引导加载程序会确定对 UART 进行编程所需的波特率和频率之比。 UART 模块系统时钟必须至少为波特率的 16 倍;因此、最大波特率不能高于 3MBaud (48MHz 除以 16)。 由于固件功能能够检测主机的传输速率、因此最大波特率限制为 1.6Mbaud。

    3.唯一的引导加载程序擦除命令包含 CCFG 的擦除操作、因此如果更新应用程序、还必须对 CCFG 进行编程。  您可能会像以前一样对 CCFG 内容进行编程。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    以下是我的两个问题:

    1.目前只有 115200 的波特率可用。 其他波特率将导致波特率不匹配错误。 `屏幕截图中所示的代码、MCU 似乎没有返回` 0x00、0xCC `或` 0x00、0x33 μ s、这会导致问题。 这些返回值是硬编码的、还是我可以自行修改?

    2.在 CCS 工具中、有一个用于设置波特率的选项、但该选项灰显且无法修改、如屏幕截图所示。 我可以自行修改此设置吗? 如果是、我该如何操作?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     TI_CC2340_Linux_SBL 工具支持多种波特率设置。  您如何更改波特率以及您是否使用逻辑分析仪或示波器确认了输出 TX。

    2.您正在查看 SysConfig 文件中的示例应用程序、该示例应用程序不适用于串行 ROM 引导加载程序功能。

    从  TI_CC2340_Linux_SBL 自述文件中:

    串行引导加载程序提供预编译的 sbl.out 文件、该文件可用于运行预编译的映像。

    为了优化应用程序的引导加载程序、可以更改 Source 文件夹中提供的 C 代码。

    SBL 主要由一组.c 和.h 文件组成:

    • Linux_Serial | Linux_Serial
    • main.c
    • myfile.c|德州仪器 myFile.h
    • sbl_device.c|德州仪器 sbl_device.h
    • sbl_device_cc2340.c|德州仪器 sbl_device_cc2340.h
    • sbl_device.c|德州仪器 sbl_device.h

    这些文件可用于使引导加载程序适应自定义应用程序。

    示例更改如下:

    调整波特率:这可以按照以下步骤完成:

    • 将所需的 Baudrate 添加到 Linux_Serial .h 中的 baudSet_t 枚举中
    • 在 Linux_Serial.c 中的 setBaudRate () 函数中添加 case
    • 在 configPort 函数中更改 setBaudRate ()

    若要在更改后编译工程、可以使用 TI_CC2340_Linux_SBL 文件夹中提供的 makefile。 这可以通过从 Linux 终端调用“make"来“来实现。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

      虽然我们查看了数据表并发现可以自动检测到 9600 和 1.6Mbaud 之间的波特率、但在调试过程中只能检测和正常使用屏幕截图中显示的波特率。 是否还没有配置其他更高的波特率? 此外、如屏幕截图所示、当波特率加倍时、为什么编程时间不会减少一半?

      此外、在写入闪存时、为什么每次写入操作所用的总时间不同? 这种现象的原因可能是什么?

      当波特率为 460800 时、编程时间超过 100 秒。 这是否异常? 造成这种情况的具体原因是什么?


    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    请记住、波特率可以增加、但写入闪存和执行其他闪存命令是静态的。 因此、将波特率加倍本身不会使下载速度减半。 想象一下、如果您无法实现 921600 的波特率、则这种情况很容易受主机生成的波特率的影响。 我在本周通过星期五离职、因此可能会延迟回复。

    此致、

    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    以下是您问题的翻译:

    1.我发现波特率 460800 时,串行通信的标准传输速度约为 30 到 40 秒。 然而,在我自己的测试中,它已经超过了 100 秒。 为何存在如此大的差异?
    2.如果写入闪存和执行闪存命令的过程是静态的,当波特率加倍时,合适的下载速度是多少?
    3.在我的测试中,我可以使用的最大波特率是 460800。 超出此范围时、会发生失配误差。 您提到、主机的波特率生成可能存在问题。 具体来说、这可能是什么问题? 我们是否可以对其进行修改以提高波特率?
    4、使用相同波特率时,为什么连续刷写内存时,每次尝试刷新内存所需的时间会有所不同?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.您是否每次使用相同的二进制映像进行编程,二进制文件的大小是否有变化?  是否确定不存在导致重新启动过程的 CRC 不匹配?
    2.我没有运行任何测试,但我预计它将是线性的二进制图像大小和波特率
    3.您的硬件(TI EVM,定制设计等)如何才能提供示波器或逻辑分析仪对失败的波特率检测过程进行测量?
    4.我不能确定这是没有进一步证据的情况。  “连续“表示您是指在每次重新启动到引导加载程序期间、还是在相同的引导加载程序序列中多次刷写器件?

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    1.在调试过程中,我使用了相同大小的相同二进制映像,在整个刷写过程中没有发生 CRC 校验和故障。
    2.在我的自检中,当使用相同的二进制映像和不同的波特率时,刷新时间随着波特率在可用范围内的增加而减少。 但是、总完成时间仍然没有达到预期的绩效。
    3.我使用 CC2340R5RGE 蓝牙 MCU。 由于电流限制、我目前无法提供相应的测量数据。
    4.表示“连续“、是指每次重新输入引导加载程序以进行串行刷写时。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您提供的信息。  您希望实现的“预期绩效“是什么?  您是否在二进制映像中使用任何填充或空白空间、如果是、是否可以减少写入的闪存大小或是否需要写入完整的 512KB?

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    基于上一个问题、我想补充你提到的以下几点:
    1.预期性能是指串行端口的波特率为 460800 时, 512 KB 闪存的标准传输时间应约为 57 秒。 但是、我们的当前时间超过 100 秒。
    2.我们正在写入整个 512 KB 的闪存。 闪存中是否有任何块不需要擦除和重写? 或者、是否可以跳过某些块并避免写入整个 512KB 闪存?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Mike:

    我使用 TTL232R-3V3 FTDI 至 USB 电缆进行测试、因为 XDS110 不应与该工具一起使用、并能够 使用完整闪存 512KB 映像 (0x7FFFF) 实现 406800 和 921600 两种波特率。  如果我仅在 Uniflash 中读取从 0x0 到 0x3FFFF 的闪存(根据没有 NVS 区域的输出*。map 文件、我的 BLE 应用有足够的闪存空间,因此更新后不会恢复保存的连接)、则使用 406800 波特率的时间会从 70 秒减少到 37 秒。  如果我按照自述文件中的说明、在 sbl_device_cc2340.c 中进一步移除 setProgress 并将 bExpectAck 设置为 false、则时间进一步缩短至 20s。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    我已根据您的建议进行了修改、但我仍有以下问题:

    1. 仅从 0x0 到 0x3FFFF 读取闪存 setProgress  bExpectAck  false  sbl_device_cc2340.c 文件中删除并设置后、编程时间减少到大约 35 秒、波特率为 460800。 但是、它仍然无法达到您提到的 20 秒。 这可能是什么原因?
    2. 我在 sbl_device_cc2340.c  下面提供了修改后的 Linux_Serial 文件的源代码。 您能帮助我检查一下与您提供的演示代码相比有哪些差异吗? 我的意思是、为什么相同的代码仍然会导致额外的 15 秒编程时间? 此外、此文件包含我们自己配置的波特率参数、但 921600 仍然无法使用。 您能帮助检查参数配置是否有任何问题吗?
    3. 您能否提供您的联系信息? 这将使通信更加高效。
      /*sbl_device_cc2340.c write flash*/
      tSblStatus writeFlashRange(uint32_t ui32StartAddress,
                                 uint32_t ui32ByteCount, const char *pcData)
      {
          uint32_t devStatus = CMD_RET_UNKNOWN_CMD;
          tSblStatus retCode = SBL_SUCCESS;
          char u8tCmdStatus[1];
          uint32_t bytesLeft, dataIdx, bytesInTransfer,u32tStatusLength=1;
          uint32_t transferNumber = 1;
          bool bACK=true;
          bool bBlToBeDisabled = false;
          tTransfer pvTransfer[2];
          uint32_t ui32TotChunks = (ui32ByteCount / SBL_CC2340_MAX_BYTES_PER_TRANSFER);
          uint32_t ui32CurrChunk = 0;
          if(ui32ByteCount % SBL_CC2340_MAX_BYTES_PER_TRANSFER) ui32TotChunks++;
      
          /*Init transfer*/
          pvTransfer[0].bExpectAck  = false;           /*Check if operation successfull?*/
          pvTransfer[0].byteCount = ui32ByteCount;   
          pvTransfer[0].startAddr = ui32StartAddress;
          pvTransfer[0].startOffset = 0;
      
          /* For each transfer */
          for(uint32_t i = 0; i < 1; i++)
          {
              /* Sanity check */
              if(pvTransfer[i].byteCount == 0)
                  continue;
      
              /* Set progress */
              //setProgress(addressToPage(pvTransfer[i].startAddr));
      
              /* Send download command */
              if((retCode = cmdDownload(pvTransfer[i].startAddr,
                                        pvTransfer[i].byteCount)) != SBL_SUCCESS)
                  return (retCode);
      
              /* Check status after download command */
              retCode = readStatus(&devStatus);
              if(retCode != SBL_SUCCESS)
              {
                  printf("Error during download initialization. Failed to read device status after sending download command.\n");
                  return (retCode);
              }
      
              /* Send data in chunks */
              bytesLeft = pvTransfer[i].byteCount;
              dataIdx   = pvTransfer[i].startOffset;
              while(bytesLeft)
              {
      			/* Set progress */
                  //setProgress( ((100*(++ui32CurrChunk))/ui32TotChunks) );		
                  /* Limit transfer count */
                  bytesInTransfer = MIN(SBL_CC2340_MAX_BYTES_PER_TRANSFER, bytesLeft);
      
      			/* Send Data command */
                  if((retCode = cmdSendData((const uint8_t*)&pcData[dataIdx], bytesInTransfer)) != SBL_SUCCESS)
                  {
                      printf("Error during flash download. \n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d.\n",
                             (ui32StartAddress+dataIdx),
                             addressToPage(ui32StartAddress+dataIdx),
                             bytesInTransfer,
                             (transferNumber));
                      return (retCode);
                  }
      
                  if(pvTransfer[0].bExpectAck){
                  	if((retCode=sendCmd(CMD_GET_STATUS,NULL,0))!=SBL_SUCCESS){
          			printf("Sending GET_STATUS_CMD failed\n");
          		return(SBL_ERROR);}
      
      			/* Receive command response (ACK/NAK) */
          		if((retCode = getCmdResponse(&bACK, 5)) != SBL_SUCCESS){
          		printf("Device NAKed Status CMD command\n");
          		return (retCode);}
      
          		if(retCode = getResponseData((uint8_t*)u8tCmdStatus,&u32tStatusLength,0) != SBL_SUCCESS){
          			sendCmdResponse(false);
              		return (retCode);}
          		sendCmdResponse(true);
      
          		if(u8tCmdStatus[0]!=0x40){
          		printf("Error during flash download. \n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d.\n",
                             (ui32StartAddress+dataIdx),
                             addressToPage(ui32StartAddress+dataIdx),
                             bytesInTransfer,
                             (transferNumber));
                             return (SBL_ERROR);
          		}
                  }
      			bytesLeft -= bytesInTransfer;
                  dataIdx += bytesInTransfer;
                  transferNumber++;
      			}
              }
          return (SBL_SUCCESS);
      }
      
      
      
      
      /*Linux_Serial.c SetBaudParm*/
      static void setBaudRate(int baud)
      {
          switch(baud)
          {
          case 38400:
              /*Set Baudrate to 38400 Baud*/
              cfsetispeed(&SerialPortSettings,B38400);
              cfsetospeed(&SerialPortSettings,B38400);
              printf("\n  BaudRate = 38400\n");
              break;
          case 57600:
              /*Set Baudrate to 57600 Baud*/
              cfsetispeed(&SerialPortSettings,B57600);
              cfsetospeed(&SerialPortSettings,B57600);
              printf("\n  BaudRate = 57600\n");
              break;
          case 230400:
              /*Set Baudrate to 230400 Baud*/
              cfsetispeed(&SerialPortSettings,B230400);
              cfsetospeed(&SerialPortSettings,B230400);
              printf("\n  BaudRate = 230400\n");
              break;
          case 460800:
              /*Set Baudrate to 460800 Baud*/
              cfsetispeed(&SerialPortSettings,B460800);
              cfsetospeed(&SerialPortSettings,B460800);
              printf("\n  BaudRate = 460800\n");
              break;
          case 9600:
              /*Set Baudrate to 9600 Baud*/
              cfsetispeed(&SerialPortSettings,B9600);
              cfsetospeed(&SerialPortSettings,B9600);
              printf("\n  BaudRate = 9600\n");
              break;
          case 1000000:
              /*Set Baudrate to 1000000 Baud*/
              cfsetispeed(&SerialPortSettings,B1000000);
              cfsetospeed(&SerialPortSettings,B1000000);
              printf("\n  BaudRate = 1000000\n");
              break;
          case 2000000:
              /*Set Baudrate to 2000000 Baud*/
              cfsetispeed(&SerialPortSettings,B2000000);
              cfsetospeed(&SerialPortSettings,B2000000);
              printf("\n  BaudRate = 2000000\n");
              break;
          case 115200:
              /*Set Baudrate to 115200 Baud*/
              cfsetispeed(&SerialPortSettings,B115200);
              cfsetospeed(&SerialPortSettings,B115200);
              printf("\n  BaudRate = 115200\n");
              break;
          case 921600:
              /*Set Baudrate to 921600 Baud*/
              cfsetispeed(&SerialPortSettings,B921600);
              cfsetospeed(&SerialPortSettings,B921600);
              printf("\n  BaudRate = 921600\n");
              break;
          case 1152000:
              /*Set Baudrate to 1152000*/
              cfsetispeed(&SerialPortSettings,B1152000);
              cfsetospeed(&SerialPortSettings,B1152000);
               printf("\n  BaudRate = 1152000\n");
              break;
          case 1500000:
              /*Set Baudrate to 1500000*/
              cfsetispeed(&SerialPortSettings,B1500000);
              cfsetospeed(&SerialPortSettings,B1500000);
               printf("\n  BaudRate = 1500000\n");
              break;
      
          default:
              printf("ERROR: INVALID BAUD\n");
              break;
          }
      }
      
      /****************************************************************
       * Function Name : configPort
       * Description   : Populate the termios structure
       * Returns       : None
       * Params        @None
       ****************************************************************/
      void configPort(int baudspeed)
      {
           /*Using thermios structure to set Serial Port structure*/
          memset(&SerialPortSettings, 0, sizeof(SerialPortSettings));
          setBaudRate(baudspeed);
      
          /*Configure serial port message interpretation */
          /* Enable receiver*/ 
          SerialPortSettings.c_cflag |= (CLOCAL | CREAD);
      
          /* Set Data Size= 8Bit        */
          SerialPortSettings.c_cflag &= ~CSIZE;                           
          SerialPortSettings.c_cflag |= CS8;
      
          /* No Parity   */
          SerialPortSettings.c_cflag &= ~PARENB;
      
          /* 1 Stop bit */
          SerialPortSettings.c_cflag &= ~CSTOPB;
          SerialPortSettings.c_cflag &= ~CRTSCTS;
      
          /* setup for non-canonical mode */
          SerialPortSettings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
          SerialPortSettings.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
          SerialPortSettings.c_oflag &= ~OPOST;
      
          /* fetch bytes as they become available */
          SerialPortSettings.c_cc[VMIN] = 0;
          SerialPortSettings.c_cc[VTIME] = 2;
      
          /* Flush out if there is any previously pending **** */
          clearRxbuffer();
      
          if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0)
              perror("ERROR in Setting attributes |");
          else
              printf("  StopBits = 1 \n  Parity   = none\n");
      }
      
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1. 我们的时间非常相似、只有在修改  GitHub 提供的默认示例的 sbl_device_cc2340.c 文件后、我的时间才进一步减少。
    2. 代码源看起来相似。  您是否确保在保存更改后重新构建该工具?  您应该不再看到闪存写入过程从 0%更新到 100%、但它仍将在  后台进行。
    3. 我认为、其他形式的沟通不会对解决这一调查带来进一步的好处。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

    我还有两个问题。

    *问题 1:**
    如 μ`main.c`文件的屏幕截图所示:
    ```c
    Uint16_t CcfgRegionStart[4]={0x0000、0x0010、0x0750、0x07D0};
    Uint16_t CcfgRegionEnd[4]={0x000B、0x074B、0x07CB、0x07FB};
    ```μ s
    关于`cfg`文件的起始地址和结束地址、在函数`fseek (CCFGfPtr、regionEndAddr、seek_set)`中、偏移量是否需要将 1 添加到结束地址? 否则、下一个写入操作可能会直接覆盖结束地址处的字节。 此外、如何以这种方式写入时确保 CRC 校验和值的准确性?

    *问题 2:**
    在函数`fwrite (&Crc32Value[0]、1、4、CCFGfPtr)`中、在写入过程中、如果发生电源故障或设备重新启动、文件是否会损坏? 是否可以将其修改为直接从存储器写入?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在函数`fwrite (&Crc32Value[0]、1、4、CCFGfPtr) 中;`、在写入过程中、如果发生电源故障或设备重新启动、文件是否会损坏? 是否可以将其修改为直接从内存写入?

    行为取决于相关的 CRC32: Ccfg.bootcfg.CRC32、Ccfg.CRC32、  Ccfg.userRecord.crc32、 Ccfg.debugCfg.crc32。  如果 器件在重新启动时 Ccfg.bootcfg.CRC32 不正确、则会禁用引导加载程序、然后会出现 TRM 中提到的引导配置问题。  否则、可以通过重新执行引导加载程序刷写序列来恢复这种情况。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan

      我们的 BLE 协议支持跨平台功能、例如 iOS 系统。 但是、目前我们只能使用 Android 设备搜索相应的蓝牙名称、而 iOS 设备无法检测到该名称。 这是否需要重新配置协议以使其生效?

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Mike:

    这不是一个典型的观察结果 、因为 SimpleLink Connect 应用 适用于 Android 或 iOS、适用于 basic_ble 或 data_stream 项目。  您需要提供有关项目变更和 iOS 版本的更多详细信息、但我要求您在这样做时发布新的 E2E 帖子、因为此当前主题涵盖了不同的主题(ROM 串行引导加载程序)。

    此致、
    Ryan