前回「RX62NのUSB機能を使う」でRX62NのUSB機能を利用してCDCデバイスでパソコンと通信するプログラムを紹介しましたが、パソコン側からうまく認識されないことがあるようです。ルネサスエレクトロニクス社のサンプルを見ていたら「Renesas USB MCU USB Peripheral Communication Device Class Driver(PCDC)」を見つけました。とりあえず手持ちのe2studioに読み込み実行しようとしましたが、E1デバッガ経由で実行することができませんでした。
プロジェクトを新たに作成し、ソースコードをコピーし、一部手直ししたら動作しました。
修正したファイル
demo_src\r_usb_pcdc_descriptor.c
r_config\r_bsp_config.h
使用しているMPUに合わせて変更(コメント通りに変更する)
「RXマイコン基板(RX62N) | Renesas MCU Software Libraryの仮想COMポートファームウェアを試す 」にも書かれています。
手直ししたプロジェクト
改造しやすいように手直ししました。
USB機能を動作させるためには、一定間隔で次のプログラムを実行する必要があります。
変更したプロジェクト
さらに、printf,scanfなどの標準入出力関数が使えるように変更しました。
一定間隔でusb_cdc_manage()関数を呼び出せば動作します。時間待ちの時にもこの関数を呼び出してください。
標準入出力が使えるプロジェクト
usb_cdc_manage()関数をタイマ割り込みで動かせば、プログラムが簡単にできると思い、プログラムを変更しました。タイマ割り込みで呼び出しても、問題なく動作しています。初期化のためinitUSB_cdc()関数を呼び出すだけで、パソコンとUSB通信することが可能です。
タイマ割り込みを利用したプロジェクト
Windows用デバイスドライバ
Windows用のデバイスドライバはルネサスエレクトロニクスの「RX62Nグループ、RX621グループ USBペリフェラルCDCによるフラッシュブートローダ」サンプル内に「CDC_Demo_Win7.inf」ファイルが入っています。ベンダIDとプロダクトIDをRX62Nのプログラムに合わせて書き換えます。
プロジェクトを新たに作成し、ソースコードをコピーし、一部手直ししたら動作しました。
修正したファイル
demo_src\r_usb_pcdc_descriptor.c
- /******************************************************************************
- User define macro definitions
- ******************************************************************************/
- /* bcdUSB */
- #define USB_BCDNUM (0x0200u)
- /* Release Number */
- #define USB_RELEASE (0x0200u)
- /* DCP max packet size */
- #define USB_DCPMAXP (64u)
- /* Configuration number */
- #define USB_CONFIGNUM (1u)
- /* Vendor ID */
- #define USB_VENDORID 0x045B
- /* Product ID */
- #define USB_PRODUCTID 0x2014
ベンダIDとプロダクトIDを手直しします。r_config\r_bsp_config.h
使用しているMPUに合わせて変更(コメント通りに変更する)
「RXマイコン基板(RX62N) | Renesas MCU Software Libraryの仮想COMポートファームウェアを試す 」にも書かれています。
手直ししたプロジェクト
改造しやすいように手直ししました。
USB機能を動作させるためには、一定間隔で次のプログラムを実行する必要があります。
- usb_cdc_driver(); /* USB Driver(Peripheral CDC) */
- switch( cdc_dev_info.state ) /* Check application state */
- {
- case STATE_DATA_TRANSFER: /* Data transfer state */
- lcd_update = cdc_data_transfer();
- break;
- case STATE_ATTACH: /* Wait Connect(USB Configured) state */
- lcd_update = cdc_connect_wait();
- break;
- case STATE_DETACH:
- cdc_detach_device(); /* Detach process */
- break;
- default:
- break;
- }
変更したプロジェクト
さらに、printf,scanfなどの標準入出力関数が使えるように変更しました。
一定間隔でusb_cdc_manage()関数を呼び出せば動作します。時間待ちの時にもこの関数を呼び出してください。
標準入出力が使えるプロジェクト
usb_cdc_manage()関数をタイマ割り込みで動かせば、プログラムが簡単にできると思い、プログラムを変更しました。タイマ割り込みで呼び出しても、問題なく動作しています。初期化のためinitUSB_cdc()関数を呼び出すだけで、パソコンとUSB通信することが可能です。
タイマ割り込みを利用したプロジェクト
Windows用デバイスドライバ
Windows用のデバイスドライバはルネサスエレクトロニクスの「RX62Nグループ、RX621グループ USBペリフェラルCDCによるフラッシュブートローダ」サンプル内に「CDC_Demo_Win7.inf」ファイルが入っています。ベンダIDとプロダクトIDをRX62Nのプログラムに合わせて書き換えます。
- ;--------------------------------------------------------
- ; Renesas
- ;
- ; Communication Device Class
- ; Virtual Serial Port
- ;
- ; 20/12/04
- ;--------------------------------------------------------
- [Version]
- Signature="$Windows NT$"
- Class=Ports
- ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
- Provider=%MANUFACTURER%
- LayoutFile=layout.inf
- ;CatalogFile=%FILENAME%.cat
- DriverVer= 3/10/2010,1.1.2600.0
- [Manufacturer]
- %MANUFACTURER%=DeviceList,NTamd64
- [DestinationDirs]
- DefaultDestDir=12
- ;--------------------------------------------------------
- ; Windows XP Support
- ;--------------------------------------------------------
- [DriverInstall.nt]
- include=mdmcpq.inf
- CopyFiles=DriverCopyFiles.nt
- AddReg=DriverInstall.nt.AddReg
- [DriverCopyFiles.nt]
- usbser.sys,,,0x20
- [DriverInstall.nt.AddReg]
- HKR,,DevLoader,,*ntkern
- HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
- HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
- [DriverInstall.nt.Services]
- AddService=usbser, 0x00000002, DriverService.nt
- [DriverService.nt]
- DisplayName=%SERVICE%
- ServiceType=1
- StartType=3
- ErrorControl=1
- ServiceBinary=%12%\%DRIVERFILENAME%.sys
- ;--------------------------------------------------------
- ; Windows Support
- ;--------------------------------------------------------
- [DriverInstall.NTamd64]
- include=mdmcpq.inf
- CopyFiles=DriverCopyFiles.NTamd64
- AddReg=DriverInstall.NTamd64.AddReg
- [DriverCopyFiles.NTamd64]
- %DRIVERFILENAME%.sys,,,0x20
- [DriverInstall.NTamd64.AddReg]
- HKR,,DevLoader,,*ntkern
- HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
- HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
- [DriverInstall.NTamd64.Services]
- AddService=usbser, 0x00000002, DriverService.NTamd64
- [DriverService.NTamd64]
- DisplayName=%SERVICE%
- ServiceType=1
- StartType=3
- ErrorControl=1
- ServiceBinary=%12%\%DRIVERFILENAME%.sys
- ;**********************************************
- ; Please change to your company's information *
- ;**********************************************
- [SourceDisksFiles]
- [SourceDisksNames]
- [DeviceList]
- %DESCRIPTION%=DriverInstall, USB\VID_045B&PID_2014
- [DeviceList.NTamd64]
- %DESCRIPTION%=DriverInstall, USB\VID_045B&PID_2014
- ;**********************************************
- ; Please change to your company's information *
- ;**********************************************
- [Strings]
- FILENAME="Renesas_cdc"
- DRIVERFILENAME ="usbser"
- MANUFACTURER="Renesas"
- INSTDISK="USB2UART"
- DESCRIPTION="CDC USB Demonstration"
- SERVICE="CDC USB Demonstration Driver"
RX62NのUSB機能を使用してRX62NをCDCデバイスにするプログラムです。基本となる部分はルネサスエレクトロニクスのサンプルプログラムを利用しました。
関数化してあるので簡単に使用することができます。
e2 studioのエクスポートしたプロジェクト
サンプルプログラム
関数化してあるので簡単に使用することができます。
e2 studioのエクスポートしたプロジェクト
サンプルプログラム
- #include <stdio.h>
- #include <stdlib.h>
- #include <machine.h>
- #include "iodefine.h"
- #include ".\USBStack\usb_hal.h"
- #include ".\USBStack\CDC\usb_cdc.h"
- void _INIT_IOLIB( void ); //プロトタイプ宣言
- int main(void)
- {
- int data;
- unsigned char c,buf[256];;
- SYSTEM.SCKCR.BIT.ICK = 0x00; //システムクロック x16 96MHz
- SYSTEM.SCKCR.BIT.PCK = 0x01; //周辺クロック x4 48MHz
- SYSTEM.SCKCR.BIT.BCK = 0x01; //外部バスクロック x4 48MHz
- /*Initialise the USB CDC Class*/
- USBCDC_Init();
- setpsw_i(); //割込み許可 clrpsw_i()割込み禁止
- _INIT_IOLIB(); // printf(),scanf()の初期化
- while(false == USBCDC_IsConnected()); //USB接続待ち
- c = charget(); //ホストから1文字入力
- printf("RX62N USB cdc test program.\n");
- while(1)
- {
- c = charget(); //ホストから1文字入力
- charput(c); //ホストに1文字出力
- printf("Input string:");
- scanf("%s",buf);
- printf("string: %s\n",buf);
- }
- }
RX62N(インターフェス2011年5月号付録)でFreeRTOSを動かしました。環境はe2 studio, renesas RXCコンパイラです。
ここにプロジェクトをエクスポートしたものを置いておきます。
ファイル構成は次の通りです。
”FreeRTOS”以下のフォルダに必要なファイルをまとめました。
”FreeRTOS/renesas”以下にウィザードが自動生成するファイルをまとめておいてあります。
”port.c”にエラーが表示されているのはインラインアセンブラを使用しているためです。

