帰ってきたGRUB

#Windows7installbattle

アップデート失敗するうううう

ようやく終わった……

あれ、デュアルブートubuntuどこ行った?

そう!ブートローダwindowsのやつに上書きされてしまったアアアッ

GRUBの再インストール

もともとのubuntuの起動

まずはCDとかUSBから何とかしてubuntuを起動
そしたら「ディスク」(ちょっと前まで「ディスクユーティリティ」って名前だったはず……変わったのか?)を起動して元々のubuntuがどこにインストールされているかメモる。たとえば/dev/sdaだったり、僕は/dev/sdb6だった。
メモったらもう一度なんとかしてubuntuを起動。その時に、紫色の画面の下の方に丸の中の人とキーボード?が表示されてるうちにESCキーを押す。
すると起動オプションの項目が出てくるのでF6を押して起動オプションを変更する。オプションの中に

boot=casper

と書いてある部分があるので、そこを

root=さっきメモったやつ

たとえば

root=/dev/sdb6

に書き換えて起動。これで今まで使ってたubuntuが起動する。
参考URL

GRUBの再インストール

端末を立ちあげて、

sudo /usr/sbin/grub-install さっきメモったやつ

で実行。例えば

sudo /usr/sbin/grub-install /dev/sdb

みたいに。なんでさっきと違って番号がついていないのかというと、GRUBはハードディスクの先頭にインストールするけど、番号がついたらハードディスク内のパーティションを指すから……だと勝手に思ってる。

滞りなく終わったらあとは多分何とかなるんじゃないかな

注意のような覚え書き

CDやUSBから起動オプション変更でもともとのubuntuを起動した時に、LogicoolのUnifyingキーボードとマウスが動作しなかった。有線キーボードやマウスは正常に使用できた。

H8/3664FでタイマA割り込みできたよ!!!やったね!!!


何がいけなかったのか?

昨日上げたソースコードから1行ずつコメントを外して検証した結果、Count関数を用いないと(NOP();を一定回数ループさせないと)7セグメントLEDが点灯しないことが判明した。ただし判明した時点での点灯状況は数字が表示されるというものではなく、ただランダムに点灯しているような状況だった。この時は、グローバル変数の値を参照して数値を表示させるようにしており、割り込み関数内でそのグローバル変数をインクリメントしている状態だった。その後、割り込みはできたが数字として表示されない状態に。
隣の班と情報交換をし、どうやらグローバル変数が悪さをしているようだが、構造的にグローバル変数を用いずに実現させるのは難しいと考え、別の解決策をググった。
コンパイル時に、プログラムは最適化される。しかし組み込み用途では、最適化が思わぬ動作を引き起こすことがあり、無効化することが望ましい場合があるとのこと。google:h8 volatile
そこでグローバル変数volatile修飾子を付けて宣言しなおしたところ、正常に動作するようになった。

長い

グローバル変数にはvolatile付けろ。配列はダメな。

現時点でのソースコード

動いたver
時計表示のための60進数実現部分でif文が入れ子になっており、これ、なんとか短くできそう。関数化するとか。

/*
 * H8/3664F 7セグメントLEDのダイナミック点灯制御実験
 */

#include "3664.h"

//7セグメントLEDの各数字表示
#define    ZERO    0x80    //10000000    //0
#define    ONE     0xF1    //11110001    //1
#define    TWO     0x44    //01001000    //2
#define    THREE   0x60    //01100000    //3
#define    FOUR    0x31    //00110001    //4
#define    FIVE    0x22    //00100010    //5
#define    SIX     0x2     //00000010    //6
#define    SEVEN   0xB0    //10110000    //7
#define    EIGHT   0x0     //00000000    //8
#define    NINE    0x20    //00100000    //9

//7セグメントLEDの格桁に対応するポート
#define DIGIT0    0x1
#define DIGIT1    0x2
#define DIGIT2    0x4
#define DIGIT3    0x8
#define DIGIT4    0x10
#define DIGIT5    0x20
#define DIGIT6    0x40

//タイマAの割り込み要求フラグが立っている状況
#define IRRTA 0x70

//タイマAの割り込み要求を許可するflug
#define IENTA 0x40

//グローバル変数(最適化対象でない)
volatile short int disp0;
volatile short int disp1;
volatile short int disp2;
volatile short int disp3;

/*入力された数値に対応する7セグメントLEDを
 *負論理で点灯させるポート出力用の数値を返す
 */
