BS21 Lab の製品 - Arduino 用 CPU パワーアップ基板(製品番号:BS21LAB-004)

31/jan/2013 新規
26/dec/2015 更新

Arduino の CPU 能力をパワーアップする基板です。

  1. 概要
  2. 御注意
  3. ギャラリー
  4. FAQ
  5. ご購入方法
  6. 注意事項
  7. 免責事項
  8. 仕様
  9. 組立て方法
  10. ソフトウェア
  11. Uno1284P の入出力
  12. Arduino ピン配置リスト
  13. PWM について
  14. SPI について
  15. TWI (i2c) について
  16. メモリマップ
  17. HIGH_PROGMEM について
  18. 参考リンク

・概要

本基板 (Atmel 製 ATmega1284P:以下「Uno1284P 基板」と呼びます) を、Arduino UNO R3 の DIP 28ピン CPU (Atmel 製 ATmega328P) と換装させる事で、 Arduino の CPU 能力をパワーアップさせます。
プログラムメモリは 128 kB (Arduino UNO R3 と比べて、4倍)、SRAM は 16 kB (同8倍)、EEPROM は 4kB (同4倍)、I/O は32点 (同+12点) に強化されます。
ブートローダー(Optiboot, 1kBサイズ) 書き込み済みですので、組み立てて換装すれば、即、動きます。

御注意!!:CPU が表面実装タイプの Arduino では、本基板は換装できません!!DIP タイプのみ換装可能です。

本製品は組み立て式キットとなっています。組み立て方は組立て方法を御覧下さい。


・御注意

2015/12/26 追記:Arduino IDE 1.6.7 に暫定対応しました。

2014/2/3 追記:Arduino IDE 付属の SoftwareSerial ライブラリと GSM ライブラリで、コンパイルが通らなかったバグを修正しました。

2013/7/10 追記:SPI 通信機能において、Arduino UNO R3 と非互換な部分が有る事が判明しました。 詳細は、後述の SPI について をご覧下さい。


・ギャラリー

Arduino UNO R3 の ATmega328P を取り外して、Uno1284P 基板に換装させます。
CPU 取り外し Uno1284P 基板に差し替えた

プログラムメモリは 130,048 バイトまで使えるようになります。SRAM も 16,384 バイトまで確保できます(スタック領域含む)。 ※「漢字 LCD シールド」については、こちらのページを御覧下さい。
Flashメモリ129482バイト SRAM10000バイト

PWM も8チャンネルあるので、LED 8個を PWM 駆動させてみました。(動画ファイル(.mov 形式) 10秒, 6.45MB)
LED 8個をPWM駆動

単独では、こんな形状です。この状態では何もできません。
単独の写真

表面実装部品のみ実装済みです。スルーホール部品はハンダ付け作業が必要になります。
部品写真

秋月電子通商殿の AE-ATmega 基板に実装してみました。(同じ緑色基板なので見分けづらくてすみません。) ※本当は外部電源入力部(写真左下の部品記号 DC から C6)が有るはずですが、手抜きで部品を実装していません。
AE-ATmega 表面

同じく裏面。Uno1284P 基板と干渉するので、Reset スイッチ等は裏面に実装する様にしました。(写真左上の X4 ピン(TX/RX/RST)も、L型2x3ピンを裏面に外向きで実装しましたが、 そうそうショートを外す事はないので、出っ張らない様に内向きに実装した方がよかったかも。)
AE-ATmega 裏面

・FAQ

QA
なぜ Arduino 互換機ではなく、CPU 換装基板なのですか? その方が安上がりだからです。現状、Arduino UNO R3 が 3000円以下、これに Uno1284P 基板を加えても 6000円を切りますが、 Arduino 互換機にした場合、相当数が見込めないと、この値段以下にするのは難しいだろう、と判断しました。
既に Arduino Mega2560 R3 があるじゃないか。これって必要? @ Arduino Mega よりも小型にできる
A Arduino Mega よりもシールドの互換性が高い(ハズ)
B SRAM が 16kB と大きい
Sanguino と、どう違うの? ピンの並びが違っています。そもそも Sanguino 基板は Arduino 用シールドが物理的に挿さりません。
Bobuino と、どう違うの? ピンの並びが違っています。当初、Bobuino とピン並びを一緒にしようかと思っていたのですが、Bobuino の PWM のピン配置が Arduino 互換で無いので、 色々と見直していくうちに、全然別物になってしまいました。
スライドスイッチを手で切り替えるのが面倒くさい 追加された I/O 12点から3点割り振って、自動切換えさせる、というのは考えたのですが、その為の部品によるコストアップ、Arduino IDE の改造やライブラリの追加、 3点の I/O が自由に使えなくなる事、そして、そもそも頻繁に切り替える事はあるのか?と考えて、結局、手で切り替える方法にしました。


・ご購入方法

本製品は、以下のサイトで取り扱って頂いております。

(株)スイッチサイエンス様


・注意事項

本製品は、電源を OFF にした状態で、スライド SW の切り替えを行ってください。通電中にスライド SW を切り替えますと、IC 等を破壊する恐れがあります。
電源を OFF にした状態でも、スライド SW を切り替える時は、静電気を逃がしてから行ってください。

また、本製品は端子等が露出しており、ショートなどで容易に故障しやすくなっておりますので、取り扱いには十分に注意してください。

鋭利な部分も多数有りますので、怪我等に十分に注意してください。


・免責事項

本製品は人命等に関わる装置への利用につきまして、考慮されておりません
また、本製品を使用した事によって発生しました如何なる事象につきまして、弊社は責任を負いかねますので御了承下さい。


・仕様

寸法幅約49mm×長さ約35.6mm 
高さ約7.5mm ※ スライドSW から ピンヘッダーの根元まで(更に ICソケットに挿さるピン長が約4mm あります)
固定方法DIP 28ピン ※ IC ソケットに挿入して、固定させます
駆動電圧直流+5V ※ +3.3V での動作は未確認です
確認した基板Arduino UNO R3
AE-ATmega 基板
 ※ これ以外の基板では、物理的に挿さるかどうかを含めて、確認しておりません。


・Arduino UNO との比較表
 Arduino UNO R3 Uno1284P コメント
CPU 型番 ATmega328P ATmega1284P Atmel 社製
Flash 容量 32 kB 128 kB 4倍 ※但し 1kB はブートローダー領域に使用済み
SRAM 容量 2 kB 16 kB 8倍
EEPROM 容量 1 kB 4 kB 4倍
I/O 点数 20点 32点 +12点 (D14〜D23, A6〜A7 が追加)
├ ADC 点数 6点 8点 +2点 (A6〜A7 が追加)
├ PWM 点数 6点 8点 +2点
└ 割込み点数 2点 3点 +1点 (INT2 が追加)
ブートローダー Optiboot, 512Bサイズ Optiboot, 1kBサイズ ※ ATmega1284P の仕様上、ブートローダー領域は 1kB が最小で、512B に設定できません。


