フォト
2017年3月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
無料ブログはココログ

STM32

2017年3月23日 (木)

次はSTM32ボードを積極的に使ていきたい(11)

Blue PillでIchigoJamのような、BASICインタプリタを動かしたいと思い、
vintagechipsさんが公開している豊四季タイニーBASICを動かしてみました。

関連情報
   ・電脳伝説 Vintagechips - 豊四季タイニーBASIC確定版

シンプルなプログラムでいい感じです。
対話型 BASICインタプリタの売り、「トライ&RUN」を行うには編集機能がちょっと弱いです。
そこで、IchigoJamのような感じでプログラム入力が出来るよう、ちょっと機能追加しました。

動画はtinyBASIC 起動直後の表示メッセージに行番号とPRINT文付けて
プログラム化してしまう操作デモです。
フルスクリーン編集対応しているからこそ出来る操作です。


MCURSESを使って手を加えただけで、結構イケてる環境にビフォー&アフターしました。
MCURSESスバラシイ..

スクリーン制御が出来ると凝ったプログラムが作れますね。
次のコマンドを追加しました。

CLS,LOCATE,COLOR,ATTR,WAIT

02_2

こんな感じで指定した位置の文字を色を付けて表示出来ます。

修正版を下記にて公開します

・Tamakichi/ttbasic_arduino 豊四季タイニーBASIC for Arduino 修正版 V0.1
  https://github.com/Tamakichi/ttbasic_arduino
まだまだ、ガンガン修正していきます.

Blue Pillでは、USBでのシリアル接続での利用となります。
Arduino MEGAでも動作しました。Arduno UNOはメモリ不足で動きません。

01_2

2017年3月16日 (木)

次はSTM32ボードを積極的に使ていきたい(10)

Blue Pillボードのフラッシュメモリの容量の確認

Blue PillボードにはARMマイコン STM32F103C8が搭載されています。

STM32F103C8は、公式にはフラッシュメモリ容量は64kバイトなのですが、
実際には128kバイトのものが流通しているとのことです。

実際にどうなのか、ちょっと確かめてしました。
まずは、搭載マイコンの刻印のチェック



STM32F103C8T6」と明記されています。

データシートにより、このマイコンのフラッシュメモリサイズは64kバイトのはずです。

03

次に、実際にフラッシュメモリサイズを128kバイトと仮定して、
その領域の最終領域のアドレス 0x801FC00 に書き込みを行ってみました。
フラッシュメモリはページ単位(1kバイト)で消去、16ビット単位で書き込みが出来ます。

04

書き込み確認用スケッチ

特定の文字列をフラッシュメモリ上の指定アドレスに書き込んで、その内容を
確認するプログラムです。
64kバイト目のページと128kバイト目のページに異なる文字列を書きこんで、
シリアル接続にて内容を確認します。

//
// FILE stm31_testFlash
// フラッシュメモリ書き込みテスト for Arduino STM32
// 作成日 2017/03/16 by たま吉さん
//

#define FLASH_PAGE_SIZE        1024
#define FLASH_START_ADDRESS    ((uint32)(0x8000000))

#include <string.h>
#include "stm32_hexedit.h"
#include "TFlash.h"

uint8_t str1[] = "1234567890A";
uint8_t str2[] = "abcdefghij";

void Arduino_putchar(uint8_t c) {
  Serial.write(c);
}

char Arduino_getchar() {
  char c;
  while (!Serial.available());
  return Serial.read();
}

uint32_t adr0 = FLASH_START_ADDRESS + FLASH_PAGE_SIZE *  63;
uint32_t adr1 = FLASH_START_ADDRESS + FLASH_PAGE_SIZE *  127;

void setup() {
  Serial.begin(115200);
  while (!Serial.isConnected()) delay(100);
  setFunction_putchar(Arduino_putchar); 
  setFunction_getchar(Arduino_getchar); 
  initscr();

  // フラッシュメモリ書き込みテスト
  TFlash.unlock();
  TFlash.eracePage(adr0);
  TFlash.write((uint16_t*)adr0, str1, strlen((char*)str1));
  TFlash.eracePage(adr1);
  TFlash.write((uint16_t*)adr1, str2, strlen((char*)str2));
  TFlash.lock();
}

