symbian流媒体入门之--《RThread使用的简单例子》

本文介绍了一个基于S60平台的RThread示例,展示了如何创建并运行线程,包括监听线程执行状态、增加线程清除栈及活动调度支持等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文出处:http://wiki.forum.nokia.com/index.php/CS000867_-_RThread

 

开发伙伴平台

 

S60 3rd Edition, FP1

 

详细描述

 

RThread示例显示了如何:

1、生成一个简单的CMyThread线程类,可以运行RThread

2、如何监听线程的执行

3、如何增加线程的清除栈

4、如何增加线程的活动调度支持

这里CMyThread线程负责运行了CPeriodic timer

 

MMP文件

 

RThread需要

LIBRARY euser.lib

 

头文件

 

 #include <e32base.h>
 
class MThreadExecuteObserver
    {
    public:
        virtual void ThreadExecuted(TInt aError) = 0;
    };
 
class CMyThread : public CActive, public MThreadExecuteObserver
    {
    public:
        static CMyThread* NewL(MThreadExecuteObserver& aObserver);
        virtual ~CMyThread();
        TInt ExecuteThread(TTimeIntervalMicroSeconds32 anInterval);
        inline TTimeIntervalMicroSeconds32 Interval(){return iInterval;};
 
    private: // From MThreadExecuteObserver
        void ThreadExecuted(TInt aError);
 
    private: // From CActive
        void RunL();
        void DoCancel();
 
    private:
        CMyThread(MThreadExecuteObserver& aObserver);
        void ConstructL();
        void CreateThreadL();
        TInt StartThread();
        static TInt ThreadFunction(TAny* aParams);
        static TInt PeriodicTick(TAny* aObject);
 
    private:
        MThreadExecuteObserver&         iObserver;
        RThread                         iThread;
        TTimeIntervalMicroSeconds32     iInterval;
    };

 

源文件

 #include "CMyThread.h"
 
const TInt KStackSize = 16384;
_LIT(KExecThreadBaseName, "CMyThread");
 
// Global thread id counter for making CMyThread thread names unique.
// This is achieved by appending counter to the end of thread name and
// incrementing counter value for next thread.
// This is writable static data.
TInt g_thread_id_counter = 0;
 
LOCAL_C void GenerateUniqueName(TDes& aResult, CMyThread* aExecutor)
    {
    _LIT(KHexFormat, "_0x%x");
    _LIT(KCounterFormat, "_%d");
    aResult.Copy(KExecThreadBaseName);
    aResult.AppendFormat(KHexFormat, aExecutor);
    g_thread_id_counter++;
    aResult.AppendFormat(KCounterFormat, g_thread_id_counter);
    }
 