表面実装部品のみ実装された状態の Uno1284P 基板の写真です。
Uno1284P 基板:表面実装部品のみ実装状態

ピンの機能切り替えに合わせて、Uno1284P 基板上の3つのスライドSW を、設定し直す必要があります。自動では切り替わりませんので、御注意下さい。
後述の PWM について 及び、TWI (i2c) について も参照下さい。
 左側説明 右側説明
SW1 PWM11pin11 を PWM 出力にします。
SPI 通信は不可になります。
 SPISPI 通信する時は、こちらに設定します。
代替機能:pin8 が PWM 出力可能です。
SW2 PWM3pin3 を PWM 出力にします。
代替機能:pin4 が INT1 割込みになります。
 INTpin3 を INT1 割込みにします。
代替機能:pin4 が PWM 出力可能です。
SW3 TWIpin A4/A5 を TWI 通信にします。
アナログ入力 A4/A5 は EXT2 のみ、になります。
 ANApin A4/A5 をアナログ入力 A4/A5 にします。
TWI 通信は EXT3 を使えば、引き続き使用可能です。


基板設計の関係で、アナログ入力の配線を長くせざるを得なくなってしまいました。この為、アナログ入力の精度が悪くなっている可能性が有ります。


また、可能な限り、背を低くしたのですが、それでもシールドによっては干渉してしまいます(Ether シールド位、背が高ければ干渉しません)。
その場合は、足長ピンソケットを間に挟んで、延長させると良いでしょう。
ピンソケット延長


<動作確認>
以下の時での動作を確認しています。

・Arduino UNO R3 (CLK=16MHz), 秋月電子通商 AE-ATmega 基板 (CLK=16MHz)
・Vcc = 5V
・Arduino IDE 1.0.3 or 1.0.5
・Windows 7 Home Premium SP1 (64 bit)


回路図:
Uno128P 基板の回路図


・組立て方法

別ページにしました。「Arduino 用 CPU パワーアップ基板」の組立て方法 をクリックしてください。


・ソフトウェア

Uno1284P 基板を利用する為には、Arduino IDE にファイルの追加、及び、修正する必要があります。
(本当は arduino.cc に追加依頼したい所ですが、如何せん Uno1284P の数が出ない事には、相手にされない気がしますので、当面は手修正で御願いします)
以下の圧縮ファイルをダウンロードし、一旦、適当な作業用フォルダーの中に解凍してください。

BS21Lab-for_Uno1284P_diff_in_ArduinoIDE105-140203.zip 2014年2月3日版 ※SoftwareSerial ライブラリと GSM ライブラリでコンパイルが通らなかったバグを修正しました

以下の圧縮ファイルはデモ・スケッチです。Arduino IDE を改造後に、Uno1284P 用のスケッチを作成する時の参考にして下さい。
BS21Lab-Uno1284P-DemoSketches-130202.zip 2013年2月2日版

※ 両方とも Arduino IDE 1.0.5 でのみ動作確認しています。(Arduino IDE 1.5.5 では未確認です。)

<追加>
Arduino IDE 1.6.7 用の暫定版です。
BS21Lab-for_Uno1284P_diff_in_ArduinoIDE167-151226.zip 2015年12月26日版 ※暫定版です

【御注意】
Windows 用の Arduino IDE でしか動作確認していません。もしかすると、Mac 用や Linux 用の Arduino IDE では、問題が発生するかもしれません。 その際は、御連絡下さい。可能な限り対応してみます。(頑張ったが無理だった、という結果になる可能性もあります…)


※ 以下では、Arduino IDE を C:\arduino フォルダーにインストールしているものとして書いてありますので、適宜、読み替えてください。

1.C:\arduino\hardware\arduino\boards.txt 書き換え方法:
boards.txt をテキストエディタ等で開いて、3行目に以下を追加します(コピペでOK)。 もしくは、解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\add_def_to_boards.txt をエディタで開いてコピペしても OK です。他の部分は変更しないようにして下さい。
##############################################################

uno1284p.name=Uno1284P

uno1284p.upload.protocol=arduino
uno1284p.upload.maximum_size=130048
uno1284p.upload.speed=115200

uno1284p.bootloader.low_fuses=0xFF
uno1284p.bootloader.high_fuses=0xDE
uno1284p.bootloader.extended_fuses=0xFD
uno1284p.bootloader.path=optiboot_uno1284p
uno1284p.bootloader.file=optiboot_uno1284p.hex
uno1284p.bootloader.unlock_bits=0xFF
uno1284p.bootloader.lock_bits=0xCF

uno1284p.build.mcu=atmega1284p
uno1284p.build.f_cpu=16000000L
uno1284p.build.core=arduino
uno1284p.build.variant=uno1284p

2.C:\arduino\hardware\arduino\variants\uno1284p\pins_arduino.h 追加方法:
C:\arduino\hardware\arduino\variants フォルダ内に、新規に uno1284p フォルダを作成し、 解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\variants\uno1284p\pins_arduino.txt をファイルのままコピーしてください。

3.C:\arduino\hardware\arduino\cores\arduino\PWM_pins.h 追加方法:
C:\arduino\hardware\arduino\cores\arduino フォルダ内に、 解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\cores\arduino\PWM_pins.h をファイルのままコピーしてください。

4.C:\arduino\hardware\arduino\bootloaders\optiboot_uno1284p フォルダの追加方法:
C:\arduino\hardware\arduino\bootloaders フォルダ内に、新規に optiboot_uno1284p フォルダを作成し、 解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\bootloaders\optiboot_uno1284p フォルダ内の 13 個のファイルを、そのままコピーしてください。

5.C:\arduino\libraries\Firmata\Boards.h の修正方法:
テキストエディタ等で開き、280行目の「// anything else」の前に、以下の記述を追加してください(コピペでOK)。 もしくは、解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\variants\uno1284p\add_def_to_lib_Firmata_Boards.txt をエディタで開いてコピペしても OK です。
// Uno1284P
#elif defined(__AVR_ATmega1284P_UNO1284P__)
#define TOTAL_ANALOG_PINS       8
#define TOTAL_PINS              32 // 24 digital + 8 analog
#define VERSION_BLINK_PIN       13
#define IS_PIN_DIGITAL(p)       ((p) >= 2 && (p) < TOTAL_PINS)
#define IS_PIN_ANALOG(p)        ((p) >= 24 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p)           digitalPinHasPWM(p)
#define IS_PIN_SERVO(p)         (IS_PIN_DIGITAL(p) && ((p) - 2) < MAX_SERVOS)
#define IS_PIN_I2C(p)           ((p) == 16 || (p) == 17)
#define PIN_TO_DIGITAL(p)       (p)
#define PIN_TO_ANALOG(p)        ((p) - 24)
#define PIN_TO_PWM(p)           PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p)         ((p) - 2)