int LightNumber( int num )
{
    int led[10] = {     ZERO , 
                        ONE , 
                        TWO , 
                        THREE , 
                        FOUR , 
                        FIVE , 
                        SIX , 
                        SEVEN , 
                        EIGHT , 
                        NINE ,
                        };
    
    return led[num];
}


/*入力された数値に対応する桁をトランジスタのスイッチングによって
 *点灯させるようにポートをセットする
 */
int LightDigit( int num )
{
    int dig[] = {   DIGIT0 , 
                    DIGIT1 , 
                    DIGIT2 , 
                    DIGIT3 , 
                    DIGIT4 , 
                    DIGIT5 , 
                    DIGIT6 ,
                    };
    
    return dig[num];
}

/*ダイナミック点灯を行う関数
 *表示する数値はグローバル変数と割り込みで更新
 */
void Count( void )
{
    int wait;
    
    //1桁目の点灯
    PDR5 = LightDigit( 0 );
    PDR8 = LightNumber( disp0 );
    
    //僅かな時間点灯させる
    for( wait = 0; wait < 10000; wait++ )
    {
        NOP();
    }
    
    //2桁目の点灯
    PDR5 = LightDigit( 1 );
    PDR8 = LightNumber( disp1 );
    
    //僅かな時間点灯させる
    for( wait = 0; wait < 10000; wait++ )
    {
        NOP();
    }
    
    //3桁目の点灯
    PDR5 = LightDigit( 2 );
    PDR8 = LightNumber( disp2 );
    
    //僅かな時間点灯させる
    for( wait = 0; wait < 10000; wait++ )
    {
        NOP();
    }
    
    //4桁目の点灯
    PDR5 = LightDigit( 3 );
    PDR8 = LightNumber( disp3 );
    
    //僅かな時間点灯させる
    for( wait = 0; wait < 10000; wait++ )
    {
        NOP();
    }
}

/*タイマーAを使用して1秒毎に割り込みを行う関数
 *これにより1秒毎にカウントアップができるようになった
 *できた
 *まあまあ理解した
 *帰れた
 */
#pragma interrupt
void int_timera( void )
{
    IRR1 &= ~IRRTA;        //タイマAの割り込み要求をクリア
    disp0++;
}

/*7セグメントLEDを0から9の順に点灯させるプログラム*/
int main()
{
    CLI();    //初期化操作のため割り込みを禁止
    
    disp0 = 0;
    disp1 = 0;
    disp2 = 0;
    disp3 = 0;
    
    /*ポート1は7セグメントLEDの数値表示に用いる
    ポート1は接触不良のため使用不可
    PMR1 = 0x00;    //汎用入出力ポートに設定
    PCR1 = 0xff;    //ポート1を全ビット出力用に使用
    PDR1 = 0x00;    //ポート1をクリア
    */
    
    //ポート5はどの7セグメントLEDを点灯させるかのトランジスタでのスイッチングに用いる
    PMR5 = 0x00;    /*汎用入出力ポートに設定*/
    PCR5 = 0xff;    /*全ビット出力用に設定*/
    PDR5 = 0x00;    /*ポート5をクリア*/
    
    //ポート8は7セグメントLEDの数値表示に用いる
    //PMR8 = 0x00;    /*ポートBは出力専用なのか?*/
    PCR8 = 0xff;      /*ポートBを全ビット出力用に使用*/
    PDR8 = 0x00;      /*ポートBをクリア*/
    
    TMA = 0x8;            //タイマーAを低速時計用クロック、速度は1秒間隔に設定
    STI();                //初期化操作終了とともに割り込みを許可
    IENR1 |= IENTA;       //タイマAの割り込みを許可
    IRR1 &= ~IRRTA;       //タイマAの割り込み要求をクリア
    
    for( ; ; )
    {
        //60進数制御if文の羅列
        //もっとスマートな書き方があるはず。関数化してしまうとか。
        if( disp0 > 9 )
        {
            disp0 = 0;
            disp1++;
            
            if( disp1 > 5 )
            {
                disp0 = 0;
                disp1 = 0;
                disp2++;
                
                if( disp2 > 9 )
                {
                    disp0 = 0;
                    disp1 = 0;
                    disp2 = 0;
                    disp3++;
                    
                    if( disp3 > 5 )
                    {
                        disp0 = 0;
                        disp1 = 0;
                        disp2 = 0;
                        disp3 = 0;
                    }
                }
            }
        }
        //ダイナミック点灯
        Count();
    }
    
}

あとはレポート書くだけ

マイコンの実験がうまくいかない

更新サボりがちなのは大目に見て

実験内容

