AN-1561: ADuCM4050 の DMA プログラミング
はじめに
ダイレクト・メモリ・アクセス(DMA)コントローラは、データ転送タスクを実行するもので、ADuCM4050 マイクロコントローラ・ユニット(MCU)をそのタスクから解放します。DMA を使用することで、ペリフェラルとメモリ間の高速データ転送が実行できるようになります。データは、CPU による動作を必要とせず、DMA によって迅速に転送可能です。これにより、CPU のリソースを他の動作に自由に使用できます。
このアプリケーション・ノートでは、ADuCM4050 MCU に搭載されたDMA機能の使用方法を説明します。また、プログラミングの手順、DMA の流れ、DMA のコード・スニペットなど、DMA コントローラのプログラム作成に必要な情報を提供します。
DMA コントローラの機能
DMA コントローラは次の機能をサポートしています。
- 27 の独立した DMA チャンネル
- DMA チャンネルごとに 2 つの優先度をプログラム可能
- DMA チャンネル番号で決められた固有の優先度を使用した各優先度のアービトレーション
- 各 DMA チャンネルはプライマリおよび/または代替チャンネル制御データ構造体にアクセス可能
- 次の転送タイプをサポート:
- メモリからメモリ
- メモリからペリフェラル
- ペリフェラルからメモリ
- 次の DMA サイクル・タイプをサポート:
- ベーシック
- 自動リクエスト
- ピン・ポン
- スキャッタ・ギャザ
- 複数の DMA 転送データ幅(8 ビット、16 ビット、32 ビット)をサポート
- 各 DMA チャンネルは、ソースとデスティネーションのインクリメント/デクリメントを個別に制御可能
DMA コントローラの詳細については、ADuCM4050 パワー・マネージメント搭載の超低消費電力 ARM Cortex-M4F MCU ハードウェア・リファレンス・マニュアルを参照してください。
DMA
DMA チャンネル
DMA には 27 個のチャンネルがあり、各チャンネルはペリフェラルからのメモリ・アクセス要求の管理を専門に行います。
表 1 に DMA チャンネルの割り当てを示します。
Channel Node | Peripheral |
0 | SPI2 transmit |
1 | SPI2 receive |
2 | SPORT0A |
3 | SPORT0B |
4 | SPI0 transmit |
5 | SPI0 receive |
6 | SPI1 transmit |
7 | SPI1 receive |
8 | UART0 transmit |
9 | UART0 receive |
10 | I2C slave transmit |
11 | I2C slave receive |
12 | I2C master |
13 | Cryptography in |
14 | Cryptography out |
15 | Flash |
16 to 23 | Software DMA |
24 | Analog-to-digital converter (ADC) receive |
25 | UART1 transmit |
26 | UART1 receive |
DMA システムのブロック図
図 1 に DMA システムのブロック図を示します。
DMA の動作
DMA は、DMA コントローラに提供される情報に基づいてメモリとペリフェラル間のデータ転送を実行します。DMA リクエスト(ソフトウェアDMAリクエスト、またはペリフェラルによるDMA リクエスト)が生成されると、DMA コントローラは該当するチャンネル制御データ構造体から情報を収集してデータ転送を実行します。
DMA コントローラ
データ転送を実行するDMAブロックにおいて主要部を担うのがDMA コントローラです。コントローラは、チャンネル制御データ構造体から転送情報を収集し、DMA 転送リクエストを受け取るとトランザクションを実行します。
チャンネル制御データ構造体
すべてのチャンネルには、プライマリと代替の 2 つの制御データ構造体があります。転送モードの複雑さに応じて、各チャンネルのプライマリ・データ構造体と代替データ構造体のどちらか、または両方を含む独立した空間がメモリ内に割り当てられます。DMA コントローラは、このメモリ空間から転送情報を収集します。
プライマリ/代替データ構造体とデータベース・ポインタ
すべてのDMAチャンネルのプライマリ・データ構造体と代替データ構造体にはDMAディスクリプタを格納します。データ構造体には、各チャンネル・ディスクリプタに対してRAM領域内の16 バイトが割り当てられます。データベース・ポインタには、これらのディスクリプタの開始アドレスが格納されており、これにより、DMA コントローラは、目的とするチャンネルのディスクリプタ情報がどこに書き込まれているか知ることができます。転送リクエストを受け取ると、DMA コントローラはベース・ポインタを読み出し、指定されたチャンネルのディスクリプタに移動します。そして、このディスクリプタで指定されたとおりにデータ転送を実行します。ディスクリプタ情報が他のメモリ空間に定義されている場合は、DMA コントローラをイネーブルする前に、ディスクリプタ情報をチャンネル・データ構造体のメモリ空間に移動させてください。代替データ構造体のベース・ポインタは読出し専用レジスタで、プライマリ・ディスクリプタのベース・ポインタが変更されるとそれに応じて自動的に値が変わります。
16バイトの DMAディスクリプタには DMAトランザクションのすべての情報が格納されています。DMA がチャンネル制御データ構造体から転送情報を収集できるよう、DMA コントローラをイネーブルする前に、ディスクリプタを目的のチャンネル制御データ構造体にコピーする必要があります。表 2 に DMAディスクリプタ・チャンネルの構成要素を示します。
名前 | 説明 | サイズ(バイト) |
SRC_END_PTR | ソース・データの終了アドレス | 4 |
DST_END_PTR | デスティネーション・データの終了アドレス | 4 |
CHL_CFG | DMA 転送の制御情報を提供 | 4 |
RESERVED | 予備 | 4 |
DMA ディスクリプタの構成要素に関する詳細については、ADuCM4050 パワー・マネージメント搭載の超低消費電力 ARMCortex-M4F MCUハードウェア・リファレンス・マニュアルを参照してください。
DMA のプログラミング・モデル
DMA を設定するためのプログラミング・シーケンスの概要を以下に示します。
- データ転送用の DMA ディスクリプタを設定します。
- DMA ベース・ポインタを設定します。
- 目的の DMA チャンネルをイネーブルします。
- DMA 構成レジスタ(DMA_CFG)で DMA コントローラをイネーブルします。
- DMA チャンネル・ソフトウェア・リクエスト・レジスタ(DMA_SWREQ)でソフトウェア DMA リクエストを生成させるか、DMA コントローラへの割込みを生成するペリフェラルをイネーブルします。
モードごとの DMA 設定に関する詳細については、DMA モードのセクションを参照してください。
DMA モード
自動リクエスト(ARQ)モードとベーシック・モード
ARQ モードとベーシック・モードは、すべてのモードの中で最も基本的なモードで、1 つのディスクリプタ転送で構成されます。ARQ モードはメモリからメモリへの転送を実行し、ベーシック・モードはメモリからペリフェラル、またはペリフェラルからメモリへの転送を実行します。
どちらのモードでも、DMA ディスクリプタを最初に作成してからチャンネル・データ構造体に移動させるか、チャンネル・データ構造体に直接書き込むことができます。
この 2 つのモードのプログラミング・シーケンスは以下のとおりです。
- DMA ディスクリプタを作成してからチャンネル・データ構造体に移動させるか、チャンネル・データ構造体に直接書き込みます。
- プライマリ制御データベース(PCD)ポインタをこのチャンネル制御データ構造体のベースを指すように設定します。
- 目的の DMA チャンネルのチャンネル・リクエスト・マスクをクリアします。
- DMA へのリクエスト・ソースの割込みと DMA 完了の割込み(オプション)をイネーブルします。
- 目的の DMA チャンネルをイネーブルします。
- DMA_CFG レジスタを 1 に設定し、DMA コントローラをイネーブルします。
- ソフトウェア DMA リクエストを生成させるか(ARQ DMA)、ペリフェラルの DMA リクエストが生成されるのを待ちます(ベーシック DMA)。
ARQモードとベーシック・モードでは一度に最大1024の転送を実行できますが、DMA コントローラは転送のたびにイネーブルし直す必要があります。
ベーシック・モードのシーケンス図を図 2 に示します。ARQ モードは、ステップ 7 以外、これとまったく同じです。
コードの例:RAM の 2 個のデータ・ブロック内でのメモリとメモリ間の ARQ 転送
メモリのブロック間で DMA ARQ 転送を実行するコードの例を示します。この例では、チャンネル 16 の DMA(ソフトウェアDMA)ディスクリプタを使用して、データを srcPtr[]からdestPtr[]にコピーします。
/* Build the channel descriptor */
ChannelDesc[16].srcEndPtr =(unsigned int) &srcPtr[61];
ChannelDesc[16].destEndPtr =(unsigned int) &destPtr[61];
ChannelDesc[16].ctrlCfg.src_inc = 0;
ChannelDesc[16].ctrlCfg.dst_inc = 0;
ChannelDesc[16].ctrlCfg.src_size = 0;
ChannelDesc[16].ctrlCfg.n_minus_1 = 61u;
ChannelDesc[16].ctrlCfg.r_power = 0;
ChannelDesc[16].ctrlCfg.cycle_ctrl = 2u;
/* give the address of the built channel descriptor to the DMA controller */
*pREG_DMA0_PDBPTR = (unsigned int) &ChannelDesc[0];
/* Enable the DMA channel 16 */
*pREG_DMA0_EN_SET = (1u << 16u);
/* Enable the peripherals to create DMA requests on channel 16 */
*pREG_DMA0_RMSK_CLR = (1u << 16u);
/* enable the DMA controller */
*pREG_DMA0_CFG = 1u;
/* Generate a software DMA request on channel 16 */
*pREG_DMA0_SWREQ = (1u << 16u);
コードの例:UART を使用した場合の、メモリとペリフェラル間のベーシック・モード・データ転送
ハードウェア・リクエストによるメモリ・ブロックとペリフェラル・バッファ・レジスタ間のベーシック・モード転送を実行するコードの例を示します。この例では、チャンネル 8 の DMA(UART0 送信)を使用して、srcPts[]からユニバーサル非同期レシーバー/トランスミッタ(UART)端子にデータを送信します。
/* Build the channel descriptor */
ChannelDesc[8].srcEndPtr =(unsigned int) &srcPtr[61];
ChannelDesc[8].destEndPtr =(unsigned int)pREG_UART0_TX;
ChannelDesc[8].ctrlCfg.src_inc = 0;
ChannelDesc[8].ctrlCfg.dst_inc = 3;
ChannelDesc[8].ctrlCfg.src_size = 0;
ChannelDesc[8].ctrlCfg.n_minus_1 = 61u;
ChannelDesc[8].ctrlCfg.r_power = 0;
ChannelDesc[8].ctrlCfg.cycle_ctrl = 1u;
/* enable the DMA controller */
*pREG_DMA0_CFG = 1u;
/* give the address of the built channel descriptor to the DMA controller */
*pREG_DMA0_PDBPTR = (unsigned int) &ChannelDesc[0];
/* Enable the peripherals to create DMA requests on channel 8 */
*pREG_DMA0_RMSK_CLR = (1u << 8u);
/* Enable the DMA channel 8 */
*pREG_DMA0_EN_SET = (1u << 8u);
/* Configure DMA Channel 8 to use primary data structure */
*pREG_DMA0_ALT_CLR = (1u << 8u);
/* pin mux for UART 0 */
*((volatile uint32_t *)REG_GPIO0_CFG) |= UART0_TX_PORTP0_MUX | UART0_RX_PORTP0_MUX ;
/* UART 0 configuration */
/* baud rate = 9600*/
*pREG_UART0_DIV = 0x1C;
*pREG_UART0_FBR = (0x1<<BITP_UART_FBR_FBEN)|(0x3<<BITP_UART_FBR_DIVM)|(0x2E<<BITP_UART_FBR_DIVN);
*pREG_UART0_LCR2 = (0x3<<BITP_UART_LCR2_OSR);
/* parity , stop */
*pREG_UART0_LCR = (0x3<<BITP_UART_LCR_WLS);
/* Enable DMA request from UART0 to DMA controller */
*pREG_UART0_IEN |=(1u << 4u);
メモリ・スキャッタ・ギャザ・モードとペリフェラル・スキャッタ・ギャザ・モード
メモリ・スキャッタ・ギャザ・モードでは ARQ モードを繰り返し、ペリフェラル・スキャッタ・ギャザ・モードではベーシック・モードを繰り返し実行します。どちらのスキャッタ・ギャザ・モードでも、複数のDMAディスクリプタを設定して一度に実行できます。このモードは、同時に大量の転送を実行したいときに便利です。
このモードでは、すべてのディスクリプタを設定してから、DMA のトランザクションが発生する代替チャンネル・データ構造体に 1 つずつディスクリプタを移動させます。このメモリから代替チャンネル・ディスクリプタ(ACD)へのディスクリプタの移動は、プライマリDMAによって実行します。したがって、目的のDMAチャンネルのプライマリ・ディスクリプタには、宣言されたディスクリプタが終了するソース・エンドの位置情報、代替チャンネル・ディスクリプタのデスティネーション、ワード・サイズおよびアービトレーション・サイズを設定します。インクリメントは 4 に設定します。アービトレーションを 4 に設定することにより、DMA コントローラはプライマリのワード・サイズの転送(これにより 1 つのディスクリプタが代替に移動する)を 4 回実行し、次に代替へ移って実際のデータ転送を実行し、その後、プライマリに戻ります。このサイクルは、ベーシック・モードDMAディスクリプタを読み出すまで継続されます。このディスクリプタによる転送が完了すると、DMA 完了の割込みが生成されます。
スキャッタ・ギャザ・モードのプログラミング・シーケンスは以下のとおりです。
- ベーシック・モードによる最新の DMA ディスクリプタを使用して、実行したい転送の情報を DMA ディスクリプタに定義します(DMA のトランザクションを完了させる必要がある場合)。
- プライマリ・チャンネル・データ構造体に、代替チャンネル・データ構造体に移動させる DMA ディスクリプタの詳細を設定し、アービトレーションを 4 にします。
- PCD ポインタがチャンネル・ディスクリプタのベースを指すように設定します。
- 目的の DMA チャンネルのチャンネル・リクエスト・マスクをクリアします。
- DMA へのリクエスト・ソースの割込みと DMA 完了の割込み(オプション)をイネーブルします。
- 目的の DMA チャンネルをイネーブルします。
- DMA_CFG レジスタを 1 に設定し、DMA コントローラをイネーブルします。
- ソフトウェア DMA リクエストを生成させるか(メモリ・スキャッタ・ギャザ DMA モード)、ペリフェラルの DMAリクエストが生成されるのを待ちます(ペリフェラル・スキャッタ・ギャザ DMA モード)。
スキャッタ・ギャザのシーケンス図を図 3 に示します。
コードの例:RAM の 2 個のデータ・ブロック内でのソフトウェア・リクエストによるメモリとメモリ間のスキャッタ・ギャザ・データ転送
DMA によるメモリのブロック間でのスキャッタ・ギャザ転送を実行するコードの例を示します。この例では、DMA チャンネル16(ソフトウェア DMA)ディスクリプタを使用して、srcPtr1[]から destPtr1[]に、srcPtr2[]からdestPtr2[]に、および srcPtr3[]から destPtr3[]にデータをコピーします。
/* Build the scatter gather descriptor 1 to copy srcPtr1[] to destPtr1[]*/
ScatterGatherDesc[0].srcEndPtr =(unsigned int) &srcPtr1[9];
ScatterGatherDesc[0].destEndPtr =(unsigned int)&destPtr1[9];
ScatterGatherDesc[0].ctrlCfg.src_inc = 0;
ScatterGatherDesc[0].ctrlCfg.dst_inc = 0;
ScatterGatherDesc[0].ctrlCfg.src_size = 0;
ScatterGatherDesc[0].ctrlCfg.n_minus_1 = 9u;
ScatterGatherDesc[0].ctrlCfg.r_power = 0;
ScatterGatherDesc[0].ctrlCfg.cycle_ctrl = 5u;
/* alternate memory to memory scatter gather */
/* Build the scatter gather descriptor 2 to copy srcPtr2[] to destPtr2[]*/
ScatterGatherDesc[1].srcEndPtr =(unsigned int) &srcPtr2[9];
ScatterGatherDesc[1].destEndPtr =(unsigned int)&destPtr2[9];
ScatterGatherDesc[1].ctrlCfg.src_inc = 0;
ScatterGatherDesc[1].ctrlCfg.dst_inc = 0;
ScatterGatherDesc[1].ctrlCfg.src_size = 0;
ScatterGatherDesc[1].ctrlCfg.n_minus_1 = 9u;
ScatterGatherDesc[1].ctrlCfg.r_power = 0;
ScatterGatherDesc[1].ctrlCfg.cycle_ctrl = 5u;
/* alternate memory to memory scatter gather */
/* Build the scatter gather descriptor 3 to copy srcPtr3[] to destPtr3[]*/
ScatterGatherDesc[2].srcEndPtr =(unsigned int) &srcPtr3[9];
ScatterGatherDesc[2].destEndPtr =(unsigned int)&destPtr3[9];
ScatterGatherDesc[2].ctrlCfg.src_inc = 0;
ScatterGatherDesc[2].ctrlCfg.dst_inc = 0;
ScatterGatherDesc[2].ctrlCfg.src_size = 0;
ScatterGatherDesc[2].ctrlCfg.n_minus_1 = 9u;
ScatterGatherDesc[2].ctrlCfg.r_power = 0;
ScatterGatherDesc[2].ctrlCfg.cycle_ctrl = 2u;
/* the last descriptor has to be ARQ to stop the DMA */
/* enable the DMA controller */
*pREG_DMA0_CFG = 1u;
/* Enable the DMA channel 16 */
*pREG_DMA0_EN_SET = (1u << 16u);
/* Enable the peripherals to create DMA requests on channel 16 */
*pREG_DMA0_RMSK_CLR = (1u << 16u);
/* give the address of the built channel descriptor to the DMA controller */
*pREG_DMA0_PDBPTR = (unsigned int) &ChannelDesc[0];
/* Locate the Alternate channel descriptor for channel 16 in memory */
pChannelDescAlternate =(ADI_DMA_DESC*)((*pREG_DMA0_ADBPTR) + (16 * 16));
uint8_t* ptypIntScatterGatherDesc =(uint8_t*)pScatterGatherDesc;
uint8_t* ptypIntChannelDescAlternate =(uint8_t*)pChannelDescAlternate;
/* Build the primary channel descriptor to move ScatterGatherDesc to ChannelDescAlternate*/
ChannelDesc[16].srcEndPtr =(unsigned int)((ptypIntScatterGatherDesc + 11*4)+3);
ChannelDesc[16].destEndPtr =(unsigned int)((ptypIntChannelDescAlternate + 3*4)+3);
ChannelDesc[16].ctrlCfg.src_inc = 2;
ChannelDesc[16].ctrlCfg.dst_inc = 2;
ChannelDesc[16].ctrlCfg.src_size = 2;
ChannelDesc[16].ctrlCfg.n_minus_1 = 11u;
ChannelDesc[16].ctrlCfg.r_power = 2;
ChannelDesc[16].ctrlCfg.cycle_ctrl = 4u;
/* Generate a software DMA request on channel 16 */
*pREG_DMA0_SWREQ = (1u << 16u);
ピン・ポン・モード
ピン・ポン・モードは、転送中に中断することなく連続的にデータを転送するのに便利です。このモードでは、DMA コントローラは、ベーシック・モード・ディスクリプタを読み出すまでプライマリ・ディスクリプタと代替ディスクリプタの切り替えを継続します。
初めに、DMA ディスクリプタの情報をプライマリ・データ構造体と代替データ構造体の両方に書き込みます。転送は、プライマリ・データ構造体から開始します。転送が完了すると、DMAコントローラはすぐに代替データ構造体を読み出し、切り替えによる遅延なしに次のトランザクションを開始します。代替による転送が完了すると、転送はプライマリ・データ構造体に戻ります。そして、このサイクルをベーシック・モード・ディスクリプタを読み出すまで継続します。
プライマリ・データ構造体の転送が完了して代替データ構造体の転送が実行されているときには、代替データ構造体が転送を完了させる前にプライマリ・データ構造体をリセットする必要があります。代替データ構造体のリセットについても同様です。
先述のように、データ構造体がトランザクションを完了すると、ソース・フィールドとデスティネーション・フィールドが更新されない限り、N − 1 フィールドとサイクル制御フィールドのみがリセットされます。
ピン・ポン・モードのプログラミング・シーケンスは以下のとおりです。
- ベーシック・モードによる最新の DMA ディスクリプタを使用して、実行したい転送の情報をすべての DMA ディスクリプタに定義します(DMA のトランザクションを完了させる必要がある場合)。
- 定義したプライマリ・ディスクリプタと代替ディスクリプタを、プライマリ・データ構造体と代替データ構造体にコピーします。
- PCD ポインタがプライマリ・チャンネル・ディスクリプタのベースを指すように設定します。
- 目的のチャンネルのチャンネル・リクエスト・マスクをクリアします。
- DMA へのリクエスト・ソースの割込みと DMA 完了の割込みをイネーブルします。
- 目的の DMA チャンネルをイネーブルします。
- DMA_CFG レジスタを 1 に設定し、DMA コントローラをイネーブルします。
- ソフトウェア DMA リクエストを生成させるか(ソフトウェア・ピン・ポン DMA リクエストの場合)、ペリフェラルの DMA リクエストが生成されるのを待ちます。
- DMA_DONE 割込みルーチンでは、プライマリの転送と代替の転送のどちらが完了したかを示すフラグを生成します。これに応じて、転送が完了するとすぐにチャンネルのプライマリ・ディスクリプタまたは代替ディスクリプタに対応したフィールドをリセットします。.
ピン・ポン・モードのシーケンス図を図 4に示します。
コードの例:UART を使用した場合の、ペリフェラルとメモリ間のピン・ポン・データ転送
ハードウェア・リクエストによるメモリ・ブロックとペリフェラル・バッファ・レジスタ間のピン・ポン・モード転送を実行するコードの例を示します。この例では、チャンネル 9 の DMA(UART0 Rx)を使用してピンとポンを交互に実行し、UART から受信したデータをsrcPtr[]とdestPtr[]に交互に保存します。UART から 5 文字受信するごとにピンとポンを切り替えます。受信した 5 文字は、受信後、UART を介して送信します。
/* Build the primary channel descriptor */
ChannelDesc[9].srcEndPtr =(unsigned int) pREG_UART0_RX;
ChannelDesc[9].destEndPtr =(unsigned int)&srcPtr[4];
ChannelDesc[9].ctrlCfg.src_inc = 3;
ChannelDesc[9].ctrlCfg.dst_inc = 0;
ChannelDesc[9].ctrlCfg.src_size = 0;
ChannelDesc[9].ctrlCfg.n_minus_1 = 4u;
ChannelDesc[9].ctrlCfg.r_power = 0;
ChannelDesc[9].ctrlCfg.cycle_ctrl = 3u;
/* enable the DMA controller */
*pREG_DMA0_CFG = 1u;
/* Enable the DMA channel 9 */
*pREG_DMA0_EN_SET = (1u << 9u);
/* Enable the peripherals to create DMA requests on channel 9 */
*pREG_DMA0_RMSK_CLR = (1u << 9u);
/* give the address of the built channel descriptor to the DMA controller */
*pREG_DMA0_PDBPTR = (unsigned int) &ChannelDesc[0];
/* Locate the Alternate channel descriptor for channel 9 in memory */
ChannelDescAlternate =(ADI_DMA_DESC*)((*pREG_DMA0_ADBPTR) + (16 * 9));
/* Build the Alternate channel descriptor */
ChannelDescAlternate->srcEndPtr =(unsigned int)pREG_UART0_RX;
ChannelDescAlternate->destEndPtr =(unsigned int)&destPtr[4];
ChannelDescAlternate->ctrlCfg.src_inc = 3;
ChannelDescAlternate->ctrlCfg.dst_inc = 0;
ChannelDescAlternate->ctrlCfg.src_size = 0;
ChannelDescAlternate->ctrlCfg.n_minus_1 = 4u;
ChannelDescAlternate->ctrlCfg.r_power = 0;
ChannelDescAlternate->ctrlCfg.cycle_ctrl = 3u;
/* Enable the DMA channel 9 interrupt in NVIC */
NVIC_EnableIRQ(DMA0_CH9_DONE_IRQn);
/* pin mux for UART 0 */
*((volatile uint32_t *)REG_GPIO0_CFG) |= UART0_TX_PORTP0_MUX | UART0_RX_PORTP0_MUX ;
/* UART 0 configuration */
/* baud rate = 9600*/
*pREG_UART0_DIV = 0x1C;
*pREG_UART0_FBR = (0x1<<BITP_UART_FBR_FBEN)|(0x3<<BITP_UART_FBR_DIVM)|(0x2E<<BITP_UART_FBR_DIVN);
*pREG_UART0_LCR2 = (0x3<<BITP_UART_LCR2_OSR);
/* parity , stop */
*pREG_UART0_LCR = (0x3<<BITP_UART_LCR_WLS);
/* Enable DMA request from UART0 RX to DMA controller */
*pREG_UART0_IEN |=(1u << 5u);