衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何選擇RTOS?使用R-Rhealstone框架評估

Rice嵌入式開發技術分享 ? 來源:Rice嵌入式 ? 作者:Rice嵌入式 ? 2024-02-20 13:54 ? 次閱讀

文章描述基于Rhealstone的系統實時性的測量基準的框架--R-Rhealstone框架。

嵌入式軟件設計和集成中,實時多任務操作系統的性能分析是至關重要的,它需要保證應用的時間限制得到滿足,即是運行時間不能超過應用的時間限制。為了選擇滿足用于特定應用的嵌入式系統的一個適當的操作系統,我們需要對操作系統服務進行分析。這些操作系統服務是由形成性能指標的參數確定的,既定的性能指標包括上下文切換時間、任務搶占時間、中斷延遲時間、信號量混洗時間、死鎖解除時間、信息傳輸延遲。

關于實時操作系統對性能指標進行分析,是為了選擇滿足用于特定應用的嵌入式系統的最優的操作系統。

Rhealstone

Rhealstone是系統實時性的測量基準之一,Rhealstone性能基準程序是實時系統的六個關鍵操作的時間量進行操作,這六個關鍵操作是:上下文切換時間、任務搶占時間、中斷延遲時間、信號量混洗時間、死鎖解除時間、信息傳輸延遲。這六項操作作為Rhealstone的六個組件,每個組件被單獨測量。然后將經驗結果合并為單一的測量值,即是Rhealstone值。

測量Rhealstone值方式:

序號 說明
方式 1 通用Rhealstone
方式 2 每個組件應用于具體應用程序的特定Rhealstone

Rhealstone性能基準程的缺點:

序號 說明
缺點 1 測量的是平均時間,而不是最壞值
缺點 2 后的結論是加權平均值,沒有給出確定權值的依據

R-Rhealstone框架

設計R-Rhealstone框架的目的:為了能讓對比的系統實時性的測量的一致性,必須保證同一個環境,解除差異性帶來測量干擾,所以R-Rhealstone框架提供了操作系統適配層,統一適配不同操作系統的各個接口,目的可以達到上層調用層次一致。

76c32840-b599-11ee-9b10-92fbcf53809c.png

上下文切換時間

描述:

上下文切換時間也稱任務切換時間(task switching time),定義為系統在兩個獨立的、處于就緒態并且具有相同優先級的任務之間切換所需要的時間。它包括三個部分,即保存當前任務上下文的時間、調度程序選中新任務的時間和恢復新任務上下文的時間。切換所需的時間主要取決于保存任務上下文所用的數據結構以及操作系統采用的調度算法的效率。產生任務切換的原因可以是資源可得,信號量的獲取等。任務切換是任一多任務系統中基本效率的測量點,它是同步的,非搶占的,實時控制軟件實現了一種基于同等優先級任務的時間片輪轉算法。影響任務切換的因素有:主機CPU的結構,指令集以及CPU特性。

任務切換過程增加了應用程序的額外負荷。CPU的內部寄存器越多,額外負荷就越重。任務切換所需要的時間取決于CPU有多少寄存器要入棧。實時內核的性能不應該以每秒鐘能做多少次任務切換來評價,RTOS中通常是1微秒左右。

流程:

原理:創建兩個同等優先級的任務,兩個任務相互切換多次,最后求平均值。

注意:①需要減去多次切換的循環時間(loop_overhead);②需要減去主動讓CPU執行時間(dir_overhead)

時間計算公式:

total_time:多次上下文切換總時間

loop_overhead:多次切換的循環時間

iterations:切換的次數

dir_overhead:調用讓出CPU接口的時間

76c6da1c-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatloop_overhead=0.0;
staticfloatdir_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount1,count2;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
/*Yieldprocessorsosecondtaskcanstartupandrun*/
rst_task_yield();