void loop() {
  // 64kバイトフラッシュメモリ最終ページの参照
  clear();
  hexedit2 (adr0, false);

  // 128kバイトフラッシュメモリ最終ページの参照
  clear();
  hexedit2 (adr1, false);  
}

スケッチを実行して確認すると、64kバイト目のページ、128kバイト目のページに
それぞれちゃんと書き込めていました。

ページ63、64kバイト目のページへの書込みの確認

06

ページ127、128kバイト目のページへの書込みの確認

05

ということで、STM32F103C8T6 ですが128kバイト利用出来ます。
ただし、生産ロット・時期により64kバイトの可能性もあります。

動作確認で利用した、フラッシュメモリ書き込みは色々と使えそうなので
ライブラリ化しました。

   ・Arduino STM32用 内部フラッシュメモリ書き込みライブラリ
     https://github.com/Tamakichi/ArduinoSTM32_TFlash

     まだ、ドキュメント等は未作成です。

     動作確認したスケッチはそのまま、ライブラリのサンプルとして入れています。
     別途、mcursesライブラリ(https://github.com/ChrisMicro/mcurses)が必要です。

 

2017年3月14日 (火)

次はSTM32ボードを積極的に使ていきたい(9)

TVoutライブラリと互換性の高いライブラリ

「次はSTM32ボードを積極的に使ていきたい(7)」で作成した、
「Arduino STM32用 NTSCビデオ出力ラブラリ」の上位層のライブラリを作成しました。

Arduino用のTVoutライブラリと互換性の高いAPIを実装しました。
TVoutのソースの一部を利用しています。

02

GitHubの方に登録&公開しました。
  ・Arduino STM32 TVoutライブラリ - TTVout
   https://github.com/Tamakichi/ArduinoSTM32_TVout


サンプルスケッチの動作の様子です
(だだし、古いバージョンのものです)




回路図(接続図)は次のような感じとなります。

01
使い方等については、公開ページの説明を参照願います。


ライブラリの実装において、ARM cortex-M3のビットバンド機能を使ってみました。
メモリ上のデータをビット単位で効率よく操作する仕組みです。

具体的には、1ビット毎にワードアドレス(32ビット)を割り付け、
そのアドレスへの読み書きでビット単位の読み書きが出来る仕組みです。

ビット操作を行うドット描画部分関数sp()に適用しました。
このsp()は、直線や円等の描画にも利用しています。
以下がその関数の実装部分です。

//
// ドット描画
// 引数
//  x:横座標
//  y:縦座標
//  c:色 0:黒 1:白 それ以外:反転
//
static void inline sp(uint16_t x, uint16_t y, uint8_t c) {
#if BITBAND==1
  if (c==1)
    _adr[_width*y+ (x&0xf8) +7 -(x&7)] = 1;
  else if (c==0)
    _adr[_width*y+ (x&0xf8) +7 -(x&7)] = 0;
  else 
    _adr[_width*y+ (x&0xf8) +7 -(x&7)] ^= 1;
#else
  if (c==1)
    _screen[(x/8) + (y*_hres)] |= 0x80 >> (x&7);
  else if (c==0)
    _screen[(x/8) + (y*_hres)] &= ~0x80 >> (x&7);
  else
    _screen[(x/8) + (y*_hres)] ^= 0x80 >> (x&7);
#endif
}

BITBANDが1の場合、ビットバンドを利用してフレームバッファのビットを操作します。
BITBANDが1でない場合は、ビットバンドを利用しません。かわりにビットシフト等にて
ビット操作を行います。

上記ソースでビットバンドを利用している場合と利用していない場合で
フレームバッファのアドレスが_adr、_screenといった具合に異なるのは、ビットバンドでの
アドレス操作が32バイト単位のため、型変換とアドレス変換を行っているためです。
    _adr = (volatile uint32_t*)(BB_SRAM_BASE + ((uint32_t)_screen - BB_SRAM_REF) * 32);

画面224x216ドットを1点ずつ点を描画して全面白色処理を行った場合、
ビットバンド機能を利用すると、全体で10%くらいパフォーマンスが向上しました。
10%は大きいです。

このビットバンド機能、ARMでもCortex-M3、Cortex-M4しかないようです。

2017年3月12日 (日)

次はSTM32ボードを積極的に使ていきたい(8)

Arduino STM32環境 Blue PillボードでPWMを使った単音演奏

01

Blue Pillボード(STM32F103C8)でPWMを使った「こいのぼり」の単音演奏をやってみました。
音の出力には圧電スピーカー(圧電サウンダ)を使いました。
ゲームなんかの効果音には使えますね。

演奏の様子
(ちょっと音が小さいです)


回路図

02

スケッチ

「こいのぼり」の演奏部分はスイッチサイエンスさんのサンプルスケッチを流用させていただきました。
SWICHI SCIENCE MAGAZINE - Arduinoで童謡「鯉のぼり」を流してみよう

/*
 *  Arduino STN32
 *  Stm32ボード(STM32F103C8T6)で PWMで任意の周波数を生成する
 *  作成日 2017/01/17 by たま吉さん

 *  説明
 *  ・PB9端子の圧電スピーカーを接続することで任意の周波数を音を出す
 *  ・Timer4 チャンネル 4 を利用しているため、PWM出力ピンはPB9固定

 *  参考にした情報
 *  ・Topic: DUE PWM Frequency (Read 51962 times) 
 *    https://forum.arduino.cc/index.php?topic=131323.15
 *    
 *  サンプル作成に参考にしたサイト
 *  ・Arduinoで童謡「鯉のぼり」を流してみよう
 *    http://mag.switch-science.com/2015/04/29/gwprojact_koinobori/
 */

//
// 音出し
// 引数
//  pin     : PWM出力ピン (現状はPB9固定)
//  freq    : 出力周波数 (Hz) 15~ 50000
//  duration: 出力時間(msec)
//
const int pwmOutPin = PB9;  // PWM出力ピン
void _tone(uint8_t pin, uint16_t freq, uint16_t duration = 0) {
  if (freq < 15 || freq > 50000 ) {
     _notone(pin);
  } else {
    uint32_t f =1000000/(uint16_t)freq;
    Timer4.setPrescaleFactor(72); // システムクロックを1/72に分周
    Timer4.setOverflow(f);
    Timer4.refresh();
    Timer4.resume(); 
    pwmWrite(pin, f/2);  
    if (duration) {
      delay(duration);
      Timer4.pause(); 
    }
  }
}

//
// 音の停止
// 引数
// pin     : PWM出力ピン (現状はPB9固定)
//
void _notone(uint8_t pin) {
    Timer4.pause();  
}

//HardwareTimer pwmtimer(2);
#define PIN pwmOutPin
void setup() {  
  pinMode(pwmOutPin, PWM);
  _tone(pwmOutPin,440, 100);
  _tone(pwmOutPin,880,100);  
  delay(500);

  _tone(PIN, 330, 150);
  delay(150);
  _tone(PIN, 294, 150);
  delay(150);
  _tone(PIN, 262, 300);
  delay(300);
  _tone(PIN, 294, 300);
  delay(300);
  _tone(PIN, 330, 300);
  delay(300);
  _tone(PIN, 440, 300);
  delay(300);
  _tone(PIN, 392, 150);
  delay(300);
  _tone(PIN, 330, 150);
  delay(150);
  _tone(PIN, 330, 150);
  delay(150);
  _tone(PIN, 330, 300);
  delay(300);
  _tone(PIN, 294, 150);
  delay(150);
  _tone(PIN, 262, 150);
  delay(150);
  _tone(PIN, 294, 300);
}

void loop() {
  
}


Arduino STM32では音を出すためのAPIとしてtone()関数があります。
  参考:  ・Arduino for STM32 - tone() and notone() have been added to the libmaple core

使ってみると音がちょっと汚いです。濁ったような音です。
原因はタイマー割り込みを使って、出力をオン・オフしているためです。
他の様々な割り込みの影響により、タイミングがずれたりして濁った音になっています。
(USBシリアル、SysTicの時間処理等)

また、このやり方だとCPU負荷もそれなりにかかります。
今後のビデオ出力を使ったゲーム作成なんかに使うにはちょと問題ありです。

そこで、PWM出力に置き換えて綺麗な音が出るようにしました。
音が出ている間はCPU負荷がかかりません。

問題点としては、利用するピンが固定となることです。標準のtone()では任意のピン
を使って音が出せます。