秋月電子のAKI-H8/3664Fキット(URL)を使ってなんか作れというもの。うちの班は秒カウンタ、もし出来ればストップウォッチや時計などを作れたらいいなーなんて話し合ってた。

甘 か っ た

基本的にうまくいかない

断線

初っ端のアクシデントは断線。ジャンパワイヤの特定の色が全部断線。で、新しくもらった1セットも赤いジャンパワイヤが全て断線していたという強運っぷり。なんでや。

謎故障

3日ほど放置しておいたマイコンが、プログラム書き込み時に応答なしになる。検証したところマイコンがオシャカになっていることが発覚。

ポート死んでる

故障したので、新しいマイコンをもらったが、あるポートが使えない。死んでいる。回路とプログラム書き直し。大した痛手じゃなかったけれどもへこむ。

書いたとおりにすら

「プログラムは思ったとおりには動かない。書いたとおりに動く」という名言があるが、なんべんやっても書いたとおりにすら動いてないんじゃないか?という状況。締め切りはもうすぐ。


何をどんな感じでやっているのか

2桁の7セグメントLEDをダイナミック点灯制御でカウントアップ。その後はタイマAによる割り込みで1秒毎に表示を更新。起動時からの秒数カウンタ(00秒から99秒まで)が完成した後に随時機能追加。

行き詰まっていることろ

基本的に動作が不安定である

突然CPUからの応答がなくなったり、点灯しなくなったりする。

割り込みができない

なんでだーーまったくわからんーーーーー

どこから持ってきたのかわからないヘッダファイル

マジどこから持ってきたし……先生が書いたのかも?
ネット上で使われているのは大抵がGCC Developer Lite(URL)内の3664f.hなのだが、この実験で提供される3664f.hはなんというか提供している機能は同じだが文法が大きく違う。最大の違いはGCC Developer Liteのヘッダファイルには構造体が使われているという点。よってネット上のサンプルコードはヘッダファイルを読み比べ、書きなおさなければいけない……っていうかGCC Developer Lite使っちゃいけないのかな?

現時点でのソースコード

バックアップ代わりに。もしかしたら優しい伊達直人が間違いを指摘してくれるかもという希望を抱いて。

/*
 *H8/3664F 7セグメントLEDのダイナミック点灯制御実験
 */

#include "3664.h"

/* P11をLEDに接続、P52をSWに接続 */
#define	P1OUT	0x2	/* P11:0000,0010 */
#define	P5IN	0x4	/* P52:0000,0100 */

//7セグメントLEDの各数字表示
#define	ZERO	0x80	//10000000	//0
#define	ONE	0xF1	//11110001	//1
#define	TWO	0x44	//01001000	//2
#define	THREE	0x60	//01100000	//3
#define	FOUR	0x31	//00110001	//4
#define	FIVE	0x22	//00100010	//5
#define	SIX	0x2	//00000010	//6
#define	SEVEN	0xB0	//10110000	//7
#define	EIGHT	0x0	//00000000	//8
#define	NINE	0x20	//00100000	//9

//7セグメントLEDの格桁に対応するポート
#define DIGIT0	0x1
#define DIGIT1	0x2
#define DIGIT2	0x4
#define DIGIT3	0x8
#define DIGIT4	0x10
#define DIGIT5	0x20
#define DIGIT6	0x40

//タイマAの割り込み要求フラグが立っている状況
#define IRRTA 0x70

//タイマAの割り込み要求を許可するflug
#define IENTA 0x40

int count = 0;

/*入力された数値に対応する7セグメントLEDを
 *負論理で点灯させるポート出力用の数値を返す
 */
int LightNumber( int num )
{
    int led[10] = { 	ZERO , 
		ONE , 
		TWO , 
		THREE , 
		FOUR , 
		FIVE , 
		SIX , 
		SEVEN , 
		EIGHT , 
		NINE ,
		};
    
    return led[num];
}


/*入力された数値に対応する桁をトランジスタのスイッチングによって
 *点灯させるようにポートをセットする
 */
int LightDigit( int num )
{
    int dig[] = {	DIGIT0 , 
		DIGIT1 , 
		DIGIT2 , 
		DIGIT3 , 
		DIGIT4 , 
		DIGIT5 , 
		DIGIT6 ,
		};
    
    return dig[num];
}

/*2桁でカウント
 *00から始まって99まで進む……すすめたらいいな
 */
