2015年10月6日火曜日

PSoC4のClockとTimerを調べる

PSoC 4 Pioneer Kitでクロック周りをもう少し調べてみた。

システムクロックを取り出したかったがPSoC 4ではcy_clockを単純にcy_pinにつないでも出力させることはできないようだ。


一応作図はできるが、コンパイルするとエラーになる。

PSoC Sensei: Using Clocks with PSoC 4」を参考にして、ちょっと裏ワザっぽい接続にすると、クロック信号を取り出せた。


↑こういう設定する。

クロック

PSoC 4 Pioneer KitはデフォルトではSystem Clockは24MHzになっているが、PSoC CreatorのDWRエディターの「clock」タブでSystem Clockを設定できる。


IMOを48Mhzと24MHzにしてオシロで見てみた。

TopDesign


48MHz

ch1:System Clock ch2:12MHz

12MHzは参考のために出力した。誤差は
(47.91MHz - 48MHz) / 48MHz = -0.1875%
(11.98MHz - 12MHz) / 12MHz = -0.16%
24MHz

誤差
(24.02MHz - 24MHz) / 24MHz = 0.083%
(12.01MHz - 12MHz) / 12MHz = 0.083%
個体差はあるかもしれないが、24MHz駆動にしたほうが若干精度が高そうだ。

Timer/Counter


DDSのサンプリング周波数を想定してTimerを48kHzと96kHzに設定して出力波形を見てみた。(System Clockは24MHz)

TopDesign

DWR

<main.c>
 #include <project.h>  
 CY_ISR(ISR_Timer_48kHz_Handler)  
 {  
   Timer_48kHz_ClearInterrupt(Timer_48kHz_INTR_MASK_TC);  
   Pin_ISR_48kHz_Write(1u);  
   //CyDelayUs(1);  
   Pin_ISR_48kHz_Write(0u);    
 }  
 CY_ISR(ISR_Timer_96kHz_Handler)  
 {  
   Timer_96kHz_ClearInterrupt(Timer_96kHz_INTR_MASK_TC);  
   Pin_ISR_96kHz_Write(1u);  
   Pin_ISR_96kHz_Write(0u);    
 }  
 int main()  
 {  
   CyGlobalIntEnable; /* Enable global interrupts. */  
   /* Place your initialization/startup code here (e.g. MyInst_Start()) */  
   ISR_Timer_48kHz_StartEx(ISR_Timer_48kHz_Handler);  
   ISR_Timer_96kHz_StartEx(ISR_Timer_96kHz_Handler);  
   Timer_48kHz_Start();  
   Timer_96kHz_Start();  
   for(;;)  
   {  
     /* Place your application code here. */  
   }  
 }  

PSoC Creator 3.3のプロジェクト(今回はv3.3を使ってみた)
https://github.com/ryood/PSoC_ClockTest

48kHz出力


ch1:OV(Overflow) ch2:ISR

OV: (47.69kHz - 48kHz) / 48kHz = だいたい -0.646%
ISR: (47.77kHz - 48kHz) / 48kHz = だいたい -0.479%

拡大

左下の「(2)PW」はch2のパルス幅でちょうど1usになっている。「(1)PD」はch1からch2の遅れで2.340us

1usは1MHzなので24MHz駆動しているので割り込みルーチン内のPINのON/OFF処理で24Clockかかってることになるのかな?

また、割り込み発生から割り込みルーチン内の処理までは56Clockぐらい?

DebugモードでBuildしてるのでReleaseモードにすればもう少し変わるかもしれない。

ISR内で1us、Delayをかける

割り込みルーチン内でCyDelayUS(1)という処理を入れた。(1usディレイ)

「(2))PW」が3.300usになっているので、
3.30us - 1us = 2.3us
で、またそれなりのオーバーヘッドがある。

96kHz出力


OV: (95.09kHz - 96kHz) / 96kHz = だいたい -0.948%
ISR: (95.24kHz - 96kHz) / 96kHz = だいたい -0.792%
拡大

(1)PD: 2.330us
(2)PW: 1.000us
オシロ(OWON SDS7102)の精度もよくわからないが、1%ぐらいの精度は出るのかな。PSoC 4のClockの精度は±2%になっているのでこんなもんかな。

メモ:


  • 48kHzと96kHzの割り込みを両方有効化するとけっこう大きいジッターが発生
  • Debugモードで96kHzだと割り込みルーチン内の処理のタイミングがかなりシビア
<追記:2015.10.06>

ReleaseモードにしてRebuildしてみたが、タイミングの変化なし。


メモリーの使用量は
Release Mode: Flash: 2048B SRAM:1436
Debug Mode: Flash 2304B SRAM:1436
</追記>