6.C:\arduino\libraries\SD\utility\Sd2PinMap.h の修正方法:
テキストエディタ等で開き、270行目の「#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)」の前に、以下の記述を追加してください(コピペでOK)。 もしくは、解凍した for_Uno1284P_diff_in_ArduinoIDE105\hardware\arduino\variants\uno1284p\add_def_to_lib_SD_utility_Sd2PinMap.txt をエディタで開いてコピペしても OK です。
#elif defined(__AVR_ATmega1284P_UNO1284P__)
// Uno1284P

// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 17;
uint8_t const SCL_PIN = 16;

// SPI port
uint8_t const SS_PIN   = 10;
uint8_t const MOSI_PIN = 11;
uint8_t const MISO_PIN = 12;
uint8_t const SCK_PIN  = 13;

static const pin_map_t digitalPinMap[] = {
  {&DDRD, &PIND, &PORTD, 0},  // D0  0
  {&DDRD, &PIND, &PORTD, 1},  // D1  1
  {&DDRD, &PIND, &PORTD, 2},  // D2  2
  {&DDRD, &PIND, &PORTD, 3},  // D3  3
  {&DDRD, &PIND, &PORTD, 7},  // D7  4

  {&DDRB, &PINB, &PORTB, 4},  // B4  5
  {&DDRB, &PINB, &PORTB, 3},  // B3  6
  {&DDRB, &PINB, &PORTB, 2},  // B2  7

  {&DDRD, &PIND, &PORTD, 6},  // D6  8
  {&DDRD, &PIND, &PORTD, 5},  // D5  9
  {&DDRD, &PIND, &PORTD, 4},  // D4 10

  {&DDRB, &PINB, &PORTB, 5},  // B5 11
  {&DDRB, &PINB, &PORTB, 6},  // B6 12
  {&DDRB, &PINB, &PORTB, 7},  // B7 13
  {&DDRB, &PINB, &PORTB, 0},  // B0 14
  {&DDRB, &PINB, &PORTB, 1},  // B1 15

  {&DDRC, &PINC, &PORTC, 0},  // C0 16
  {&DDRC, &PINC, &PORTC, 1},  // C1 17
  {&DDRC, &PINC, &PORTC, 2},  // C2 18
  {&DDRC, &PINC, &PORTC, 3},  // C3 19
  {&DDRC, &PINC, &PORTC, 4},  // C4 20
  {&DDRC, &PINC, &PORTC, 5},  // C5 21
  {&DDRC, &PINC, &PORTC, 6},  // C6 22
  {&DDRC, &PINC, &PORTC, 7},  // C7 23

  {&DDRA, &PINA, &PORTA, 0},  // A0 24
  {&DDRA, &PINA, &PORTA, 1},  // A1 25
  {&DDRA, &PINA, &PORTA, 2},  // A2 26
  {&DDRA, &PINA, &PORTA, 3},  // A3 27
  {&DDRA, &PINA, &PORTA, 6},  // A6 28
  {&DDRA, &PINA, &PORTA, 7},  // A7 29
  {&DDRA, &PINA, &PORTA, 4},  // A4 30
  {&DDRA, &PINA, &PORTA, 5},  // A5 31
};
//------------------------------------------------------------------------------

7.C:\arduino\libraries\Ethernet\utility\w5100.h の修正方法:
テキストエディタ等で開き、338行目の「#else」の前に、以下の記述を追加してください(コピペでOK)。
#elif defined(__AVR_ATmega1284P_UNO1284P__)
  inline static void initSS()    { DDRD  |=  _BV(4); };
  inline static void setSS()     { PORTD &= ~_BV(4); };
  inline static void resetSS()   { PORTD |=  _BV(4); };

8.C:\arduino\libraries\Robot_Control\SdCard.h の修正方法(Arduino IDE 1.0.5 のみ):
テキストエディタ等で開き、32行目の「||defined(__AVR_ATmega328P__)」を、以下の様に修正してください(コピペでOK)。
||defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1284P_UNO1284P__)
※ ただし、この Arduino Robot の CPU は ATmega32u4 であり、Uno1284P に交換不可能っぽいので、上記7の修正はやらなくても支障無いと思います。

9.TFTLCD_ST7781 ライブラリを使用している場合のみ:
aitendo さんで販売されている2.6インチ液晶 for Arduino UNO [UNO026LCD7781TP] などで使用可能な yamsam/TFTLCD_ST7781 ・ GitHub の TFTLCD.cpp(2014/2/25版)は、そのままではコンパイルが通りません。 このファイルに置き換えてください。

また、Uno1284P 基板の3つのスイッチは、SW1:SPI 側、SW2:INT 側、SW3:ANA 側(aitendo UNO026LCD7781TP の場合)、に設定してください。

ただし、SPI 通信を使用中は、TFTLCD::readData 関数と TFTLCD::readRegister 関数は使用不可(一見動作しているように見えますがバグります)となりますので、御注意ください。 これは、デジタル5ピンに相当する PB4 ポートが、SPI 使用時には出力モードに固定になってしまうため、読み込み不可能になってしまうからです。 SPI 通信を使用しない場合は、この問題は発生しませんが、そうすると SD カードの読み書きが出来なくなってしまいます。spi.end 関数を呼べば SPI 通信は終了するので、 TFTLCD の読み込みもできるようになりますが、今度は SD カード上のファイル操作がすごく面倒になってしまいます...

10.sparkfun 製 CC3000 WiFi Arduino Shield 用 SFE_CC3000 ライブラリを使用している場合のみ:
SFE_CC3000.cpp をテキストエディタ等で開き、107 行目を、以下の様に修正してください。
   defined(__AVR_ATmega328P__) || defined (__AVR_ATmega328__) || defined(__AVR_ATmega1284P_UNO1284P__)


以上で、Arduino IDE 1.0.5 の修正は終了です。以下の様なフォルダ階層になっていれば OK です。
改造後の Arduino IDE のフォルダ階層

ただし、Arduino IDE の標準ライブラリ以外のライブラリでは、別途、対応が必要になるかもしれません。
※ もし上手くコンパイルできない場合は、defined(__AVR_ATmega1284P__) か defined(__AVR_ATmega644P__) を検索し、 そこに、defined(__AVR_ATmega1284P_UNO1284P__) を追加してみる様にして下さい。

マイコンボード選択で "Uno1284P" を選びます。一方、シリアルポート選択は Arduino UNO だった時と同じままで構わないはずです。
Arduino IDE でボード選択


・Uno1284P の入出力

極力、Arduino UNO R3 とピン配置互換になる様にしましたが、一部、非互換の部分も有りますので、注意して下さい。

<デジタル入出力>
D0〜D23 まで使用可能です。この内、D14〜D15 は拡張コネクタEXT1 に、D16(SCL兼用), D17(SDA兼用), D18〜D19 は拡張コネクタEXT3 に、D20〜D23 は拡張コネクタEXT2 に配置されます。
更に、後述の A0〜A7 を D24〜D31 として使用する事も可能です。

