蓝牙量产必备:QCC51XX 与30XX系列蓝牙设备一拖多烧录,蓝牙产科文章

亲爱的各位嘉宾大家好,我是Self,十多年蓝牙经验,专业可靠!


蓝牙门诊部(简称门诊)专业解客户Bug

蓝牙生产科,(简称产科)专门解决客户量产问题

以上两个部门简称:产科门诊



攻城狮每天设计,程序猿日夜奋战,终于完成蓝牙方案。俗话说十月怀胎,一朝分娩,迫在眉睫,蓝牙批量生产,这可让工厂生产小妹为难,我们连线一位工厂小妹,“客户要的太多,都要生产,客都接不过来啦”

生产订单多,我们蓝牙设备一个个下载程序,造成工厂小妹们巨大的痛楚,急需攻城狮改善量产方案,此时程序猿是刚下刀山,又进火海。后来多亏我们蓝牙生产科,批量生产一拖多!


这个设计怎么样?

客户们的需求,是否可以得到满足?

小妹们的痛楚,是否可以得到缓解?

攻城狮的理想,是否可以得到实现?

真是妙手回春

且听我一一道来!

正所谓:蓝牙门诊部胜过铁匠铺,蓝牙生产科超越装甲车!(蓝牙门诊部与蓝牙生产科两个部门简称产科门诊)


总之:产科门诊,妙手回春




大大通独家赞助,欢迎收看!



1、一拖一  PK 一拖多

提到蓝牙生产,我们之前有很多专题,大大通搜索“蓝牙量产必备”

这里有设备信息读写的,比如名称地址修改:
文章链接:QCC512x 与QCC302X 蓝牙系列量产必备:设备信息修改

还有顺利生产的,比如 Flash 擦除操作
文章链接:QCC512x 与QCC302X 蓝牙系列量产必备:擦除Flash

也有产后修复的,比如频偏校准,
文章链接:QCC 蓝牙系列量产必备:设备频偏校准


产后修复部分后续会着重讲解,但并不是本集重点!本集主要讲解生产烧录,生产烧录可以分为两种操作:

(1)一对一操作,详见:

 文章链接:QCC512x 与QCC302X 蓝牙系列量产必备:擦除Flash

(2)一托多操作, 详见

文章链接:QCC51XX 与30XX 蓝牙系列量产必备:一拖多擦除


在往期蓝牙生产科文章:QUALCOMM QCC51XX 与30XX 蓝牙系列量产必备:一拖多擦除中,我们提到电脑上最多连接几台耳机设备,烧录也是这样的!


一般客户可以做到一拖八的话,一拖一烧录,一台机器大概用1分钟的话,一拖八同时烧录8台机器,也就一分钟,无论是从操作次数,还是花费时间上,都大大减少,对比一拖一来说,这就是节约了人力物力。


2、开发环境与程序接口


2.1、开发环境设置

开发环境:C++(Microsoft Visual Studio)

头文件:TestFlash.h

库文件:TestFlash.lib

运行环境:Windows 系统,TestFlash.dll 相关DLL,为了使得工具能够运行,可以把TestFlash.dll 相关DLL所在文件夹路径:C:\Program Files (x86)\QTIL\BlueSuite 3.3.8,
设置成Path环境变量,这样工具程序就可以动态调用DLL相关库运行了。

 

2.2、Flash升级接口

  QCC51XX/30XX Flash 参数 升级接口, 在我们的 Bluesuite 库 TestFlash API 中,

在Bluesuite 安装路径下面,找到TestFlash.chm

TestFlash  API :flmProgramSpawn


int32 flmProgramSpawn(
    uint32 deviceMask,
    uint8 eraseFirst,
    uint8 verifyAfter,
    uint8 restartAfter
);

Parameters

deviceMask

Specifies which devices will be programmed. See flmOpen for the details of this parameter.
eraseFirst
Set to 1 to erase the entire NVM of all devices before programming. Set to 0 if erase is not required.
verifyAfter
Set to 1 to verify the NVM contents of devices after completion of the programming process. Set to 0 if verify is not required.
restartAfter
Set to 1 to restart all devices after completion of the programming process. Set to 0 if restart is not required.

其中传入的 deviceMask 一个32位的整数,每个位代表一个设备,理论上是32 台。实际上,如前所说,还要考虑供电等稳定性因素,接个十台八台耳机设备,已经够可以了

 

3、开发流程

3.1、程序设计

打开
Microsoft Visual Studio 集成开发环境,新建Win32-> console application,输入Project名BT_Info_Mag,选择console application—>Empty project->Finish 确认。

添加 BT_Info_Mag.cpp,代码如下:详见附件源文件,登录即可下载

//BT_Info_Mag.cpp

