Nucleo-F401REでpython-on-a-chip(LEDチカチカ編)

Nucleo-F401REでPythonのサブセットのpython-on-a-chipを動かしてLEDチカチカするまでの簡単な手順です。

Nucleo-F401REの入手

国内で入手できる主な通販サイトです。

USBケーブル(mini USB)は付属していませんので別途入手して下さい。

ファームウェアの更新

以下のページの手順に従ってNucleo-F401REのファームウェアを更新します。
http://mbed.org/teams/ST/wiki/Nucleo-Firmware
動画での更新手順の説明です。

Getting started with ARM mbed Integrated Development Environment
http://youtu.be/BrMw5TNQROo?t=1m39s

プログラミング

python-on-a-chipオンラインコンパイラのサイトを開く。
http://pymbed.appspot.com/ python-on-a-chip compiler for mbed

ターゲットを ST Nucleo F401RE に変更します。

以下のコードがエディタに入力されているのを確認します。

#
import mbed
import sys
myled = mbed.DigitalOut('LED1')
while 1:
    myled.write(1)
    sys.wait(200)
    myled.write(0)
    sys.wait(200)

compileボタンをクリックすると main_F401RE.bin がダウロードされるのでNUCLEOドライブに保存する。
保存が完了するとプログラムが自動実行されてLEDがチカチカします。

動画での実行手順の説明です。

スレッドとジェネレーターを使ったLチカ例。

import mbed
import sys

myled = mbed.DigitalOut('LED1')

def toggle():
    while 1:
        yield 0
        yield 1

def mythread1():
    for n in toggle():
        myled.write(n)
        sys.wait(200)

sys.runInThread(mythread1)
while 1:
    print sys.heap()
    sys.wait(1000)

MRT.cpp

#include "MRT.h"

MRT::MRT(int channel)
{
     LPC_SYSCON->SYSAHBCLKCTRL |= (1<<10); // enable MRT
     LPC_SYSCON->PRESETCTRL |= (1<<7); // reset MRT

    _ch = &LPC_MRT->Channel[channel];
    _ch->CTRL |= (1<<1); // one-shot
}

void MRT::write(uint32_t interval)
{
    _ch->INTVAL = interval | (1<<31); // and LOAD
    _ch->STAT |= 0x01;
}

int MRT::status()
{
    if (_ch->STAT & 1) {
        return IDLE;
    }
    return RUNNING;
}

void MRT::wait_ms(uint32_t timeout_ms)
{
    write((SystemCoreClock/1000) * timeout_ms);
    while(status() == RUNNING);
}

void MRT::wait_us(uint32_t timeout_us)
{
    write((SystemCoreClock/1000000) * timeout_us);
    while(status() == RUNNING);
}

uint32_t MRT::read()
{
     return _ch->TIMER;
}

MRT.h

#pragma once
#include "LPC8xx.h"

#define IDLE    0
#define RUNNING 1

class MRT {
public:
    MRT(int channel);
    /** write down counter
     * @param interval start count
     */
    void write(uint32_t interval);
    /** read down counter
     */
    uint32_t read();
    int status();
    void wait_ms(uint32_t timeout_ms);
    void wait_us(uint32_t timeout_us);
protected:
    MRT_Channel_cfg_Type* _ch;
};

Multi-Rate Timer (MRT)

#include "mbed.h"

DigitalOut led1(LED1);

extern "C" void MRT_IRQHandler()
{
    if (LPC_MRT->Channel[3].STAT & 1) {
        led1 = !led1;
        LPC_MRT->Channel[3].STAT |= 1; // clear interrupt
    }
}

int main()
{
    LPC_SYSCON->SYSAHBCLKCTRL |= 1<<10; // enable MRT
    LPC_SYSCON->PRESETCTRL |= 1<<7; // reset MRT
    LPC_MRT->Channel[3].INTVAL = (SystemCoreClock/5)|0x80000000; // 5Hz and LOAD
    LPC_MRT->Channel[3].CTRL |= 1; // enable interrupt
    NVIC_EnableIRQ(MRT_IRQn);

    while(1) {
        __wfi();
    }
}