<アナログ入力>
A0〜A7 まで使用可能です。この内、A6〜A7 は拡張コネクタEXT1 に配置されています。また、SW3 を「ANA」側に設定している場合は pin A4 は A4、pin A5 は A5 となります。
一方、SW3 を「TWI」側に切り替えた場合は、pin A4 は SDA、pin A5 は SCL になる為、A4〜A5 は拡張コネクタEXT2 でのみ使用可能になります。 (後述の TWI (i2c) について も参照下さい。)
※ Arduino UNO 用のスケッチで、analogReference 関数で INTERNAL(内蔵基準電圧=1.1V) を使用している場合、Uno1284P では INTERNAL1V1(1.1V なので UNO と互換)か INTERNAL2V56(2.56V)のどちらかに修正する必要があります。

<シリアル通信>
pin0 が RX0、pin1 が TX0 と、Arduino 互換です。更に、pin2 に RX1、pin3 に TX1 が使用できます(HardwareSerial クラスの Serial1 で使用できると思われますが、きちんと確認していません)。

<SPI 通信>
SW1 を「SPI」側に設定する必要があります。その場合、pin11〜pin13 及び ICSP ピンでの SPI 通信が可能になります。
一方、SW1 を「PWM11」側に設定すると、MOSI が pin8 に移動してしまう為、pin11〜pin13 及び ICSP ピンでの SPI 通信は使用できなくなります。 (後述の SPI について と、PWM について も参照下さい。)

<TWI 通信>
SW3 を「TWI」側に設定する必要があります。pin A4 は SDA、pin A5 は SCL になります。この場合でも、アナログ入力 A4〜A5 は拡張コネクタEXT2 で使用可能です。
一方、SW3 を「ANA」側に設定している場合に TWI 通信させたい時は、拡張コネクタEXT3 の SCL/SDA ピンを使用する必要があります。 (UNO R3 で追加された SCL/SDA ピンソケットも A4〜A5 入力になっているので、このピンソケットでの TWI 通信はできません) (後述の TWI (i2c) について も参照下さい。)

<PWM 出力>
Arduino UNO 互換にするには、SW1 を「PWM11」側、SW2 を「PWM3」側に設定する必要があります。その場合、SPI 通信は使用できず、また、INT1割込みの互換性が無くなります。
SW1 を「SPI」側に設定している場合、pin11 は SPI 通信としてのみ使用可能で、PWM として使用できません。その代わり、pin8 が PWM として使用できます。
また、SW2 を「INT」側に設定している場合、pin3 は INT1 としてのみ使用可能で、PWM として使用できません。その代わり、pin4 が PWM として使用できます。
さらに、pin12 と pin13 を PWM として使用できます(7〜8チャンネル目)。その場合、当然ですが SPI 通信はできなくなります。 (後述の PWM について も参照下さい。)

<INT0/INT1/INT2 割込み>
Arduino 互換にするには、SW2 を「INT」側に設定する必要があります。この場合、pin2 が INT0、pin3 が INT1、pin7 が INT2 になります。
一方、SW2 を「PWM3」側に設定している場合、Arduino 互換では無くなります。この場合、pin2 が INT0、pin4 が INT1、pin7 が INT2 になります。
※注意!!:Arduino IDE 1.0.5 のバグで、INT2 のみ attachInterrupt 関数で attach したっきり、detachInterrupt 関数で detach できません。 どうしても detach しなければならない場合は、Issue 879: detachInterrupt() support missing for INT2, INT2 missing for ATmega644 を参照に、 WInterrupts.c の該当箇所を修正してください。この問題、将来の Arduino IDE で修正されるかは不明です。
⇒ 2015/12/26 追記 : Arduino IDE 1.6.7 では直った様です。

<AIN 入力>
Arduino UNO と同様に pin6 と pin7 に配置されていますが、AIN0 と AIN1 が逆転しているので、注意してください。

<T0/T1 入力>
Arduino UNO とピン互換がありません。Arduino UNO では pin4 と pin5 に配置されていますが、Uno1284P では、拡張コネクタEXT1 の pin14 と pin15 を使用しなければなりません。
実物が無いので確認できていませんが、SparkFun 製の CodecShield の回路図を見ると、WM8731 の CLKOUT 信号を pin5 の T1 へ入力している様に見えます。 もしこれが正しいのならば、SparkFun 製 CodecShield を使用する際は、何らかの対策を講じる必要があります。(もっとも Leonardo にも同じ事が言えますが)


・Arduino ピン配置リスト