#include "include\\testengine.h"

#include "include\\TestFlash.h"

#include "iostream"

#include"conio.h"

#include"Windows.h"

#include"tchar.h"

using namespace std;

#include "vector"

// Program 2 devices

//uint32 g_devMask = 0x3;

uint32 g_devMask=0;//升级设备的MASK,每一位代表一个设备

uint32 m_Conected_Devices=0;

//#define _Test_Engine_

/**枚举Debug 端口**/

int IGetAvailablePorts(vector& ports,vector& trans);

/**分割字串到相应的ports**/

vector split(const string &s, const string &seperator);

char sXUVFilename[]="D:\\3024.xuv";

uint8 m_eraseFirst=0;

uint8 m_verifyAfter=1;

uint8 m_restartAfter=1;

int main(int argc, char** argv){

    int32 status;//是否枚举出端口

    vector m_vPorts; // The human readable port strings (e.g. "USBDBG(100)")

    vector m_vTrans; // The transport option strings (e.g. "SPITRANS=USBDBG SPIPORT=1")

 

    status=IGetAvailablePorts(m_vPorts,m_vTrans);

    if(status){

         BYTE Bl=m_vPorts.size();

         printf("DebugPorts:len:%d\n",Bl);

 

         int i=0;

         for(vector::iterator iter1=m_vPorts.begin(); iter1!=m_vPorts.end(); ++iter1 ){

             g_devMask+=(1<<i);

             i++;

             printf("DebugPorts %d :%s\r\n",i,iter1->c_str());

         }

         m_Conected_Devices=i;

    }

    bool success = 0;

    /**********************************

    TestFlash Return Values

    #define TFL_OK 0

    #define TFL_ERROR -1

    #define TFL_DEVICE_ERROR -2

    #define TFL_ERROR_UNSUPPORTED -3

    *****************************************/

    int32 flReturn;

 

    // Convert the port specification in to a specification suitable for multiple

    // device open

    // For the purposes of this example, we're just using the first in the list

    char* newTransStr = new char[m_vTrans.at(0).length() + 1];

    uint32 device;

    status = flmConvertPort(m_vTrans.at(0).c_str(), newTransStr, &device);

    if( status != TFL_OK )

    {

         cout << "Error converting port to transport" << endl;

         delete[] newTransStr;

         return status;

    }

    int k=0;

    // Open the port using the trans string

    flReturn = flmOpenTrans(g_devMask, newTransStr, 32);

    while(flReturn != TFL_OK)//self

    {

         Sleep(1000);

         flReturn = flmOpenTrans(g_devMask, newTransStr, 32);

         k++;

         if(k>=5){

             _tprintf(_T("Failed to open TestFlash connection"));

             break;

         }

    }

    if(flReturn == TFL_OK)

    {

         success = true;

         if (flmReadProgramFiles(sXUVFilename) != TFL_OK)

         {

             cout << "Failed to read flash program files" << endl;

             success = false;

         }

         if (success && flmSetFlashType(g_devMask, TFL_TYPE_SQIF) != TFL_OK)

         {

             cout << "Failed to set flash type" << endl;

             success = false;

         }

         if (success && flmSetSubsysBank(g_devMask, 4, 0) != TFL_OK)

         {

             cout << "Failed to set subsystem and bank" << endl;

             success = false;

         }

 

         if (success && flmProgramSpawn(g_devMask, m_eraseFirst, m_verifyAfter, m_restartAfter) != TFL_OK)

         {

             cout << "Failed to spawn flash program thread" << endl;

             success = false;

         }

 

         if (success)

         {

             uint16 devicesRunning;

             int32 progress;

             int32* progressArray= new int32[m_Conected_Devices];

             do

             {

                  devicesRunning = 0;

                  for (uint32 devIndex = 0; devIndex < m_Conected_Devices; ++devIndex)

                  {

                      // Only check the progress if the device is in the mask

                      //if ((devMask >> devIndex) & 1)

                      //if(m_isChecked[devIndex]==1)

                      {

                          progressArray[devIndex]=progress = flmGetDeviceProgress(devIndex);

                          if (progress < 100)

                          {

                               ++devicesRunning;

                          }

                          cout << "dev" << devIndex << ":Programming progress = " << progress << "%" << endl;

                      }

                  }

                  Sleep(1000);

             } while (devicesRunning > 0);

             delete[] progressArray;

             cout << "Completed" << endl;

 

             int32 error = flmGetLastError();

             if (error != TFL_OK)

             {

                  cout << "Programming failed with error: " << error << ". Failed devices mask = " << flmGetBitErrorField() << endl;

                  success = false;

             }

             error=flmGetBitErrorField();

 

         }

 

         if (success)

         {

             cout << "Successfully programmed devices" << endl;

         }

         flmClose(g_devMask);

    }

 

    delete[] newTransStr;

 

}