void Count( void )
{
    int disp[2] = { 0 , 0 };
    int i;
    int j;
    int k;
    int wait;
    
    for( ;; )
    {
        for( j = 0; j < 100; j++ )
        {
            //1桁目の点灯
            PDR5 = LightDigit( 0 );
            PDR8 = LightNumber( disp[0] );
            
            //僅かな時間点灯させる
            for( wait = 0; wait < 10000; wait++ )
            {
                NOP();
            }
            
            //2桁目の点灯
            PDR5 = LightDigit( 1 );
            PDR8 = LightNumber( disp[1] );
            
            //僅かな時間点灯させる
            for( wait = 0; wait < 10000; wait++ )
            {
                NOP();
            }
            
        }
        
        //桁制御
        disp[0]++;
        if( disp[0] > 9 )
        {
            disp[0] = 0;
            disp[1]++;
            
            if( disp[1] > 9 )
            {
                disp[0] = 0;
                disp[1] = 0;
            }
        }
    }
}

/*タイマーAを使用して1秒毎に割り込みを行う関数
 *これにより1秒毎にカウントアップができるようになる気がする
 *できてほしい
 *まだよくわかってない
 *帰りたい
 */
#pragma interrupt
void int_timera( void )
{
    IRR1 &= ~IRRTA;		/*タイマAの割り込み要求をクリア*/
    count++;
}

/*7セグメントLEDを0から9の順に点灯させるプログラム*/
int main()
{
    int wait;
    //CLI();	//初期化操作のため割り込みを禁止
    
    //ポート1は7セグメントLEDの数値表示に用いる
    //ポート1は接触不良のため使用不可
    //PMR1 = 0x00;    /*汎用入出力ポートに設定*/
    //PCR1 = 0xff;	     /*ポート1を全ビット出力用に使用*/
    //PDR1 = 0x00;    /*ポート1をクリア*/
    
    //ポート5はどの7セグメントLEDを点灯させるかのトランジスタでのスイッチングに用いる
    PMR5 = 0x00;	    /*汎用入出力ポートに設定*/
    PCR5 = 0xff;	    /*全ビット出力用に設定*/
    PDR5 = 0x00;	    /*ポート5をクリア*/
	
    //ポート8は7セグメントLEDの数値表示に用いる
    //PMR8 = 0x00;   /*ポートBは出力専用なのか?*/
    PCR8 = 0xff;        /*ポートBを全ビット出力用に使用*/
    PDR8 = 0x00;      /*ポートBをクリア*/
	
    //この下の4行はコメントを外すと動かないことから怪しいがこれがないと割り込みできない
    //TMA = 0x8;           //タイマーAを低速時計用クロック、速度は1秒間隔に設定
    //STI();                     //初期化操作終了とともに割り込みを許可
    //IENR1 |= IENTA;    //タイマAの割り込みを許可
    //IRR1 &= ~IRRTA;  //タイマAの割り込み要求をクリア
    
    //この関数ならカウントアップ可能
    //Count();
    
    //このへんから割り込みなど行いたいがうんともすんとも。
    while( 1 )
    {
        if( count > 9 )
        {
            count = 0;
        }
        
        PDR5 = LightDigit( 0 );
        PDR8 = LightNumber( count );
        //僅かな時間点灯させる
        for( wait = 0; wait < 10000; wait++ )
        {
            NOP();
        }
    }
}

台湾でのパケット通信と心配事

台湾に行く事になり、一番心配しているのが現地でのパケット通信料。
だってインターネット依存症だし。

WORLD WING

海外でのパケット通信だが、機種と使用可能な国はまあ置いといて、docomoの場合はWORLD WINGを契約していれば「海外パケ・ホーダイ」が適用され、パケット通信料が1日最大2980円になるとのこと。
WORLD WINGの月額使用料金は無料だからたいてい契約してる。だから何も考えなくても良かったかというと……ちょっとちがう

データローミング

これをONにしないとダメ。逆に、これをOFFにしたままなら海外でのパケット通信は発生しない。念の為SIM抜いたり電源切っておけばなお安心だけど。
あと、日本に帰ってきたらデータローミングはOFFること。

充電

あー

パソコン

重い

そろそろ高専祭

只今午前3時。ここ最近はずっとこんな感じ。

夏休みの宿題が全て終わるまでは更新しないと決めていて、提出したけど時間がなくてこんな時間に更新。

高専祭の実行委員になったので、毎日夜遅く(早朝)まで高専祭の準備で授業は寝てしまっている毎日。これも学校に泊まりこんで書いている。晩御飯を食べそこねたが、最寄りのコンビニの入荷は4時半だとか。はぁ。

みんな高専祭来てね!Javaカレー食べてね!