CMyThread* CMyThread::NewL(MThreadExecuteObserver& aObserver)
    {
    CMyThread* self = new (ELeave) CMyThread(aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }
 
CMyThread::CMyThread(MThreadExecuteObserver& aObserver)
    : CActive(EPriorityStandard),iObserver(aObserver)
    {
    CActiveScheduler::Add(this);
    }
 
CMyThread::~CMyThread()
    {
    Cancel();
    iThread.Close();
    }
 
void CMyThread::ConstructL()
    {
    }
 
TInt CMyThread::ExecuteThread(TTimeIntervalMicroSeconds32 anInterval)
    {
    TInt ret = KErrNone;
    iInterval = anInterval;
    TRAP(ret,CreateThreadL());
    if (!ret)
        {
        ret = StartThread();
        }
    return ret;
    }
 
TInt CMyThread::StartThread()
    {
    TInt ret = KErrNone;
    if(!IsActive())
        {
        // Requests notification when this thread dies
        // normally or otherwise
        iThread.Logon(iStatus);
        SetActive();
        iThread.Resume();
        }
    else
        {
        ret = KErrOverflow;
        }
    return ret;
    }
 
void CMyThread::ThreadExecuted(TInt aError)
    {
    iObserver.ThreadExecuted(aError);
    }
 
void CMyThread::RunL()
    {
    iObserver.ThreadExecuted(iStatus.Int());
    }
 
void CMyThread::DoCancel()
    {
    iThread.LogonCancel(iStatus);
    iThread.Kill(KErrCancel);
    }
 
void CMyThread::CreateThreadL()
    {
    HBufC* threadName = HBufC::NewLC(KMaxFileName);
    TPtr ptr = threadName->Des();
    GenerateUniqueName(ptr, this);
 
    User::LeaveIfError(iThread.Create(
                        *threadName,
                        CMyThread::ThreadFunction,
                        KStackSize,
                        NULL,
                        this));
 
    CleanupStack::PopAndDestroy(threadName);
    }
 
TInt CMyThread::ThreadFunction(TAny* aParams)
    {
    // 1. Add cleanup stack support.
    CTrapCleanup* cleanupStack = CTrapCleanup::New();
 
    // 2. Get pointer to thread host
    CMyThread* host = (CMyThread*)aParams;
 
    TRAPD(err,
        // 3. Add support for active objects
        CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
        CleanupStack::PushL(activeScheduler);
        CActiveScheduler::Install(activeScheduler);
 
        // 4. Create and start CPeriodic class that is executed in this thread
        CPeriodic* periodic = CPeriodic::NewL(CActive::EPriorityLow);
        CleanupStack::PushL(periodic);
        periodic->Start(host->Interval(),host->Interval(),
        TCallBack(host->PeriodicTick, host));
 
        // NOTE: When adding CActiveScheduler support for threads we have to
        // add atleast one active object in it or it fails on
        // CActiveScheduler::Start().
        // CPeriodic is derived from CActive active object so that is good for
        // this example.
 
        // 5. --> Thread execution starts
        CActiveScheduler::Start();
        // 6. --> Thread execution ends (waiting for CActiveScheduler::Stop())
 
        CleanupStack::PopAndDestroy(periodic);
        CleanupStack::PopAndDestroy(activeScheduler);
        );
 
    host->ThreadExecuted(err);
    delete cleanupStack;
    return KErrNone;
    }
 
TInt CMyThread::PeriodicTick(TAny* aObject)
    {
    CMyThread* mythread = (CMyThread*)aObject;
    if (mythread)
        {
        // Thread is executed once so time to stop it
        CActiveScheduler::Stop();
        // After this execution continues from CActiveScheduler::Start()
        }
    // Does not continue again
    // Note: Does not work with this CPeriodic class
    return EFalse;
    }

 

运行CMyThread

将CMyThread作为类成员变量,然后执行它

TTimeIntervalMicroSeconds32 time(100);
iMyThread = CMyThread::NewL(*this);
iMyThread->ExecuteThread(time);

当线程执行时,它会调用作为引用参数传入CMyThread::NewL(*this)的observer

void CYourClass::ThreadExecuted(TInt aError)
    {
    // Will be called after thread execution
    }

<think>好的,我需要帮助用户解决在RT-Thread Studio中使用QBoot与Y-Modem的问题。首先,我需要理解用户的具体需求。用户提到参考了站内的几个引用,其中涉及QBoot的配置、RT-Thread Studio的使用步骤以及时钟设置的问题。用户可能是在尝试将QBoot和Y-Modem结合使用进行固件升级,但遇到了困难。 首先,我应该回顾QBoot和Y-Modem的基本概念。QBoot是RT-Thread的一个精简版引导程序,支持通过串口使用Y-Modem协议进行固件升级。Y-Modem是一种文件传输协议,常用于通过串口传输数据,适合在资源有限的嵌入式设备上使用。 接下来,我需要整理用户提供的引用内容。引用[1]提到了QBoot的Gitee仓库,用户可能已经尝试过该仓库的步骤。引用[4]详细描述了在RT-Thread Studio中新建项目、修改时钟配置以及遇到的编译错误。用户可能在配置QBoot时遇到了时钟设置的问题,导致编译错误或者固件无法正常运行。 用户的问题可能涉及以下几个方面: 1. 如何在RT-Thread Studio中配置QBoot项目? 2. 如何集成Y-Modem协议到QBoot中? 3. 如何解决编译过程中出现的错误,尤其是时钟配置相关的问题? 4. 如何通过串口使用Y-Modem进行固件升级? 我需要按照这些步骤逐步解答。首先,引导用户正确配置QBoot项目,确保项目设置正确,包括时钟配置(如使用外部高速时钟HSI改为HSE)。然后,添加Y-Modem相关的软件包或代码,并配置串口通信。接着,处理可能出现的编译错误,比如时钟配置错误或依赖缺失。最后,测试固件升级流程,确保Y-Modem能够正确传输和烧录固件。 此外,用户可能遇到的常见问题包括: - 时钟源配置不正确导致系统时钟错误,进而使串口通信失败。 - Y-Modem软件包未正确添加或配置,导致协议无法正常工作。 - 串口驱动未正确初始化,导致无法通信。 - 编译时的依赖项缺失或版本冲突。 需要提醒用户注意检查这些部分,并参考官方文档和示例代码进行调整。同时,提供具体的代码示例和配置步骤,帮助用户逐步操作。如果用户遇到了特定的错误信息,可能需要更详细的日志或错误提示来进一步诊断问题。</think>### RT-Thread Studio中QBoot与Y-Modem集成使用教程 #### 一、环境准备 1. **安装RT-Thread Studio** 确保使用最新版本(推荐5.1.0+),从[官网](https://www.rt-thread.org/studio.html)下载安装[^4]。 2. **硬件配置** - 确认开发板支持串口通信(如STM32G070KBT6的USART1)。 - 检查外部高速晶振(HSE)是否焊接并配置正确[^4]。 --- #### 二、QBoot配置步骤 1. **新建QBoot项目** - 在RT-Thread Studio中依次点击:【文件】→【新建】→【RT-Thread项目】,选择“基于开发板”模板,勾选`QBoot组件`[^1][^3]。 - 配置项目时选择正确的芯片型号(如STM32G070KBT6)。 2. **修改时钟源配置** QBoot默认使用HSI(内部时钟),需改为外部高速时钟HSE: ```c // board.h #define BSP_CLOCK_SOURCE ("HSE") #define BSP_CLOCK_SOURCE_FREQ_MHZ ((int32_t)8) // 根据实际晶振频率修改 ``` 修改后全局编译,确保无时钟配置错误[^4]。 3. **配置串口通信** - 在`board.c`中初始化串口硬件(如USART1),确保波特率与Y-Modem协议匹配(默认115200)。 - 启用DMA或中断模式提升传输效率。 --- #### 三、集成Y-Modem协议 1. **添加Y-Modem软件包** - 在RT-Thread Studio的“软件包中心”搜索并安装`Ymodem`组件。 - 在`rtconfig.h`中启用相关宏: ```c #define RT_USING_DFS #define RT_USING_DFS_DEVFS #define PKG_USING_YMODEM ``` 2. **实现固件接收逻辑** 在QBoot的`main.c`中添加Y-Modem回调函数: ```c static void ymodem_recv_callback(const char* filename, uint32_t size) { // 擦除Flash并写入接收到的固件 qboot_firmware_update((uint8_t*)ymodem_buffer, size); } ``` --- #### 四、编译与烧录 1. **解决常见编译错误** - **依赖缺失**:检查`Ymodem`软件包是否完整安装。 - **Flash分区冲突**:在`qboot_cfg.h`中调整分区表,确保APP区域与QBoot无重叠。 2. **烧录QBoot到设备** 使用ST-Link或J-Link工具将编译生成的`qboot.bin`烧录至Flash起始地址(0x08000000)。 --- #### 五、测试Y-Modem升级 1. **启动QBoot** 复位设备,通过串口终端(如PuTTY)进入QBoot交互模式,输入`ymodem`启动传输。 2. **发送固件文件** 使用终端工具发送固件(如`app.bin`),QBoot会自动擦写Flash并跳转到新固件。 --- ### 常见问题解决 1. **Y-Modem传输中断** - 检查波特率是否一致。 - 确认串口驱动未占用DMA资源冲突。 2. **固件无法启动** - 验证Flash分区地址是否正确。 - 检查APP固件的向量表偏移量是否匹配。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值