ピン名称Arduino UNO R3ATmega328P Arduino Leonardo (参考)ATmega32U4 Uno1284PATmega1284PUno1284P のコメント
pin0 RX PD0 RX1/INT2 PD2 RX0/T3 PD0
pin1 TX PD1 TX1/INT3 PD3 TX0 PD1
pin2 INT0 PD2 INT1/SDA PD1 INT0/RX1 PD2
pin3 PWM (OC2B)/INT1 PD3 PWM (OC0B)/INT0/SCL PD0 INT1/TX1 PD3 SW2で pin4(PWM) とswap可能
pin4 T0/XCK PD4 ADC8/ICP1 PD4 PWM (OC2A) PD7 SW2で pin3(INT1) とswap可能
pin5 PWM (OC0B)/T1 PD5 PWM (0C3A) PC6 PWM (OC0B)/~SS PB4 SPI 使用時は出力モードのみ (2013/7/10追記)
pin6 PWM (OC0A)/AIN0 PD6 PWM (0C4D)/ADC10/T0 PD7 PWM (OC0A)/AIN1PB3
pin7 AIN1 PD7 AIN0/INT6 PE6 AIN0/INT2 PB2
pin8 ICP1/CLKO PB0 ADC11 PB4 PWM (OC2B)/ICP1PD6 SW1で pin11(MOSI) とswap可能 ※SPI 使用不能になる
pin9 PWM (OC1A) PB1 PWM (0C1A)/ADC12 PB5 PWM (OC1A) PD5
pin10 PWM (OC1B)/~SS PB2 PWM (0C1B)/ADC13 PB6 PWM (OC1B)/XCK1PD4
pin11 PWM (OC2A)/MOSI PB3 PWM (0C0A/1C)/~RTS PB7 MOSI/ICP3 PB5 SW1で pin8(PWM) とswap可能 ※SPI 使用不能になる
pin12 MISO PB4 ADC9/T1 PD6 PWM (OC3A)/MISOPB6
pin13 SCK PB5 PWM (OC4A)/ICP3/CLKO PC7 PWM (OC3B)/SCK PB7
pin14 = pin A0 PC0 MISO/PDO PB3 T0/XCK0 PB0 拡張コネクタEXT1
pin15 = pin A1 PC1 SCK/PDI PB1 T1/CLKO PB1 拡張コネクタEXT1
pin16 = pin A2 PC2 MOSI PB2 SCL PC0 拡張コネクタEXT3:SW3で pin A5(ADC7) と切替え可能
pin17 = pin A3 PC3 SS/RXLED PB0 SDA PC1 拡張コネクタEXT3:SW3で pin A4(ADC6) と切替え可能
pin18 = pin A4 PC4 = pin A0 PF7 TCK PC2 拡張コネクタEXT3
pin19 = pin A5 PC5 = pin A1 PF6 TMS PC3 拡張コネクタEXT3
pin20 = pin A2 PF5 TDO PC4 拡張コネクタEXT2
pin21 = pin A3 PF4 TDI PC5 拡張コネクタEXT2
pin22 = pin A4 PF1 TOSC1 PC6 拡張コネクタEXT2
pin23 = pin A5 PF0 TOSC2 PC7 拡張コネクタEXT2
pin A0 ADC0 PC0 ADC7/TDI PF7 ADC0 PA0
pin A1 ADC1 PC1 ADC6/TDO PF6 ADC1 PA1
pin A2 ADC2 PC2 ADC5/TMS PF5 ADC2 PA2
pin A3 ADC3 PC3 ADC4/TCK PF4 ADC3 PA3
pin A4 ADC4/SDA PC4 ADC1 PF1 ADC6 PA6 拡張コネクタEXT2:SW3で pin17(SDA) と切替え可能
pin A5 ADC5/SCL PC5 ADC0 PF0 ADC7 PA7 拡張コネクタEXT2:SW3で pin16(SCL) と切替え可能
pin A6 ADC8 (= pin4) PD4 ADC4 PA4 拡張コネクタEXT1
pin A7 ADC10 (= pin6) PD7 ADC5 PA5 拡張コネクタEXT1
pin A8 ADC11 (= pin8) PB4
pin A9 ADC12 (= pin9) PB5
pin A10 ADC13 (= pin10) PB6
pin A11 ADC9 (= pin12) PD6
pin SCL= pin A5 PC5 = pin3 PD0 = pin16 PC0 UNO R3 追加ピンソケット
pin SDA= pin A4 PC4 = pin2 PD1 = pin17 PC1 UNO R3 追加ピンソケット
pin MOSI= pin11 PB3 = pin16 PB2 = pin11 PB5 ICSP ピン
pin MISO= pin12 PB4 = pin14 PB3 = pin12 PB6 ICSP ピン
pin SCK= pin13 PB5 = pin15 PB1 = pin13 PB7 ICSP ピン

※ Leonardo も併記したので、非常に見づらくて申し訳無し。しかし、Leonardo は互換性、悪すぎな気がする…


・PWM について

最大8チャンネル使用できます。ただし、後述の通り、Uno1284P 基板上の SW1/SW2 を操作しないと、Arduino UNO R3 ピン互換になりません。

PWM_pins.h をインクルードすると、以下の様にスケッチが、若干読みやすく書けます。

使用例:
#include <Arduino.h>
#include <PWM_pins.h>

void setup()
{
}

void loop()
{
  for (int val = 0 ; val <= 255; val +=5) {
    analogWrite(PWM13, val);
    delay(30);
  }

  for (int val = 255 ; val >= 0; val -=5) {
    analogWrite(PWM13, val);
    delay(30);
  }
}

使用できる PWMx は、以下の表の通りです。一見 Uno1284P は 10 チャンネル有る様に見えますが、前述の通り、8チャンネルだけです。

 Arduino UNO R3Arduino LeonardoUno1284P 説明
PWM2 ××× 
PWM3 ○ (実際は PWM4 指定した時と同じ挙動) SW2 で切替え
PWM4 ×× SW2 で切替え
PWM5  
PWM6  
PWM7 ××× 
PWM8 ×× SW1 で切替え
PWM9  
PWM10  
PWM11 ○ (実際は PWM8 指定した時と同じ挙動) SW1 で切替え
PWM12 ×× 
PWM13 × Lチカ可能

Uno1284P の場合、PWM3 を指定しても PWM4 の時と同じ様に ATmega1284P の PD7 を駆動させます(下図で D4-PWM となっている配線)。 これを SW2 にて 3 番ピンソケット側(下図では D3-328P)に配線を切り替える事で、PWM3 を実現させています。
同様に、PWM11 を指定すると PWM8 の時と同じ様に ATmega1284P の PD6 を駆動させます(下図で D8-PWM となっている配線)が、 SW1 で 11 番ピンソケット側(下図では D11-328P)に配線を切り替える事で、PWM11 を実現させています。
この部分の回路図は、以下の様になっています。

PWM 回路図抜粋

なお、Arduino UNO 基板上の ICSP ピンは、Arduino UNO 基板上で 11〜13 番ピンソケットと配線が直結されてしまっているので、SW1 を PWM11 側に切り替えている時は、 MOSI が 8 番ピンソケットに配線されてしまう為、11〜13 番ピンソケットではもちろんの事、ICSP ピンでも SPI 通信はできなくなってしまいます。


・SPI について (2013/7/10追記)

Arduino UNO R3 では、SPI 通信用にデジタル 11番ピン〜13番ピンが使用されますが、同時に、デジタル 10番ピンが強制的に出力モードにされます。 これは 10番ピンを SPI 通信の SS 用として使用する・しないに関わらず、そうなります。

一方、Uno1284P でも同様に、SPI 通信用にデジタル 11番ピン〜13番ピンが使用されますが、同時に、デジタル5番ピンが強制的に出力モードにされます。 10番ピンではありませんので注意して下さい。

なぜこうなるかですが、Arduino UNO R3 や Uno1284P で使用している AVR CPU は仕様上、SPI マスターの時は ~SS ピンを出力モードにしておかなければいけない為です。 この ~SS ピンが、Arduino UNO R3 では 10番ピンであるのに対して、Uno1284P では5番ピンになっているため、この様な違いが生じています。

もちろん、Uno1284P でも、10番ピンを SPI 通信の SS 用として使用する事は可能です。ただし、以下の記述を、必ず行う必要があります(既に記述されていれば2回行う必要はありません)。
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

また、5番ピンは出力モードでありさえすれば、SPI 通信以外の用途に使用してもかまいません。デジタル出力どころか、PWM 出力すら可能です (SPI 通信+LED fading で動作確認しました)。

なお、以上の事は、SPI 通信を使用する時のみの話です。SPI 通信を使用しない場合は、5番ピンを入力モードで使用しても、何ら問題ありません。


※ 実は小生の勘違いで、~SS ピンは SlaveSelect の意味だから、SPI スレーブの時は必ず入力モードにして、Select されたかをチェックしないといけないが、 SPI マスターの時は特に気にする必要は無く、Arduino が 10番ピンを SS とて使用しているのは、単なる習慣によるもの、だとばかり思っておりました。 さらに Arduino Leonardo に至っては、~SS 信号はピンソケットにすら繋がっていない(RXLED に繋がっているだけ)ので、Uno1284P は SPI マスターになる事は有っても、 SPI スレーブになる事は、まず無い(せいぜい2台以上の Arduino を組み合わせる時くらい)から、~SS ピンが何番ピンに割り振られようが関係無し、と思っておりました。 AVR の仕様書を読めば、SPI 通信時には、ちゃんと出力モードにしろ、と書いてあるのに、全くもって、お恥ずかしい限りです。


