Atlas-Socソフト開発環境構築

#やること
[前回](http://qiita.com/new3bon/items/295bbd4906468ee9a42f)セルフコンパイルを試したけど、SDカードを外してPCでソースを編集するのが面倒くさいのでsambaを導入します。
FPGAのバイナリもsamba経由で書き込めるようにします。
lwコマンドもモジュールを分離して次につなげます。

#SDカードを焼く
最初からやり直すためにイメージから焼き直します。
まだ最新はV1.1ですね。
`sudo dd if=atlas_sdcard_v1.1.img of=/dev/sdb bs=1M`
PCでやる作業です。

#Atlas-SoCの起動
PCからSDカードを抜いてAtlas-SoCに刺します。ネットワークケーブルとUSBをつなげて電源を入れます。PCではminicomを起動しておきます。
以下はAtlas-SoCでの作業です。
rootでログインします。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/99409/f0dcfb0d-0075-2c41-4269-ff3f047c5c20.png)

#フォルダの作成
起動すると/home/rootの下に出るのでそこにフォルダを作ります。
`mkdir fat`
`mkdir app`

#Sambaの導入
Sambaもgccも最初から入ってました。新規インストール不要。
設定ファイルを編集します
`vi /etc/samba/smb.conf`
最後に以下を追加します。

```
[root]
    path = /home/root
    writeable = yes

```

sambaユーザを追加します。rootと言う名前にしておきます。
`smbpasswd -a root`
パスワードを求められるので適当なパスワードを入れておきます。

#fatのマウント
FPGAバイナリのATLAS_SOC_GHRD.rbfもsambaからアクセスできるようにfatパーティションをマウントします。fdiskで調べるとfatは/dev/mmcblk0p1にいます。
起動時のマウント設定ファイルを編集します。
`vi /etc/fstab`
最後に以下を追加します。

```
/dev/mmcblk0p1       /home/root/fat       auto       defaults              0  0
```

#再起動
これで設定は完了です。
再起動します
`reboot`

#PCからのアクセス
ファイルのネットワークを表示からたどっていくとアクセスできます。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/99409/f99d971e-01d3-a0ff-4ad7-fd249c613752.png)
Windows ネットワーク - MYGROUP - ATLAS_SOCKIT
その下にrootが見えるのでクリックします。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/99409/29391083-8fbd-1ca5-b5bf-8513c8a03a12.png)
パスワードが求められるのでユーザ名:root,ドメイン:MYGROUPと入力して、パスワードにsmbpasswdで入力したものを入れます。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/99409/83fe3982-6257-738e-0962-ecc15f3105fc.png)
これで先ほど作ったappとfatが見えるようになりました。
fatにはSDカードのFATパーティションが見えています。
FPGAバイナリは
fat/ATLAS_SOC_GHRD/output_files/ATLAS_SOC_GHRD.rbf
にあります。これを書き換えて再起動すると新しいFPGAバイナリを試せます。

#lwソースの整備
Lightweight FPGA Slavesにアクセスするlwプログラムを整理します。他でも使えそうなコードを別ファイルに分けました。
appの下にテキストファイルを作って、以下をubuntuのgeditで書きました。

```c:lw.c
#include <stdio.h>
#include <stdlib.h>
#include <error.h>

#include "lw_driver.h"

int main(int argc, char ** argv)
{
    uint32_t adrs,data;

    // 引数チェック
    if(argc!=2 && argc!=3)
    {
        printf("lw adrs [data]\n");
        exit(EXIT_FAILURE);
    }
 
 	// lwドライバをオープンする   
    if(open_lw())
    	exit(EXIT_FAILURE);

	sscanf(argv[1], "%x", &adrs);
	
	// 引数が3つの時は書き込み,2つの時は読み込み
	if(argc==3)	// write
	{
		sscanf(argv[2], "%x", &data);
		write_lw(adrs, data);
		printf("write ");
	}
	else		// read
	{
		data = read_lw(adrs);
		printf("read ");
	}
	printf("adrs:%08x data:%08x\n", adrs, data);		

	close_lw();
    exit(EXIT_SUCCESS);
}
```

```c:lw_driver.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#include "lw_driver.h"

// The start address and length of the Lightweight bridge
#define HPS_TO_FPGA_LW_BASE 0xFF200000
#define HPS_TO_FPGA_LW_SPAN 0x00020000

int devmem_fd = 0;
void *lw_bridge_map = 0;

// lwドライバを開く 
// エラーが起きたら１を返す
int open_lw(void)
{
    int result, i;
    
    if(devmem_fd || lw_bridge_map)
    	return 1;
    
    // Open up the /dev/mem device (aka, RAM)
    devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if(devmem_fd < 0) {
        perror("devmem open");
        return 1;
    }

    // mmap() the entire address space of the Lightweight bridge so we can access our custom module 
    lw_bridge_map = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE); 
    if(lw_bridge_map == MAP_FAILED) {
        perror("devmem mmap");
        close(devmem_fd);
        return 1;
    }
    return 0;    
}

// 書き込み
void write_lw(uint32_t adrs, uint32_t data)
{
	if(lw_bridge_map==0)
		return;
	
	*((uint32_t*)lw_bridge_map + adrs) = data;	// FPGAへの書き込み
}

// 読み込み
uint32_t read_lw(uint32_t adrs)
{
	if(lw_bridge_map==0)
		return 0;

	return *((uint32_t*)lw_bridge_map + adrs);	// FPGAからの読み込み
}

// クローズ
void close_lw(void)
{
    munmap(lw_bridge_map, HPS_TO_FPGA_LW_SPAN); 
    close(devmem_fd);
}
```

```c:lw_driver.h
// lwドライバ
#include <stdint.h>

int open_lw(void);							// lwドライバを開く 
void write_lw(uint32_t adrs, uint32_t data);// 書き込み
uint32_t read_lw(uint32_t adrs);			// 読み込み
void close_lw(void);						// クローズ
```

#コンパイル
Atlas-SoCの上でコンパイルします。
rootでログインした後、
`cd app`
`gcc lw.c lw_driver.c -o lw`
これでlwコマンドが準備できました。
今回、アドレスは32bit換算にしました。