0

e2 studio を使用して Renesas Synergy SK-S7G2 ボードで動作するように、arduino 用の Lmic ライブラリ ビルド ( https://github.com/matthijskooijman/arduino-lmic ) を実行しようとしています。hal.cpp ファイルを変更したところ、コードが完全に実行され、TTN ネットワークでアップリンク メッセージが表示されるようになりました。私が直面している問題は、私のフレームが aes 暗号化の間で何らかの形で変化していることです (私の推測)。暗号化の前に確認したところ、LMIC.frame[6]と のLMIC.frame[7]値が示されています0x00が、何らかの理由で、TTN ネットワークで受信しているのは です0xFF。このため、TTN の cnt65535が最初のカウントとして表示されます。

ライブラリには使用できる 2 つの aes メソッドがあり、両方を試しましたが、同じ結果が得られました。

これまでに思いついた理由は次のとおりです。

  1. ライブラリは8ビットarduinoを対象としているため、32ビットarm m4プロセッサが原因である可能性があります(ただし、ライブラリにはaes用の32ビットプロセッサバージョンもあり、それも試しましたが同じ結果が得られました)
  2. 私のhal_ticks()機能は、本来すべきことをまだ行っていません。

どなたかからの情報提供をお待ちしております。以下に、e2 studio のコンソール出力と、TTN ネットワークで受信した物理ペイロードを示します。作成した hal.c ファイルも添付します。

前もって感謝します

TTN で受信した物理ペイロード

406511012680 FFFF 0171F9EF1810C3B61F4D4EDE940844A945CE

e2 studio で実行中のコンソール メッセージ

Starting..
Time: 0
RXMODE_RSSI
5824: engineUpdate, opmode=0x808
7349: TXMODE, freq=868100000, len=26, SF=7, BW=125, CR=4/5, IH=0
Packet queued
42111: RXMODE_SINGLE, freq=868100000, SF=7, BW=125, CR=4/5, IH=0
73505: RXMODE_SINGLE, freq=869525000, SF=9, BW=125, CR=4/5, IH=0
75435Event
EV_TXCOMPLETE (includes waiting for RX windows)
79028: engineUpdate, opmode=0x900

hal.c ファイル

/*
 * hal.c
 *
 *  Created on: Jul 4, 2019
 *      Author: areeb
 */


/*******************************************************************************
 * Copyright (c) 2015 Matthijs Kooijman
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * This the HAL to run LMIC on top of the Arduino environment.
 *******************************************************************************/


#include <hal/hal.h>
#include "hal_data.h"
#include <stdio.h>
#include "../lmic/lmic.h"

ssp_err_t err;
u4_t t ;
unsigned int ticks=0, fg=0;

u2_t  cnt=0 ;

uint32_t scaled = 0, ch=0;

static volatile bool spi_done = false;
static bool dio_states[3] = {0};



void spi_callback(spi_callback_args_t *p_args)
{
    SSP_PARAMETER_NOT_USED(p_args);
    spi_done= true;
}

void timer0_callback(timer_callback_args_t *p_args)
{
    SSP_PARAMETER_NOT_USED(p_args);
    ticks++;


}

void irq_callback(external_irq_callback_args_t *p_args)
{
    if(p_args->channel == 1)
    {

        dio_states[0]=1;
        radio_irq_handler(0);
        dio_states[0]=0;

    }
    else if(p_args->channel == 2)
    {

        dio_states[1]=1;
        radio_irq_handler(1);
        dio_states[0]=0;
    }
    else if(p_args->channel == 14)
    {

        dio_states[2]=1;
        radio_irq_handler(2);
    }
    else
    {
        ;
    }
//    if(p_args->channel == 14)
//    {
//        radio_irq_handler(2);
//    }

}



// -----------------------------------------------------------------------------
// I/O

//#define nss (IOPORT_PORT_04_PIN_13)
//
//#define rst (IOPORT_PORT_05_PIN_11)


u1_t transmit[1]={0},ccc=0;
u1_t recv[1]={0};



static void hal_io_init () {

//    g_ioport.p_api->pinDirectionSet(lmic_pins.nss, IOPORT_DIRECTION_OUTPUT);
//    g_ioport.p_api->pinCfg(lmic_pins.dio[0], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
//    g_ioport.p_api->pinDirectionSet(lmic_pins.dio[0], IOPORT_DIRECTION_INPUT);
//    g_ioport.p_api->pinCfg(lmic_pins.dio[1], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
//    g_ioport.p_api->pinDirectionSet(lmic_pins.dio[1], IOPORT_DIRECTION_INPUT);
//    g_ioport.p_api->pinCfg(lmic_pins.dio[2], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
//    g_ioport.p_api->pinDirectionSet(lmic_pins.dio[2], IOPORT_DIRECTION_INPUT);


}

// val == 1  => tx 1
void hal_pin_rxtx (u1_t val) {

}

// set radio RST pin to given value (or keep floating!)
void hal_pin_rst (u1_t val) {
g_ioport.p_api->init(g_ioport.p_cfg);
    if(val == 0 || val == 1)
    {
        g_ioport.p_api->pinCfg(lmic_pins.rst, IOPORT_DIRECTION_OUTPUT);
        g_ioport.p_api->pinDirectionSet(lmic_pins.rst, IOPORT_DIRECTION_OUTPUT);
            if(val == 0)
                g_ioport.p_api->pinWrite(lmic_pins.rst,IOPORT_LEVEL_LOW);
            else if (val == 1)
                g_ioport.p_api->pinWrite(lmic_pins.rst,IOPORT_LEVEL_HIGH);
    }
    else
    {
        g_ioport.p_api->pinCfg(lmic_pins.rst, IOPORT_DIRECTION_INPUT);
        g_ioport.p_api->pinDirectionSet(lmic_pins.rst, IOPORT_DIRECTION_INPUT);
    }


}


ioport_level_t readpin;
u1_t rd=0;

//static void hal_io_check() {
//
//    uint8_t i;
//        for (i = 0; i < NUM_DIO; ++i) {
//            if (lmic_pins.dio[i] == 0xff)
//                continue;
//            g_ioport.p_api->pinRead(lmic_pins.dio[i], &readpin);
//            if(readpin == IOPORT_LEVEL_HIGH)
//                rd = 1;
//            else
//                rd = 0;
//
//            if (dio_states[i] != readpin) {
//                dio_states[i] = !dio_states[i];
//            if (dio_states[i])
//                    radio_irq_handler(i);
//            }
//        }
//
//
//}
 void hal_io_check() {
    uint8_t i;
//    for (i = 0; i < 3; ++i) {
//        if (lmic_pins.dio[i] == 0xff)
//            continue;
//
//        if (dio_states[i] != 0) {
//            dio_states[i] = !dio_states[i];
//            if (dio_states[i])
//                radio_irq_handler(i);
//        }
//    }
//    radio_irq_handler(0);
}

// -----------------------------------------------------------------------------
// SPI

//static const SPISettings settings(10E6, MSBFIRST, SPI_MODE0);

static void hal_spi_init () {
   err =  g_spi0.p_api->open(g_spi0.p_ctrl,g_spi0.p_cfg);



   err = g_timer0.p_api->open(g_timer0.p_ctrl,g_timer0.p_cfg);
   err = g_timer0.p_api->start(g_timer0.p_ctrl);

   g_external_irq0.p_api->open(g_external_irq0.p_ctrl,g_external_irq0.p_cfg);
  g_external_irq0.p_api->enable(g_external_irq0.p_ctrl);
  g_external_irq0.p_api->triggerSet(g_external_irq0.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);

   g_external_irq1.p_api->open(g_external_irq1.p_ctrl,g_external_irq1.p_cfg);
   g_external_irq1.p_api->enable(g_external_irq1.p_ctrl);
   g_external_irq1.p_api->triggerSet(g_external_irq1.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);

   g_external_irq2.p_api->open(g_external_irq2.p_ctrl,g_external_irq2.p_cfg);
   g_external_irq2.p_api->enable(g_external_irq2.p_ctrl);
   g_external_irq2.p_api->triggerSet(g_external_irq2.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);


}

void hal_pin_nss (u1_t val) {
    g_ioport.p_api->pinDirectionSet(lmic_pins.nss, IOPORT_DIRECTION_OUTPUT);
    if(val == 0)
        g_ioport.p_api->pinWrite(lmic_pins.nss,IOPORT_LEVEL_LOW);
    else if(val == 1)
        g_ioport.p_api->pinWrite(lmic_pins.nss,IOPORT_LEVEL_HIGH);

}

// perform SPI transaction with radio
u1_t hal_spi (u1_t out) {
    if((out & 0x80) == 0x80)
    {
        uint8_t temp[1] = {out};
        g_spi0.p_api->write(g_spi0.p_ctrl, (const void*)temp,1,SPI_BIT_WIDTH_8_BITS);
        while(false == spi_done)
        {
          ;
        }
        spi_done = false;
        return 0;
    }
    else if((out > 0x00) && (out & 0x80) != 0x80)
    {
        ccc = out;
        uint8_t temp[1] = {out};
        g_spi0.p_api->write(g_spi0.p_ctrl, (const void*)temp,1,SPI_BIT_WIDTH_8_BITS);
        while(false == spi_done)
        {
;
        }
        spi_done = false;
    }
    else if(out == 0x00)
    {
        g_spi0.p_api->read(g_spi0.p_ctrl,  recv, sizeof(recv), SPI_BIT_WIDTH_8_BITS);
        while(false == spi_done)
        {
            ;
        }
        spi_done = false;
        return recv[0];
    }

    return recv[0];
}
// -----------------------------------------------------------------------------
// TIME

static void hal_time_init () {
    // Nothing to do
}

u4_t hal_ticks () {
    // Because micros() is scaled down in this function, micros() will
    // overflow before the tick timer should, causing the tick timer to
    // miss a significant part of its values if not corrected. To fix
    // this, the "overflow" serves as an overflow area for the micros()
    // counter. It consists of three parts:
    //  - The US_PER_OSTICK upper bits are effectively an extension for
    //    the micros() counter and are added to the result of this
    //    function.
    //  - The next bit overlaps with the most significant bit of
    //    micros(). This is used to detect micros() overflows.
    //  - The remaining bits are always zero.
    //
    // By comparing the overlapping bit with the corresponding bit in
    // the micros() return value, overflows can be detected and the
    // upper bits are incremented. This is done using some clever
    // bitwise operations, to remove the need for comparisons and a
    // jumps, which should result in efficient code. By avoiding shifts
    // other than by multiples of 8 as much as possible, this is also
    // efficient on AVR (which only has 1-bit shifts).
//    g_timer0.p_api->stop(g_timer0.p_ctrl);
//    static uint8_t overflow = 0;

    // Scaled down timestamp. The top US_PER_OSTICK_EXPONENT bits are 0,
    // the others will be the lower bits of our return value.
//    u4_t t = ticks;
//    g_timer0.p_api->counterGet(g_timer0.p_ctrl, &cnt);
//    cnt = 65535-cnt;
//    if( (cnt > 65000) && (cnt < 65535 ) )
//    {
//        g_timer0.p_api->reset(g_timer0.p_ctrl);
//        cnt=0;
//        t++;
//    }
//    scaled = ticks >> US_PER_OSTICK_EXPONENT; // 625
    // Most significant byte of scaled
//    uint8_t msb = scaled >> 24;
    // Mask pointing to the overlapping bit in msb and overflow.
//    const uint8_t mask = (1 << (7 - US_PER_OSTICK_EXPONENT));
    // Update overflow. If the overlapping bit is different
    // between overflow and msb, it is added to the stored value,
    // so the overlapping bit becomes equal again and, if it changed
    // from 1 to 0, the upper bits are incremented.
//    overflow += (msb ^ overflow) & mask;

    // Return the scaled value with the upper bits of stored added. The
    // overlapping bit will be equal and the lower bits will be 0, so
    // bitwise or is a no-op for them.
//    g_timer0.p_api->start(g_timer0.p_ctrl);

//    return scaled | ((uint32_t)overflow << 24);

    // 0 leads to correct, but overly complex code (it could just return
    // micros() unmodified), 8 leaves no room for the overlapping bit.
//    static_assert(US_PER_OSTICK_EXPONENT > 0 && US_PER_OSTICK_EXPONENT < 8, "Invalid US_PER_OSTICK_EXPONENT value");


    t = ticks;
//
////    hal_disableIRQs();
///
    g_timer0.p_api->counterGet(g_timer0.p_ctrl, &cnt);
    if(cnt != 0 )
        cnt = 65535 - cnt;
//    if( (cnt < 500) )
//    {
//        g_timer0.p_api->reset(g_timer0.p_ctrl);
//        cnt=0;
//        t++;
//    }
//    hal_enableIRQs();

    return ((t<<16)|cnt);

}

// Returns the number of ticks until time. Negative values indicate that
// time has already passed.
static s4_t delta_time(u4_t time) {
    u4_t t = hal_ticks();
    s4_t d = time - t;
    if( d<=0 ) return 0;    // in the past
    if( (d>>16)!=0 ) return 0xFFFF; // far ahead
    return (u2_t)d;
}

void hal_waitUntil (u4_t time) {
    while( delta_time(time) != 0 );
}
//    s4_t delta = delta_time(time);
//    // From delayMicroseconds docs: Currently, the largest value that
//    // will produce an accurate delay is 16383.
//    while (delta > (16000 / US_PER_OSTICK)) {
//        R_BSP_SoftwareDelay(16, BSP_DELAY_UNITS_MILLISECONDS);
//        delta -= (16000 / US_PER_OSTICK);
//    }
//    if (delta > 0)
//        R_BSP_SoftwareDelay((delta * US_PER_OSTICK), BSP_DELAY_UNITS_MICROSECONDS);
////        delayMicroseconds(delta * US_PER_OSTICK);
//}

// check and rewind for target time
u1_t hal_checkTimer (u4_t time) {
    // No need to schedule wakeup, since we're not sleeping
    return delta_time(time) <= 0;
}

static uint8_t irqlevel = 0;

void hal_disableIRQs () {

//    __disable_irq();
//    g_timer0.p_api->close(g_timer0.p_ctrl);
//    g_external_irq1.p_api->disable(g_external_irq1.p_ctrl);
//    g_external_irq2.p_api->disable(g_external_irq2.p_ctrl);
    irqlevel++;
}

void hal_enableIRQs () {

    if(--irqlevel == 0) {
//        __enable_irq();
//        g_timer0.p_api->open(g_timer0.p_ctrl,g_timer0.p_cfg);
//        g_external_irq1.p_api->enable(g_external_irq1.p_ctrl);
//        g_external_irq2.p_api->enable(g_external_irq2.p_ctrl);

            // Instead of using proper interrupts (which are a bit tricky
            // and/or not available on all pins on AVR), just poll the pin
            // values. Since os_runloop disables and re-enables interrupts,
            // putting this here makes sure we check at least once every
            // loop.
            //
            // As an additional bonus, this prevents the can of worms that
            // we would otherwise get for running SPI transfers inside ISRs
            hal_io_check();
        }
    hal_io_check();

 }

void hal_sleep () {
    // Not implemented
}

// -----------------------------------------------------------------------------

#if defined(LMIC_PRINTF_TO)
static int uart_putchar (char c, FILE *)
{
    LMIC_PRINTF_TO.write(c) ;
    return 0 ;
}

void hal_printf_init() {
    // create a FILE structure to reference our UART output function
    static FILE uartout;
    memset(&uartout, 0, sizeof(uartout));

    // fill in the UART file descriptor with pointer to writer.
    fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);

    // The uart is the standard output device STDOUT.
    stdout = &uartout ;
}
#endif // defined(LMIC_PRINTF_TO)

void hal_init () {
    // configure radio I/O and interrupt handler
    hal_io_init();
    // configure radio SPI
    hal_spi_init();
    // configure timer and interrupt handler
    hal_time_init();

#if defined(LMIC_PRINTF_TO)
    // printf support
    hal_printf_init();
#endif
}

void hal_failed (const char *file, u2_t line) {

}
4

0 に答える 0