・TWI (i2c) について

Arduino UNO R3 では、アナログ入力 A4/A5 と TWI (i2c) 通信は、A4/A5 ピンソケット兼用になっています。同時に両方使用する事はできません。

一方、Uno1284P では、アナログ入力 A4/A5 と TWI (i2c) 通信を同時に使用することが可能ですが、どちらを A4/A5 ピンソケットに配線するかを、SW3 を切り替える事で選択する事が可能です。 この時、選ばれなかった方は、拡張コネクタ EXT2 もしくは EXT3 で使用する事ができます。
この部分の回路図は、以下の様になっています。

TWI 回路図抜粋

なお、Arduino UNO R3 で追加された SCL/SDA ピンソケットは、Arduino UNO 基板上で A4/A5 ピンソケットと配線が直結されてしまっているので、 SCL/SDA ピンソケットを TWI 通信用+ A4/A5 ピンソケットをアナログ入力用、と言った風に、分割して使用する事はできません。


・メモリマップ

Uno1284P のメモリマップは、以下の様になります。

プログラム・メモリマップ:128kB ※ バイト・アドレスはワード・アドレスのちょうど2倍の値になります。
ワード・アドレスバイト・アドレス 使用領域名称 説明
0x0000 〜0x00000 〜 vector テーブル領域 140バイト固定サイズ
0x0046 〜0x0008C 〜 PROGMEM 領域 PROGMEM 宣言されたデータが配置される。(.progmem.data セクション)
vvvv 〜vvvv × 2 〜 関数テーブル領域 コンストラクタ/デストラクタ関数テーブルが配置される場合がある (.ctors/.dtors セクション)
存在する場合、バイト・アドレス 0x10000 を超えてはならない(超えると 100%暴走します。後述)
wwww 〜wwww × 2 〜 プログラム・コード領域 プログラム・コード開始アドレス (.init0 セクション)
0x80000x10000  ※ HIGH_PROGMEM を使用する場合は、プログラム・コードがバイト・アドレス 0x10000 を跨いでいる必要がある。
(xxxx - 1) 〜(xxxx - 1) × 2 〜  プログラム・コード終了アドレス (.fini1 セクション)
xxxx 〜xxxx × 2 〜 HIGH_PROGMEM 領域 HIGH_PROGMEM 宣言されたデータが配置される。(.fini0 セクション)
バイト・アドレス 0x10000 以上に配置されている必要がある。
yyyy 〜yyyy × 2 〜 DATA 領域の初期値 startup ルーチンで SRAM にコピーされる。コピー後は SRAM の方を Read/Write するので、ここのはアクセスされない。
zzzz 〜zzzz × 2 〜 空き領域 
0xFE00 〜0x1FC00 〜 BootLoader 領域 1kB 固定。Arduino IDE からは読み書きできません(読み書きするには AVRISP mkII 等が必要)
0xFFFF0x1FFFE Memory 末尾 
※ vvvv/wwww/xxxx/yyyy/zzzz の具体的な値は、スケッチによって変化します。

SRAM メモリマップ:16kB
バイト・アドレス 使用領域名称 説明
0x0000 〜 SFR 領域 256バイト固定サイズ
0x0100 〜 内蔵 SRAM 開始 Stack 領域含めて最大 16384 バイト
ssss 〜 Stack 領域 
0x40FF 内蔵 SRAM 末尾 
0x4100 〜 SRAM 未実装 ATmega1284P は拡張 SRAM 機能が無いので、アクセス不可
0xFFFF Memory 末尾 
※ ssss は 0x40FF から開始し、スタックの使用状態により、下位アドレスの方向に伸びていきます。


・HIGH_PROGMEM について

既存の PROGMEM 宣言だと、フラッシュメモリの前半 64kB にしか割り当てられず、後半 64kB に割り当てる事ができません (64kB 超えてもコンパイル・エラーにならないので、一見割り当てられる様に思えますが、Arduino IDE 1.0.5 で使用している avr-gcc ver.4.3.2 にはバグが有り、 PROGMEM 宣言されたデータの合計が 64kB を超えると、実行時に暴走する可能性があります。 これは startup ルーチン内の __do_global_ctors を処理する所で呼び出される __tablejump__ が、フラッシュメモリ上のコンストラクタ関数テーブルを読み出す時に、 本当は elpm 命令を使用しなければならない所を lpm 命令を使っている為、結果、おかしな値が読み出され、あらぬ所にジャンプしてしまう為です。 この問題、avr-gcc ver.4.5.4 で修正されている様ですが、残念ながら現行の Arduino IDE 1.0.5 には取り込まれていません。 参考:avr-gcc, avr-libc compiler and toolchain known bugs。 なお、DATA 領域の初期値の方は、elpm 命令が使用されているので、HIGH_PROGMEM 領域より高位アドレスに配置されても、正しく SRAM へコピーされます)。

そこで HIGH_PROGMEM 宣言を新たに追加しました。HIGH_PROGMEM 宣言すると、プログラム・コードよりも高位アドレスにデータが配置される様になります(上記のプログラム・メモリマップを参照)。 (本当は .fini0 セクションは、こういう使い方をする為のセクションでは無いのですが、これしか回避方法を思いつきませんでした。)
宣言の仕方は PROGMEM 宣言と同様で、以下の様に宣言すれば OK です。

     HIGH_PROGMEM const char abc [10000];
     HIGH_PROGMEM const uint16_t xyz [10000];

ただし、PROGMEM 宣言の時と同じ様に、HIGH_PROGMEM 宣言でも、1つの配列は最大 32767 バイトまで、です(超えると error: size of array 'xxx' is too large というコンパイル・エラーになる)。 これは、avr-gcc の制約ですので、回避する方法はありません。

また、HIGH_PROGMEM 宣言のデータを使用する時は、以下の制約が有ります。
この様に xxx_P 関数群に使えない為、xxx_P 関数群で使いたいデータは PROGMEM 宣言、pgm_read_xxx_hi 関数での使用で間に合うデータは HIGH_PROGMEM 宣言、という様に使い分ける必要があります。

UseHighProgMem 関数は、ATmega1284P の RAMPZ というレジスタを 1 に設定しているだけです。この RAMPZ は、lpm 命令に影響を与えず、elpm 命令(と spm 命令)のみに影響するレジスタです。 フラッシュメモリの 0x00000〜0x0FFFF は lpm 命令でアクセスし、0x10000〜0x1FBFF は elpm 命令でアクセスする様にすれば、RAMPZ は常に1にしてても、問題ありません。 (当然ですが、RAMPZ を変更する様な処理を行った時は、再度 UseHighProgMem 関数を呼び出す様にして下さい)