フォルダを閉じるとユーザープログラムのみでシンプルになります。

プロジェクト作成時にはできるだけ自動生成するファイルを省き、それでも作成されるものは”FreeRTOS/renesas”のファイルと被るので削除します。

ここに”FreeRTOS”フォルダ以下のファイルをドラッグアンドドロップでコピーすればFreeRTOSのインストールは終了です。
4つのタスクが違う間隔で起動と待期を繰り返しながらLEDを点滅させるプログラムは次のようになります。
ここにプロジェクトをエクスポートしたものを置いておきます。
ファイル構成は次の通りです。
”FreeRTOS”以下のフォルダに必要なファイルをまとめました。
”FreeRTOS/renesas”以下にウィザードが自動生成するファイルをまとめておいてあります。
”port.c”にエラーが表示されているのはインラインアセンブラを使用しているためです。

フォルダを閉じるとユーザープログラムのみでシンプルになります。

プロジェクト作成時にはできるだけ自動生成するファイルを省き、それでも作成されるものは”FreeRTOS/renesas”のファイルと被るので削除します。

ここに”FreeRTOS”フォルダ以下のファイルをドラッグアンドドロップでコピーすればFreeRTOSのインストールは終了です。
4つのタスクが違う間隔で起動と待期を繰り返しながらLEDを点滅させるプログラムは次のようになります。
- #include <stdio.h>
- #include "FreeRTOS/renesas/iodefine.h"
- /* Kernel includes. */
- #include "FreeRTOS/FreeRTOS.h"
- #include "FreeRTOS/task.h"
- #include "FreeRTOS/queue.h"
- void vTask1(void *pvParameters)
- {
- while(1) {
- PORTD.DR.BIT.B1 = ~PORTD.DR.BIT.B1;
- vTaskDelay(100/portTICK_PERIOD_MS);
- }
- }
- void vTask2(void *pvParameters)
- {
- while(1) {
- PORTD.DR.BIT.B2 = ~PORTD.DR.BIT.B2;
- vTaskDelay(200/portTICK_PERIOD_MS);
- }
- }
- void vTask3(void *pvParameters)
- {
- while(1) {
- PORTD.DR.BIT.B3 = ~PORTD.DR.BIT.B3;
- vTaskDelay(300/portTICK_PERIOD_MS);
- }
- }
- void vTask4(void *pvParameters)
- {
- while(1) {
- PORTD.DR.BIT.B0 = ~PORTD.DR.BIT.B0;
- vTaskDelay(400/portTICK_PERIOD_MS);
- }
- }
- void main(void)
- {
- /* Renesas provided CPU configuration routine. The clocks are configured in
- here. */
- /* Turn all LEDs off. */
- PORTD.DDR.BYTE = 0xFF; //ポートC出力
- PORTD.DR.BYTE = 0xFF; //初期値
- xTaskCreate(vTask1,"Task1",100,NULL,1,NULL);
- xTaskCreate(vTask2,"Task2",100,NULL,1,NULL);
- xTaskCreate(vTask3,"Task3",100,NULL,1,NULL);
- xTaskCreate(vTask4,"Task4",100,NULL,1,NULL);
- /* Create the queue. */
- vTaskStartScheduler();
- /* If all is well the next line of code will not be reached as the scheduler
- will be running. If the next line is reached then it is likely that there was
- insufficient heap available for the idle task to be created. */
- for( ;; );
- }
RX62Nの12bitAD変換器を動かすプログラムのサンプルです。MTU0のTGRAのコンペアマッチを使い一定間隔で変換を行います。AD変換結果の読み出しに割り込みを使用しています。
- #include <stdio.h>
- #include <machine.h>
- #include "iodefine.h"
- #include "vect.h"
- #define PCLK 48 //PCLK = 48MHz
- /*
- * MTU0の初期化
- * TGRAのコンペアマッチでAD変換をスタートさせる
- *
- * 12bit A/Dコンバータ初期化
- * AN0のみ使用
- */
- void initMTU0_S12AD(void)
- {
- MSTP(MTU0) = 0; //タイマMTU0回路動作
- MTU0.TCR.BIT.CCLR = 1; //TGRAコンペアマッチでカウンタクリア
- MTU0.TCR.BIT.CKEG = 0; //クロックエッジ選択ビット (使用しない)
- MTU0.TCR.BIT.TPSC = 3; //PCLK/64でカウント
- MTU0.TMDR.BIT.MD = 0; //通常動作
- MTU0.TIER.BIT.TTGE = 1; //A/D変換開始要求の発生を許可
- MTU0.TCNT = 0;
- MTU0.TGRA = PCLK*1000000L/64L/1000L - 1L; // PCLK = 48MHzで1秒間に1000回AD変換を行う
- MSTP(S12AD) = 0; // 12bit AD変換回路動作
- delay_ms(100); // AD変換回路が安定するのを待つ
- PORT4.DDR.BIT.B0 = 0; // AN0を使用するためデジタル入力に
- S12AD.ADCSR.BIT.CKS = 3; // クロック PCLK/1
- S12AD.ADCSR.BIT.EXTRG = 0; // A/D開始トリガ選択レジスタ(ADSTRGR)で選択されたタイマ要因による、スキャン変換の開始を選択
- S12AD.ADCSR.BIT.TRGE = 1; // 外部トリガ(ADTRG0#)または、MTU、TMRトリガによるスキャン変換を許可
- S12AD.ADCSR.BIT.ADIE = 1; // スキャン終了後のS12ADI0割り込み発生の許可
- IR(S12AD,ADI) = 0; // 割り込みフラグクリア
- IEN(S12AD,ADI) = 1; // 割込み許可
- IPR(S12AD,ADI) = 0x01; // 割り込み優先順位設定
- S12AD.ADANS.BIT.ANS = 0x01; // AN0のみ変換
- S12AD.ADCER.BIT.ADRFMT = 0; // 保存データは右詰め
- S12AD.ADSTRGR.BIT.ADSTRS = 1; // TRG0AN_0トリガで変換開始
- MTUA.TSTR.BIT.CST0 = 1; // タイマMTU0スタート
- }
- /*
- * S12AD ADI
- * AD変換終了で呼び出される割り込み関数
- * AD変換の結果を表示
- */
- //
- void Excep_S12AD_ADI(void)
- {
- int ans;
- ans = S12AD.ADDR0;
- printf("AD value %d\n",ans);
- }
- int main(void)
- {
- volatile int i;
- Initialization();
- initMTU0_S12AD(); //AD変換初期化
- printf("A/D converter test.\n");
- while (1) {
- //何もしない 割込みで動作
- }
- }
RX62Nの12bitAD変換器を動かすプログラムのサンプルです。
- #include <stdio.h>
- #include <machine.h>
- #include "iodefine.h"
- /*
- * 12bit A/Dコンバータ初期化
- * AN0のみ使用
- */
- void s12ad_init(void) {
- MSTP(S12AD) = 0;
- delay_ms(100); // AD変換回路が安定するのを待つ
- PORT4.DDR.BIT.B0 = 0; // AN0を使用するためデジタル入力に
- S12AD.ADCSR.BIT.CKS = 0x03; // クロック PCLK/1
- S12AD.ADANS.BIT.ANS = 0x01; // AN0のみ変換
- S12AD.ADCER.BIT.ADRFMT = 0; // 保存データは右詰め
- }
- /*
- * AD変換を実行
- */
- unsigned short get_s12ad(void) {
- int i;
- unsigned short adv;
- S12AD.ADCSR.BIT.ADST = 1; // AD変換開始
- while(S12AD.ADCSR.BIT.ADST==1); // AD変換が終了するのを待つ
- adv = S12AD.ADDR0; // 結果の読み出し
- return adv;
- }
- int main(void)
- {
- int adv;
- Initialization();
- s12ad_init(); //AD変換初期化
- printf("A/D converter test.\n");
- while (1) {
- adv = get_s12ad();
- printf("AD value %d\n",adv);
- delay_ms(100);
- }
- }