MPLABXでIO定義がエラーになりコード補完もできない状態からとりあえず脱出

カテゴリー: PIC

とりあえずコンパイラは通るんです。いままで大丈夫だったのが急にエラーがでたり、突然直ったり頭痛いです。

この現象、メジャーなMPLAB Xの不具合らしいです。

IO定義にエラーマークが付き補完が効かない

IO定義補完きかないのはきついです

通常はこのように補完が効きます。おかげでこれに頼り切りです。

ある日、突然こうなる。【Unable to resolve identifire】キターーーー

こうなる規則性がわかりませんが、日をあけてプロジェクトを開くとこうなってることも・・・

でもコンパイラは通る

自力で個別のチップ定義ファイルをインクルードで脱出!

【xc.h】インクルードしてるのに

というわけで、個別のチップ定義ファイルを(今回の例はpic16F1459.h)を自力でインクルードして解決しました。

むむっ、気のせいか以前のXC8とフォルダ構成が違うような? \procなんてあったっけ?

セッティングでコンパイラパスを指定してみるのも手か?

IO定義ファイルのパスの問題かな?とうすうす感じていますが確認はしてません。いちいちコンパイラパスを入れるのも面倒だしXC8のバージョン変わったらと思うと・・・。ならまずは目につくソースで埋め込んだほうが楽、と判断しました。

どなたか成功した方いらっしゃいましたら、ぜひご教授お願い致します。

不思議なことに一度パスすると、インクルードコメントアウトしてもエラーはでない

深く追求しませんが、一度読込まれるとプロジェクト内に固定されるのかしら?

定義ファイルを毎回インクルードして私の環境では弊害はなさそう。日にちをあけて沼にハマるのもいやなので、ソースにIO定義ファイルを読込む習慣をつけることにします。

dsPIC(XC16)でFreeRTOS。小規模システムで使う

カテゴリー: PIC

dsPIC(XC16)でFreeRTOS。xprintfを導入しfloatを扱う」の続編です。小規模システムでのRTOS実装です。H8/3664のころからキャラクタLCDの表示だけでもRTOSは有効です(当時はHOS)と、言っていましたが、同じ16ビットMCUのdsPICでRTOSの主要機能を実装してみました。

XC16はC言語onlyでC++が使えないので、クラス記述を使ったリエントラントな関数を作りづらいです。動的メモリ確保も手間がかかりますので、関数の実行終了までタスクをウエイトするのが一番簡単です。

今回のシステムは各タスク実行に余裕ある(5%以下)ので、この方法で問題ないです。

回路ブロック図

簡易ブロック図です。大袈裟な図だなあ、と言わずご覧ください。

永らく愛用していたVisio2003がwindows10では微妙な立ち位置なので、「代わりに!」と購入した「EdrawMax」で描いてます。Visioファイルとの互換性はなかなか厳しいものはありますが、描画簡単で超楽しいです。

RTOSを実装する

シングルタスクで思いつくまま作り上げていくことに慣れた身には、RTOSは頭の中で簡単に構成できません。あらかじめ設計しておかないと苦戦します。手元のメモで設計し、何度も書き直して関連性を構築します。今回もそのメモをカッコつけて「EdrawMax」で清書です。

普段はメモで終わるのでこんなことまではやりません(^^)・・・

必要な関数を抽出してみると、気を付けないといけないのは、リエントラントでない関数を複数タスクから呼ぶ場合と、ハードウエアに対応しているeepromの変数がクリティカルセクションのリスクがありそう、ぐらいでしょうか。

カッコつけて描いてみました

RTOS機能の実装

まずは、main()でRTOS機能を実装します