既存の pgm_read_xxx 関数群は内部で lpm 命令を使用している為、フラッシュメモリの 0x00000〜0x0FFFF しか読み出せません。
新規追加の pgm_read_xxx_hi 関数群は、elpm 命令を使用するので、フラッシュメモリの 0x10000〜0x1FBFF を読み出す事ができます (逆に RAMPZ を1に固定している為、0x00000〜0x0FFFF が読み出せない)。
既存の pgm_read_xxx_far 関数群を使えば、フラッシュメモリの全域 0x00000〜0x1FBFF を読み出す事ができますが、毎回 RAMPZ を 0 か 1 にセットするので、 その分、コードサイズが大きくなります(RAMPZ も変更されてしまいます)。

xxx_P 関数群は、内部で pgm_read_xxx 関数を呼び出している為、フラッシュメモリの 0x00000〜0x0FFFF のデータ(PROGMEM 宣言されたデータ)しかアクセスできません。 SRAM 上のデータや、フラッシュメモリの 0x10000〜0x1FBFF のデータ(HIGH_PROGMEM 宣言されたデータ)は、xxx_P 関数群ではアクセス不能です。
この為、それぞれの xxx_P 版に一対一で対応する xxx_PH 版の関数が有れば良いのですが、現状、memcpy_PH 関数以外の関数は存在しない為、 一旦 SRAM にコピーしてから、xxx 版の関数を呼び出すしかありません。
これは非常に大きな制約ですが、全ての関数の xxx_PH 版を作るのは、かなりの手間ですので、申し訳有りませんが『仕様』とさせて下さい (流石に memcpy_PH 関数だけは無いと不便すぎるので、これだけは用意しました)。

実は、最新の avr-gcc (正確には AVR Toolchain ver.3.4.1.830 に含まれているもの、と書いた方が正しいのかな?関係が複雑すぎて理解できていない)には xxx_PF 版が有る様で、 これを使えば 64kB よりも高位のアドレスに配置されたデータでもアクセスできると思われるのですが、現行の Arduino IDE 1.0.5 が使用している avr-gcc ver.4.3.2 は xxx_PF 版が無いバージョンのままです(将来の Arduino IDE でもサポートされるかは不明です)。
また、xxx_PF 版だとポインタ(uint_farptr_t)のサイズが4バイト長になる為、メモリを多く消費してしまうデメリットも有ります。

データの位置ポインタのサイズUno1284P で指定できるアドレスの範囲lpm/elpm ラッパー関数名使用可能な関数名の書式説明
SRAM 上2バイト長0x0000〜0x40FF無しxxx読み書き可
フラッシュメモリ上PROGMEM 宣言2バイト長0x000000〜0x00FFFFpgm_read_xxx 関数群xxx_P読み出しのみ
4バイト長0x000000〜0x01FBFFpgm_read_xxx_far 関数群xxx_PF (最新の avr-gcc のみ。Arduino IDE 1.0.5 では不可)
HIGH_PROGMEM 宣言2バイト長0x010000〜0x01FBFFpgm_read_xxx_hi 関数群xxx_PH (memcpy_PH 関数以外、存在しない)
4バイト長0x000000〜0x01FBFFpgm_read_xxx_far 関数群xxx_PF (最新の avr-gcc のみ。Arduino IDE 1.0.5 では不可)

さて、最大の問題が、HIGH_PROGMEM 宣言されたデータを、フラッシュメモリ上の 0x10000〜0x1FBFF に配置させる方法です。
実は、HIGH_PROGMEM 宣言は、そのデータをプログラム・コードの後ろに配置する様に指示するだけで、必ずしも 0x10000 以降に配置してくれる訳ではありません。
プログラム・コードが短い場合は、HIGH_PROGMEM 宣言しても、0x10000 よりも前に配置されてしまう可能性が大です。 この為、0x10000 以降に配置される様に、手作業でコードサイズを調整してやる必要が有ります。

具体的には、ダミーの PROGMEM 宣言のデータを作ってやって、プログラム・コードが 0x10000 の境界を跨ぐように調整します。 ただし、ダミーを含めた全ての PROGMEM 宣言のデータが 0x10000 を超えてしまわない様にする必要もあります(超えてしまうと上記の通り、実行時に暴走する可能性があります)。 この為、ダミーの PROGMEM 宣言のデータは、丁度良いサイズにする必要が有ります。

これを“勘”で調整するのは難しいので、実際は map ファイルか、lst ファイル(lss ファイルと表記されている場合もあるが、同じもの)を見て、調整させる事になります。
ところが、現状の Arduino IDE では、困った事に map も lst もどちらも作成してくれません。環境設定や preferences.txt を見ても有りません。
(追加要請自体は2年前にされている様です。Patches to fix various -W -Wall warnings, enabling -W -Wall flags, .map and .lst files, and more verbose size report を参照)
ArduinoIDE の環境設定

そこで以下の様にして lst ファイルを作成し、ダミーの PROGMEM 宣言のデータのサイズを調整して下さい (HIGH_PROGMEM 宣言を使用しない時でも、PROGMEM 宣言されたデータの合計が 64kB に近い時は、念のために確認しておいた方が良いかも)。
  1. 環境設定で「より詳細な情報を表示させる」の「コンパイル」にチェックを入れて OK を押す
  2. Arduino IDE でコンパイルさせる(当然ですがコンパイルが通るまで、バグは取り除いてください)
  3. その時、スケッチ名+.cpp.hex ファイルが作成される一時作業フォルダー名が表示されるので、Explorer でその作業フォルダーを開く
  4. スケッチ名+.cpp.elf ファイルが有るはずなので、それを C:\arduino\hardware\tools\avr\bin にコピーする
  5. コマンドプロンプトで C:\arduino\hardware\tools\avr\bin に移動し、「avr-objdump -h -S スケッチ名+.cpp.elf > スケッチ名+.cpp.lst」を実行させる。 あるいは、そういう bat ファイルを作成し実行させる
  6. 作成された スケッチ名+.cpp.lst をテキストエディタで開く
  7. stop_program_in_fini1_sec を検索する。以下の例の様に8桁の16進数が 0x0000FFFC 以上になっていれば OK です (HIGH_PROGMEM 宣言されたデータは、このアドレス+4以降に配置される為)。0x0000FFFC 未満の時はダミーデータのサイズを増やしてください。
    例≫ 00010f36 <stop_program_in_sec_fini1>:
  8. 続いて __dtors_end を検索する(本当は __init の方が良いのですが、lst ファイルに配置されないようです)。 以下の例の様に8桁の16進数が 0x00010000 以下になっていれば OK です(PROGMEM 宣言されたデータは、このアドレスより前に配置される為)。 もし 0x00010000 を超えている時はダミーデータを減らしてください。 ダミーデータのサイズが0になっても 0x00010000 を超えている時は PROGMEM 宣言されたデータが多すぎます(つまり実行時に暴走する可能性があります)。
    例≫ 0000ff38 <__dtors_end>:
  9. なお、__dtors_end が見つからず、__ctors_end のみ見つかる時は、__ctors_start == __ctors_end == __dtors_start == __dtors_end だと思われます。 この場合は、関数テーブルそのものが存在しないと思われます。よって PROGMEM 宣言されたデータの合計が 64kB を超えても、実行時に暴走する事は無いと思われます。 (もっとも、超えた部分は pgm_read_xxx 関数群でアクセスできないので、困る事に変わりありませんが)