for(count1=0;count1

任務搶占時間

描述:

搶占時間即系統將控制權從低優先級的任務轉移到高優先級任務所花費的時間。為了對任務進行搶占,系統必須首先識別引起高優先級任務就緒的事件,比較兩個任務的優先級,最后進行任務的切換,所以搶占時間中包括了任務切換時間。

它和任務切換有些類似,但是搶占時間通?;ㄙM時間更長。這是因為執行中首先要確認喚醒事件,并評估正在運行的任務和請求運行的任務的優先級高低,然后才決定是否切換任務。實質上,所有的多處理任務可以在執行期間動態分配優先級,所以,搶占時間也是衡量實時性能的重要指標。

流程:

原理:創建兩個任務,任務1優先級比任務2優先級低,兩個任務進行搶占多次,最后求平均值。

注意:①需要減去多次任務搶占的循環時間(loop_overhead);②需要減去掛起任務所需要的時間(dir_overhead)

時間計算公式:

total_time:多次任務搶占總時間

loop_overhead:多次任務搶占的循環時間

iterations:任務搶占的次數

switch_overhead:掛起任務所需要的時間

76caa1b0-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatloop_overhead=0.0;
staticfloatswitch_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Startuptask2,getpreempted*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
switch_overhead=rst_benchmark_time_read();

rst_benchmark_time_init();
/*Benchmarkcode*/
for(count=0;count

中斷延遲時間

描述:

中斷延遲時間是指從接收到中斷信號到操作系統做出響應,并完成進入中斷服務例程所需要的時間。多任務操作系統中,中斷處理首先進入一個中斷服務的總控程序,然后才進入驅動程序的ISR。

中斷延遲時間=最大關中斷時間+硬件開始處理中斷到開始執行中斷服務例程第一條指令之間的時間。

硬件開始處理中斷到開始執行中斷服務例程的第一條指令之間的時間由硬件決定,所以,中斷延遲時間的長短主要取決于最大關中斷的時間。硬實時操作系統的關中斷時間通常是幾微秒,而Linux最壞可達幾毫秒。

流程:

原理:創建一個任務,任務執行主動觸發中斷,執行完中斷服務程序返回,統計其時間。

注意:①需要減去讀取時間接口的耗時時間(timer_overhead);

時間計算公式:

isr_enter_time:多次任務搶占總時間

iterations:任務搶占的次數

timer_overhead:讀取時間接口的耗時時間

76d91538-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloattimer_overhead=0.0;
staticfloatisr_enter_time=0.0;

staticrst_task_idrst_task1=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_LOWEST_PRIORITY+1,
#else
.priority=RST_TASK_LOWEST_PRIORITY-1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_isr_handler(void*param)
{
isr_enter_time=rst_benchmark_time_read();
}

staticvoidrst_task1_func(void*arg)
{
rst_isr_install(RST_ISR_NUM,rst_isr_handler,NULL);

/*Benchmarkcode*/
rst_benchmark_time_init();
/*goestoIsr_handler*/
rst_isr_trigger(RST_ISR_NUM);

RST_PRINT_TIME(
"R-Rhealstone:interruptlatencytime",
isr_enter_time,
1,/*OnlyRhealstonethatisn'tanaverage*/
timer_overhead,
0
);
rst_task_delete(NULL);
}

rst_statusrst_interrupt_latency_init(void)
{
rst_task_create(&rst_task1,rst_task1_func,NULL,&rst_task1_attr);
if(rst_task1==NULL)
{
RST_LOGE("RST:task1createfailed");
returnRST_ERROR;
}

rst_benchmark_time_init();
rst_benchmark_time_read();
rst_benchmark_time_init();
timer_overhead=rst_benchmark_time_read();

returnRST_OK;
}

信號量混洗時間

描述:

信號量混洗時間(semaphore shuffling time),是指從一個任務釋放信號量到另一個等待該信號量的任務被激活的時間延遲。在RTOS中,通常有許多任務同時競爭某一共享資源,基于信號量的互斥訪問保證了任一時刻只有一個任務能夠訪問公共資源。信號量混洗時間反映了與互斥有關的時間開銷,因此也是衡量RTOS實時性能的一個重要指標。

流程:

原理:創建一個信號量和兩個相同優先級的任務。代碼需要執行兩次,第一次信號量不介入調度,計算任務切換的時間,第二次多次循環,信號量接入調度,信號量在兩個任務中ping-pong執行,計算總時間。

注意:①需要減去任務切換的時間(switch_overhead);

時間計算公式:

telapsed:多次信號量混洗總時間

iterations:信號量混洗的次數

switch_overhead:切換的時間

76dc72dc-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatswitch_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount=0;
staticuint32_tsem_exe=1;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_sem_idrst_sem=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Startuptask2,yieldsoitcanrun*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
rst_task_yield();

/*Benchmarkcode*/
for(;count

死鎖解除時間

描述:

死鎖解除時間(deadlock breaking time),即系統解開處于死鎖狀態的多個任務所需花費的時間。死鎖解除時間反映了RTOS解決死鎖的算法的效率。

流程:

原理:創建一個信號量和三個任務,優先級排序:任務1 < 任務2 < 任務3。代碼需要執行兩次,第一次信號量不介入調度,計算任務3切換到任務2,任務2切換到任務1得時間(即從高優先級切換到低優先級得時間),第二次多次循環,信號量接入調度,任務3死鎖,任務2喚醒任務1,任務1解除死鎖,通過統計多次,求平均值。

注意:①需要減去任務切換的時間(switch_overhead);

時間計算公式:

telapsed:多次死鎖解除總時間

iterations:死鎖解除的次數

switch_overhead:任務切換的時間

lock_overhead:調用信號量持有接口所需要得時間

76e87b9a-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatswitch_overhead=0.0;
staticfloatlock_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount=0;
staticuint32_tsem_exe=1;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;
staticrst_task_idrst_task3=NULL;

staticrst_sem_idrst_sem=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task3_attr={
.name="task3",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-5,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+5,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task1_func(void*arg)
{
/*AlltaskshavehadtimetostartuponceTA01isrunning*/

/*Benchmarkcode*/
rst_benchmark_time_init();
for(count=0;count

信息傳輸延遲

描述:

信息傳輸延遲(datagram throuShput time),指一個任務通過調用RTOS的消息隊列,把數據傳送到另一個任務去時,每秒可以傳送的字節數。

流程:

原理:創建一個消息隊列和兩個任務,優先級排序:任務1 < 任務2。任務1負責發送數據,任務2負責接收數據,執行多次,求平均值

注意:①需要減去調用消息隊列接收函數的時間(receive_overhead);

時間計算公式:

telapsed:多次信息傳輸總時間

iterations:死鎖解除的次數

loop_overhead:多次循環的時間

receive_overhead:調用消息隊列接收函數的時間

76ec1034-b599-11ee-9b10-92fbcf53809c.png

代碼:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

#defineRST_QUEUE_BUFF_SIZE4

staticfloatloop_overhead=0.0;
staticfloatreceive_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_queue_idrst_queue=NULL;

staticintqueue_buff[RST_QUEUE_BUFF_SIZE]={0};

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Putamessageinthequeuesorecieveoverheadcanbefound.*/
rst_queue_send(rst_queue,
(constvoid*)queue_buff,
(uint32_t)sizeof(queue_buff),
(rst_time_t)RST_WAIT_FOREVER);

/*Startupsecondtask,getpreempted*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}

for(;count

RTOS對比結論

對比環境說明

說明
芯片 芯片型號:stm32f401
芯片架構:Cortex-M4
主頻:84 MHz
開發環境 KEIL 5.x
工具鏈 ARMCC

對比結果說明

對比項 RT-Thread LiteOS FreeRTOS TobudOS
上下文切換 2.594596 us 6.739740 us 1.049049 us 2.343343
任務搶占 7.360721 us 7.603206 us 2.715431 us 4.523046 us
中斷延遲 2.000000 us 1.000000 us 1.000000 us 1.000000 us
信號量混洗 23.829000 us 25.588000 us 19.496000 us 18.451000 us
死鎖解除 18.108000 us 18.074000 us 21.522000 us 31.606000 us
信息傳輸延遲 7.749499 us 7.390782 us 7.298597 us 3.446894 us

總結

作者測試過程采用定時器計數器是1us,精度上有所欠缺,策略結果大致對比

中斷延時部分,RT-Thread的中斷是有框架的,而LiteOS和FreeRTOS直接使用STM32的HAL庫,時間差異在框架的耗時

FreeRTOS在本次的對比的優勢比較明顯,除了死鎖解除稍微遜色一點,其他的持平或由于RT-Thread和LiteOS

LiteOS在本次對比表現最差,尤其是上下文切換的耗時是RT-Thread和FreeRTOS的2~3倍。

開源鏈接

鏈接路徑:https://github.com/RiceChen0/r-rhealstone.git

說明:該框架目前已經適配作為RT-Thread的軟件包,可以通過軟件包體驗其功能

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5093

    文章

    19178

    瀏覽量

    307713
  • 框架
    +關注

    關注

    0

    文章

    403

    瀏覽量

    17543
  • RTOS
    +關注

    關注

    22

    文章

    819

    瀏覽量

    119890
收藏 人收藏

    評論

    相關推薦

    R-Rhealstone框架使用教程

    本篇文章描述基于Rhealstone的系統實時性的測量基準的框架--R-Rhealstone框架
    的頭像 發表于 01-18 10:54 ?1646次閱讀
    <b class='flag-5'>R-Rhealstone</b><b class='flag-5'>框架</b>使用教程

    請問使用ADA4927-1評估R5、R6、R7、R8、R9、R10的值怎么選擇

    請教大家一個問題,在使用ADA4927-1評估板時,R5、R6、R7、R8、R9、
    發表于 10-09 18:03

    嵌入式設計中,如何評估最適合應用的 RTOS?

    RTOS 可供開發人員使用,從開源系統到經認證的商業 RTOS。那么,該如何選擇 RTOS 并開始使用呢?如何評估最適合應用的
    發表于 07-26 14:15

    該如何選擇RTOS?如何去使用RTOS呢?

    選擇RTOS需要考慮哪些因素?如何評估最適合應用的RTOS?STMicroelectronics和Renesas是什么?
    發表于 06-28 06:03

    RTOS框架下使用ROSSerial

    STM32以極優的性價比提供了可以運行RTOS的硬件平臺,使用RTOS已經不是一件奢侈的事情了,如果能在RTOS框架下使用ROSSerial應該是編寫嵌入式控制程序的福音,故做此嘗試。
    發表于 03-02 06:47

    選擇RTOS時要看哪些參數?

    選擇RTOS時,要看哪些參數
    發表于 09-21 07:42

    選擇實時操作系統(RTOS)的要點詳解

      對許多嵌入式項目來說,系統設計師都傾向于選擇實時操作系統(RTOS)。但RTOS總是必要的嗎?答案是取決于具體
    發表于 10-28 10:41 ?9234次閱讀
    <b class='flag-5'>選擇</b>實時操作系統(<b class='flag-5'>RTOS</b>)的要點詳解

    如何選擇適合自己的開源RTOS

    選擇適合自己的開源RTOS
    的頭像 發表于 03-12 11:44 ?2809次閱讀

    詳解選擇RTOS的要點

    大多數程序員不熟悉RTOS的限制和要求。大多數人通常因其性能選擇RTOS。大多數RTOS產品代碼少和速度快,現在RTOS還提升了一致性。
    的頭像 發表于 04-05 09:44 ?1708次閱讀

    RTOS如何使用及如何選擇

      許多項目把自己畫到了一個角落,改變 RTOS 或系統設計不再是可行的選擇;編寫了太多代碼以允許改變方向。無論好壞,該項目都被它選擇的任何東西所困擾。這對豆類柜臺和其他所有人來說都是個壞消息。
    發表于 06-29 09:08 ?1393次閱讀

    如何選擇正確的RTOS

      在開發醫療設備時,選擇 RTOS 是一個涉及生死攸關的復雜決定。仔細關注 RTOS 產品的技術特性及其在生命關鍵設備實施中的跟蹤記錄是唯一安全的方法。
    發表于 08-11 14:57 ?1087次閱讀

    在單片機中使用的RTOS代碼框架

    在這次開發中,也是遇到了很多的問題,主要的感想是關于代碼的框架。在單片機開發中,特別是使用了RTOS的時候,一個良好的代碼框架真的是相當的必要的。
    的頭像 發表于 02-10 14:21 ?1193次閱讀

    詳解選擇RTOS的要點

    對于許多嵌入式項目來說,在采用非實時操作系統(non-RTOS)的任何場合,也都可采用RTOS。但是,要找到一款具有完全相同應用編程接口(API)的匹配RTOS就相當困難了。因此,許多傳統的操作系統
    的頭像 發表于 03-31 15:20 ?895次閱讀

    選擇實時操作系統(RTOS)的要點詳解

    對許多嵌入式項目來說,系統設計師都傾向于選擇實時操作系統(RTOS)。但RTOS總是必要的嗎?答案是取決于具體的應用,因此了解我們要達到什么目標是決定RTOS是必要的還是花瓶的關鍵。
    發表于 05-30 09:45 ?1087次閱讀

    何時選擇裸機?何時選擇RTOS?何時選擇GPOS?

    在每個開發項目的初期,你都必須選擇軟件開發的基礎。雖然有很多選擇,但它們通常分為三類:裸機、實時操作系統(RTOS)或通用操作系統(GPOS)。
    的頭像 發表于 02-27 11:42 ?1295次閱讀
    大发888老虎机下载| 德州扑克英文| 优博娱乐网址| 百家乐官网翻天腾讯视频| 三公百家乐官网在线哪里可以| 百家乐制胜法宝| 皇冠体育网| 蓝盾百家乐官网赌场娱乐网规则 | 通榆县| 百家乐官网网上真钱娱乐| 澳门百家乐网上赌博| e世博备用网址| 长春百家乐官网的玩法技巧和规则 | 威尼斯人娱乐城赌博| 胶南市| 百家乐官网桌手机套| 百家乐怎么骗人| E世博线上娱乐城| 涿州市| 凯旋门百家乐技巧| bet365网址器| 新利百家乐官网的玩法技巧和规则 | 莱西市| 百家乐出千赌具| 犹太人百家乐的玩法技巧和规则 | 百家乐官网娱乐开户| 娱乐百家乐官网可以代理吗| 冠赌球网| 百家乐官网真钱斗地主| 百家乐翻天超清| 视频百家乐官网平台出租| 百家乐在线娱乐可信吗| 皇冠投注网| 百家乐有人赢过吗| 太阳城娱乐城怎么样| 犹太人百家乐官网的玩法技巧和规则 | 网页百家乐官网| 百家乐官网代打公司| 稳赢的百家乐投注方法| 永利高足球博彩网| 百家乐二号博彩正网|