void main() {
    {変数の初期化を記述する}
    extern void xPortPendSVHandler( void );
    extern void xPortSysTickHandler( void );
    extern void vPortSVCHandler( void );
	// 排他セマフォ生成
	xxprMutex = xSemaphoreCreateMutex();
	xeepMutex = xSemaphoreCreateMutex();
	// タスク生成
	xTaskCreate(vTask1,"task_main",1000,NULL,1,&xTask1);
	xTaskCreate(vTask2,"task_setting",200,NULL,1,&xTask2);
	xTaskCreate(vTask3,"task_buzzer",100,NULL,3,&xTask3);
	xTaskCreate(vTaskDisp,"task_display1",200,NULL,1,&xTaskDisp);
	// キューバッファ生成
	dispQueue = xQueueCreate(15,sizeof(Qdata));		// Byte x 15
	// イベントグループ(イベントフラグ)生成
	eventFlag = xEventGroupCreate();
	//スケジューラを起動
	vTaskStartScheduler();
	for(;;);
}


メインループの周期性

便利な関数「vTaskDelayUntil()」。

システム時間が1ms単位なので、タスク内でベアメタル時間計測してもどうしてもジッタがでます。便利な関数「vTaskDelayUnti()」がありました。

計数開始に初期計測をすればあとはセットタイム自動更新するので1ms分解能で正確な周期をジッタなく刻むことができました。便利な関数ではありますがRTOS黎明期にはみなさん悩んでいたことが想像できます。

 

// 周期ディレイ(開始のスタートタイムのセットが不要)
		vTaskDelayUntil( &xLastWakeTime, 50 );  // 50ms

構造体を作る

RTOS用に作成する構造体は、Queue用とEEPROM用です。

まず、Queueデータ用バッファ。各所で使うのでtypedef宣言。

typedef union {		// Queue用のデータフォーマット
	struct {
		int	dot;	// 小数点位置
		int	data;	// data
		int	mode;	// 0:数値、1:キャラクタ
		char mess[8];
		float fval;
	};
	char	bt[sizeof(int)*3+8+sizeof(float)];	// 文字列
} Qdata;

Mutexで排他制御するEEPROMのデータバッファ

// EEPROM保存用変数
#define	EEPSIZE	sizeof(int)*12
union {
	struct {
		int	Kpu;
		int	Tiu;
		int	Tdu;
		int	Kpd;
		int	Tid;
		int	Tdd;
		int	Sv;
		int	Md;
		int	Alp;
		int	Bta;
		int	Gma;
		int	dmy;
	};
	unsigned char ech[EEPSIZE];
} eepbuf;

EEPROM変数については、実は当初は全部float(4byte)変数にしていたので、16bitMCUではクリティカルセクションになりかねないのでMutexを採用しました。今はすべての変数をintにしたので、アセンブラを見てもクリティカルにはならないと判断していますが、システム実行にかなり余裕があるのでこのままにします。

xsprintf()にMutexを適用する

CHaN氏作xsprintfは今更説明の必要はなく組み込みに欠かせない出力ルーチンですが、リエントラントではありませんので、排他制御でTask間の干渉を回避します。

今回使うのはメインタスクと設定タスクだけですが(デバッグ時、例えばEEPROMマーチングテストなど、では各所で使う)、Mutexをおまじないのように前後にTakeとGiveを付加するだけです。

		xSemaphoreTake(xxprMutex, portMAX_DELAY);	// Mutex取得
		if(dot==0) {
			xsprintf(ldtmp,"%4d  ",dt);	// for Mode
		} else if(dot==1) {
			xsprintf(ldtmp,"%5.1f` ",dt/10.0f);	// for Sv
		} else if(dot==2) {
			xsprintf(ldtmp,"%5.2f ",dt/100.0f);	// other param
		} else xsprintf(ldtmp,"%5.3f ",dt/1000.0f);
		xSemaphoreGive(xxprMutex);					// Mutex解放

ユーザー関数をリセットするモード

通常の演算関数FuncXX()は内部変数をリセットしたい場面があります。タスク間でおこなうのは面倒なのでフラグを立てて場合分けて内部リセットすることにしました。