HIGH_PROGMEM 宣言されたデータを使用できる関数:現状、以下の6関数のみ。
戻り値関数名引数 説明
voidUseHighProgMem(void) 以下の関数を使用する前に1回だけ呼び出す。(RAMPZ を1に設定するだけ)
uint8_tpgm_read_byte_hi(uint8_t *addr) addr で指定された HIGH_PROGMEM 領域のバイトデータを1つ読み出す。
uint16_tpgm_read_word_hi(uint16_t *addr) addr で指定された HIGH_PROGMEM 領域のワードデータを1つ読み出す。
uint32_tpgm_read_dword_hi(uint32_t *addr) addr で指定された HIGH_PROGMEM 領域のダブルワードデータを1つ読み出す。
floatpgm_read_float_hi(float *addr) addr で指定された HIGH_PROGMEM 領域の単精度浮動小数点データを1つ読み出す。
void *memcpy_PH(void * dest, const void * src, size_t len) src で指定された HIGH_PROGMEM 領域のデータを、SRAM 上の dest に len バイト分、コピーする。戻り値は dest そのもの。

使用例:
PROGMEM      const char str1 [32500] = "abcdefg1"; // フラッシュメモリ前半 64kB 内に配置
PROGMEM      const char str2 [32500] = "abcdefg2"; // 同上
HIGH_PROGMEM const char str3 [32500] = "abcdefg3"; // フラッシュメモリ後半 64kB 内に配置

char buff [10000]; // SRAM 上に 10000バイト確保

void setup()
{
  char ch;

  memcpy_P ( &ch, str1, 1 ); // コンパイル時の最適化で str1 が消えてしまわない為の対策
  memcpy_P ( &ch, str2, 1 ); // コンパイル時の最適化で str2 が消えてしまわない為の対策

  UseHighProgMem(); // HIGH_PROGMEM 使用時は必須
  ch = pgm_read_byte_hi ( &str3[3] ); // HIGH_PROGMEM 領域から1バイト読み出す。この場合は 'd' の文字。
  memcpy_PH ( buff, str3, sizeof(buff) ); // HIGH_PROGMEM 領域から、SRAM 上の buff に 10000 バイト分、コピー
}

void loop()
{
}
※ 2つの memcpy_P 関数が無いと、コンパイル時の最適化で str1, str2 が消えてしまい、str3 が 0x10000 以上に配置されなくなってしまいます。

コンパイルすると、以下の様にコードが生成されます(上記手法で作成した lst ファイルを参照)。この例では、関数テーブル領域はありませんでした。
00000000 <__vectors>: ※ vector テーブル領域開始アドレス
       0:   0c 94 3a 7f     jmp 0xfe74  ; 0xfe74 <__ctors_end>
(中略)
      88:   0c 94 5a 7f     jmp 0xfeb4  ; 0xfeb4 <__bad_interrupt>

0000008c <_ZL4str1>: ※ PROGMEM 領域開始アドレス。頭の _ZL4 は「const char 配列」の意味だと思われる。
      8c:   61 62 63 64 65 66 67 31 00 00 00 00 00 00 00 00     abcdefg1........
    ...

00007f80 <_ZL4str2>:
    7f80:   61 62 63 64 65 66 67 32 00 00 00 00 00 00 00 00     abcdefg2........
    ...

0000fe74 <__ctors_end>: ※ プログラム・コード領域開始アドレス。__ctors_end となっているが、本来は __init であるべき。ここが 0x00010000 以下になっていれば OK
    fe74:   11 24           eor r1, r1
(中略)
    fffe:   85 bd           out 0x25, r24   ; 37 ※ ここで 0x00010000 の境界を跨いでいる
   10000:   ee e6           ldi r30, 0x6E   ; 110
(中略)
   10074:   08 95           ret

00010076 <stop_program_in_fini1_sec>: ※ ここのアドレスが 0x0000FFFC 以上になっていれば OK
   10076:   f8 94           cli
   10078:   ff cf           rjmp    .-2         ; 0x10078 <stop_program_in_fini1_sec+0x2>

0001007a <_ZL4str3>: ※ HIGH_PROGMEM 領域開始アドレス。無事 0x00010000 以上に配置されている。
   1007a:   61 62 63 64 65 66 67 33 00 00 00 00 00 00 00 00     abcdefg3........
    ...

   17f6e:   f8 94           cli
00017f70 <__stop_program>:
   17f70:   ff cf           rjmp    .-2         ; 0x17f70 <__stop_program>


・参考リンク

本製品は、以下のリンク先を参考にして作りましたが、本製品についての御問い合わせ等は、弊社までに御願いします。

日本語:順不同。思い出せた限り。他にも参考にしたサイトあったはず。
YCIT(senshu LAB) :: Board Index ※ 一番参照したサイト。レベル高くて、小生の浅学では及びもつかないと痛感しました。
マイコン風雲録: duino系
ねむいさんのぶろぐ | AVR/ATXmega
続、avr-gccの制約 | PIC AVR 工作室 ブログ ※ avr-gcc の配列サイズが 32767 バイトまで、の記述。
メモたんく ≫ prog_char型がなくなった。 ※最新の avr-gcc だと色々変更になってしまうらしい。


英語:同じく順不同。思い出せた限り。他にも参考にしたサイトあったはず。
Arduino - HomePage
Atmel
What Is Sanguino? - Sanguino.cc ※ あちこちに名前が出ていたので、見てみたら、Arduino 用シールドが物理的に挿さらない事に気付きました。
Bobuino ※ 当初、これのピン互換にしようかと考えていた。
Steve Marple's blog: Introducing the Calunium - An Arduino clone based on the ATmega644P/ATmega1284P ※ これもピン配置の参考にした。
Arduino on ATmega1284P | maniacbug
Sanguinololu - RepRapWiki ※ 当初、これが Sanguino だと勘違いしていた。
optiboot - An optimised bootloader for Arduino platforms - Google Project Hosting
AVR Freaks ※ 広大すぎて、どこをどう見たか忘れました。
arduino - Arduino is an open-source electronics prototyping platform based on flexible, easy-to-use hardware and software
Issues ・ arduino/Arduino ・ GitHub


製品リストに戻る

Copyright (C) 2013-2015 BS21 Lab, All rights reserved.