main.cpp on LPC1114FN28

#include "mbed.h"
#include "SWDSerial.h"
SWDSerial pc;
LocalFileSystem local("local");

int main()
{
    FILE* fp = fopen("/local/MBED.HTM", "r"); // SYS_OPEN
    if (fp) {
        for(int i = 0; i < 176; i++) {
            pc.putc(fgetc(fp)); // SYS_READ,SYS_WRITEC
        }
        fclose(fp); // SYS_CLOSE
    }
    exit(0); // SYS_EXIT
}

workspace_tools/export_example.py

# export_example.py 2013/8/11
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
from os.path import join, abspath, dirname, exists
ROOT = abspath(join(dirname(__file__), ".."))
sys.path.append(ROOT)

from workspace_tools.paths import *
from workspace_tools.utils import mkdir, cmd, copy_file
from workspace_tools.export import export

from shutil import copytree

EXPORT_DIR = join(BUILD_DIR, "export_example")
USER_WORKSPACE = join(EXPORT_DIR, "user_workspace")

USR_PRJ_NAME = "example"
USER_PRJ = join(USER_WORKSPACE, USR_PRJ_NAME)
USER_LIB = join(USER_PRJ, "lib")
USER_SRC = join(USER_PRJ, "src")

TEMP = join(USER_WORKSPACE, ".temp")


def setup_test_user_prj():
    if exists(USER_PRJ):
        print 'Test user project already generated...'
        return
    
    # Build project directory structure
    for d in [USER_LIB, USER_SRC]:
        mkdir(d)
    
    # Sources
    print 'Copying sources...'
    open(join(USER_SRC, "main.cpp"), 'w').write("""#include "mbed.h"

DigitalOut myled(LED1);

int main() {
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}
""")

    #copy_file(join(TEST_DIR, "rtos", "mbed", "basic", "main.cpp"), join(USER_SRC, "main.cpp"))
    #copytree(join(LIB_DIR, "rtos"), join(USER_LIB, "rtos"))

    # FAKE BUILD URL
    open(join(USER_SRC, "mbed.bld"), 'w').write("http://mbed.org/users/mbed_official/code/mbed/builds/976df7c37ad5\n")


def fake_build_url_resolver(url):
    # FAKE BUILD URL: Ignore the URL, always return the path to the mbed library
    return {'path':MBED_LIBRARIES, 'name':'mbed'}


def test_export(toolchain, target, expected_error=None):
    if toolchain is None and target is None:
        base_dir = join(TEMP, "zip")
    else:
        base_dir = join(TEMP, toolchain, target)
    temp_dir = join(base_dir, "temp")
    mkdir(temp_dir)
    
    zip_path, report = export(USER_PRJ, USR_PRJ_NAME, toolchain, target, base_dir, temp_dir, False, fake_build_url_resolver)
    
    if report['success']:
        export_name = join(EXPORT_DIR, "%s_%s_%s.zip" % (USR_PRJ_NAME, toolchain, target))
        #cmd(["mv", zip_path, export_name])
        copy_file(zip_path, export_name)
        print "[OK]"
    else:
        if expected_error is None:
            print '[ERRROR] %s' % report['errormsg']
        else:
            if (zip_path is None) and (expected_error in report['errormsg']):
                print '[OK]'
            else:
                print '[ERROR]'
                print '    zip:', zip_path
                print '    msg:', report['errormsg']


if __name__ == '__main__':
    setup_test_user_prj()
    
    for toolchain, target in [
            ('uvision', 'LPC1768'), 
            ('uvision', 'KL25Z'),
            ('uvision', 'LPC1114'),
            ('uvision', 'LPC11U24'),
        ]:
        print '\n=== Exporting to "%s::%s" ===' % (toolchain, target)
        test_export(toolchain, target)