次の項のイベントフラグと使うことにします。

イベントフラグ(event group)を使う

itronでいうところの「イベントフラグ」は、FreeRTOSでは「event group」として使います。

個々のビットはMutexで構成され、and/orの組み合わせてビット待ちができますが、下記のように単純なandでマスクすることで単なる1ビットフラグとしても使えます。

ビット幅は、「FreeRTOSconfig.h」の「#define configUSE_16_BIT_TICKS 0」で24か8の使い分けできますが、もともと8ビットで使っている分にはどちらも問題なく使えます

// フラグをセットする
xEventGroupSetBits(eventFlag,0x02); 		// フラグセット

// フラグチェックし、有効なら実行してフラグクリアする
if((ret=xEventGroupGetBits(eventFlag) & 0x02)==0x02) {
  // ビット1有効なら実行するルーチンを入れる
  xEventGroupClearBits(eventFlag,0x02);	// フラグリセット
}

キュー

ベアメタルで慣れた私にとって、キューはすごく楽しいです。だって、データが存在したときだけ稼働するのは、メモをパラパラっと書いて「印刷よろしくね!」というだけで良いのと同じですから。

渡すのが構造体なので、一般的な範囲を間違えなければ割と安全に使用できます。

 

// Queueを送る側の例
Qdata    ldqdata;

	ldqdata.dot=param[mode].dot; ldqdata.data=*param[mode].it; ldqdata.mode=mode; // Qdataに値をセット
	xQueueSendToBack(dispQueue, &ldqdata, portMAX_DELAY);

// Queueを受ける側(例:キューデータ待ちでdisplay()を呼び出す)
void vTaskDisp() {
	Qdata	queuedata;

	for(;;) {
		xQueueReceive(dispQueue, &queuedata, portMAX_DELAY);	// Queue待ち
		display(queuedata.mode,queuedata.data,queuedata.dot,queuedata.mess);
	}
}

Queueのデータをどう使うかはユーザ次第です。はじめは余分にマージン取っておいて最後に調整するのが良いです。dsPIC33CK256はメモリに比較的余裕あるので、文字列エリアを多めに確保するなどして確認しておきます。当然ですが例えば4文字は’\0’が入るので5文字分確保が必須です。

16ビットMCUでも、十分にRTOS使える

1ms分解能のリアルタイム性に「vTaskDelayUnti」が使えるのがわかった時点で、16ビットMCUでもRTOSを使おう、という意識がどんどんわいてきました。

FreeRTOSの情報は、まだ十分とはいえません。どんどん使って、どんどんアップしましょ。

dsPIC33CKのADCでオーバーサンプリングフィルタを使う

カテゴリー: PIC

dsPIC33CK256MP505では、2個のDedicated(専用)ADCと1個のShared(共用)ADCがあり、どちらもオーバーサンプリングフィルタを設定できます。今回初めて使ってみました。

いつもDedicatedADCは主にPWMトリガで電流検出に使うため、サンプルタイミングがクリティカルなのでオーバーサンプリングをしたことがありません。今回はADC1を1ms周期の普通のアナログ入力にしたので、適用してみました。

応用に使ったボードは20KHzPWMで強烈なスイッチングをしているのでセンサ入力など中・低速サンプリングには結構なノイズが乗ってきます。

続きを読む…

dsPIC(XC16)でFreeRTOS。xprintfを導入しfloatを扱う

カテゴリー: PIC

dsPIC33CKでFreeRTOSを使うの続編です。RTOSでsprintfを使いたいですが、標準入出力のprintf/scanfは共通ヒープメモリを使うのでRTOSではうまくない、とのことです。実際sprintfではうまくなかったです。そこでCHaN氏作「xprintf」の登場です。

「xprintf」はすでにPSoC5LPでFreeRTOSでも使っています。使いたい関数は、文字列に対する「xsprintf」で、今回はfloatを扱ってみます。