vector split(const string &s, const string &seperator)

{

    vector result;

    typedef string::size_type string_size;

    string_size i = 0;

 

    while(i != s.size()){

         //找到字符串中首个不等于分隔符的字母;

         int flag = 0;

         while(i != s.size() && flag == 0){

             flag = 1;

             for(string_size x = 0; x < seperator.size(); ++x)

                  if(s[i] == seperator[x]){

                      ++i;

                      flag = 0;

                      break;

                 }

         }

 

         //找到又一个分隔符,将两个分隔符之间的字符串取出;

         flag = 0;

         string_size j = i;

         while(j != s.size() && flag == 0){

             for(string_size x = 0; x < seperator.size(); ++x)

                  if(s[j] == seperator[x]){

                      flag = 1;

                      break;

                  }

                  if(flag == 0)

                      ++j;

         }

         if(i != j){

             result.push_back(s.substr(i, j-i));

             i = j;

         }

    }

    return result;

}

 

 

int IGetAvailablePorts(vector& ports,vector& trans)

{

    int32 status;

    uint16 maxLen(256);

    uint16 count(0);

    char* portsStr = new char[maxLen];

    char* transStr = new char[maxLen];

    int k=0;

#if defined(_Test_Engine_)

    status = teGetAvailableDebugPorts(&maxLen, portsStr, transStr, &count);

    while( (status != TE_OK || count == 0))

#else

    status = flGetAvailablePorts(&maxLen, portsStr, transStr, &count);

    while( (status != TFL_OK || count == 0) )

#endif

    {

         k++;

         printf("teGetAvailableDebugPorts %d 次失败\r\n",k);

         Sleep(900);

#if defined(_Test_Engine_)

         status = teGetAvailableDebugPorts(&maxLen, portsStr, transStr, &count);

#else

         status = flGetAvailablePorts(&maxLen, portsStr, transStr, &count);

#endif

 

         if(k>=6){

             delete[] portsStr;

             delete[] transStr;

             return status&&count;

         }

 

    }

 

#if defined(_Test_Engine_)

    if( status != TE_OK && maxLen != 0 )

#else

    if( status != TFL_OK && maxLen != 0 )

#endif

 

    {

         // Not enough space - resize the storage

         delete[] portsStr;

         portsStr = new char[maxLen];

         delete[] transStr;

         transStr = new char[maxLen];

#if defined(_Test_Engine_)

         status = teGetAvailableDebugPorts(&maxLen, portsStr, transStr, &count);

#else

         status = flGetAvailablePorts(&maxLen, portsStr, transStr, &count);

#endif

 

    }

 

    ports=split( portsStr,(const std::string ) ","); // Use these for user selection (e.g. drop down list)

    trans=split( transStr, (const std::string )","); // Use these to open a transport

 

    delete[] portsStr;

    delete[] transStr;

#if defined(_Test_Engine_)

    return status&&count;

#else

    return !status&&count;

#endif

}

 然后把TestFlash.lib 添加进来,就可以编译通过




3.2
、运行结果

QCC51Xx 与QCC30XX 系列的两块板子,通过 USB 连上PC,(限于开发板数量,我们用两台实例做演示,客户可以用八台设备的生产夹具)运行应用程序,xuv 程序升级到两块板子的Flash 中,大概需要半分钟,过程中还有下载程序的进度打印出来。





真正做到:产科门诊,妙手回春



以上是本篇博文的全部内容!

大大通方案与博文,十分精彩,引人入胜,如果不在登录状态的看官,大大通则视为“匆匆之过客”很快就“不见庐山真面目”了,看的正过瘾啊!怎么会这样,急死人了,怎么办?

各位看官!不要着急!只需一个小小的动作而已:登录!没账号咋办尼?  很简单,请扫描下面二维码注册。



而且还附带小编联系方式,各位看官,如有疑问,请在博文下方评论留言,或者私信给我,收到之后会第一时间回复哦!

想要了解更多内容,请多多关注小编与大大通平台,我们会不断分享最新的热点技术!

相关视频

蓝牙量产必备:QCC51XX 与30XX系列蓝牙设备一拖多烧录,蓝牙产科文章

生产订单多,我们蓝牙设备一个个下载程序,造成工厂小妹们巨大的痛楚,
急需攻城狮改善量产方案,此时程序猿是刚下刀山,又进火海。

后来多亏我们蓝牙生产科,批量生产一拖多,

这个设计怎么样?

客户们的需求,是否可以得到满足?

小妹们的痛楚,是否可以得到缓解?

攻城狮的理想,是否可以得到实现?

 真是妙手回春!

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论