なお、試していませんが、一文字出力ルーチンに出力のポインタを指定すれば、LCDやUARTに直接出力することもできるらしいです。う~ん、これは凄い!

環境はMPLAB Xv5.45 XC16 v1.6です

続きを読む…

dsPIC33CKでFreeRTOSを実装

カテゴリー: PIC

以前PSoC5LPとPSoC Creater4.2にFreeRTOSを実装した記事「FreeRTOSをPSoC5LPで使う」と同様に、MPLAB XでdsPIC33CK256MP503にFreeRTOSを実装した覚書です。

使用アイテムは現時点で最新版、FreeRTOSV202012.00(カーネルはV10.4.3)、MPLAB X5.45です。 続きを読む…

久々のAKIーPICプログラマーとOTPーPIC

カテゴリー: PIC

もう20年以上続いている基板にPIC12C509A-04/Pを使っています。久しぶりに50ヶ書き込み作業です。 続きを読む…

dsPIC30F3012 DIPタイプの書き込み

カテゴリー: PIC

知人から、dsPIC30F3012の書き込みを頼まれました。普段はSOPかQFPを基板に設けたICSPコネクタで書き込んでいますが、dsPICのDIPタイプは久しぶりです。

dsPIC30F 18pinは、PIC16F/18Fの 18pinとピン配列が異なる

しばらくぶりだと、そんなことも忘れていました。そこで、手作りPIC書込みアダプタを急遽改良!

dsPIC33CK sin演算スピード・・・ドタバタ顛末記

カテゴリー: PIC,ソフトウェア

dsPIC30F/33EPからdsPIC33CKへ移行しようとしています。「sinテーブルを演算させるルーチンで意外なほど演算時間がかかった」、という投稿を最初にしたものの、完全に自分のミスであることが判明したので、投稿を全面改版し、ドタバタ顛末記として再投稿です。

事の発端は、パワーオン時にsinテーブルの計算をさせたこと

これは「パワーオンですぐに動作させる回路」プログラミング時、冒頭で、 続きを読む…

dsPIC33CK256MP503 覚書①

カテゴリー: PIC

dsPIC30FやdsPIC33EPから、dsPIC33CKへの移行の覚書です

36pin UQFNパッケージ

大きな違いは?

独断と偏見で恣意的な比較表

  dsPIC30F dsPIC33EP dsPIC33CK
MAX速度 30MIPS 70MIPS 100MIPS
Core   MUL,Divider MUL,Divider、4×割り込み退避エリア
汎用タイマ 16bit×3 16bit×3

32bit×1(CCPの汎用タイマ×2)、PTG×1

ADC

12bit 200Ksps

12bit×2+1(shared), 3.25Msps

12bit×2+1(shared), 3.25Msps

DAC non 12bit×2 12bit×3
PWM 16bit×3

HSPWM 16bit×3,up to 1.04㎱

HSPWM 16bit×8,up to 250ps

EEPROM 1Kbyte/non non non
other Function UART,SPI,I2C UART,SPI,I2C,PGA UART,SPI,I2C,CAN FD,QEI,CLC,DMA
電流 小小

 

要は、高速高機能かつ低消費電流です。 続きを読む…

dsPIC33CKをICD4でデバッグ

カテゴリー: PIC

前回投稿のICD4インプレッションの続きです

新しいdsPIC33CKで使ってみる

いま試したい機能を全部いれた試作用基板ができてきました。dsPICの他にmbed Nucleo64ボードも使えるものです。搭載dsPICデバイスは新しいシリーズの「dsPIC33CK256MP503-I/M5」。

十数年前から使っているdsPIC30Fも基板を更新するたびに、そろそろ新型dsPICへ移行したいと思っていました。基板の要求機能が増えたわけではありませんが、同じ速度(20MIPS)で消費電流が4分の1、なおかつ100MIPSまで使え、その消費電流も少ないので切替えの候補になった次第です。 続きを読む…