GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
がじぇるね岡宮です。
RL78/G13系のGRボードで、ライブラリバージョンV2.xxではanalogWriteのソフトPWMが動かないようです。主には3,5,6,9,10以外のピンを指定したときに発生します。(GR-ADZUKIでは10ピンもsoftwarePWM)
V2.xxにバージョンアップした際に、コンパイラバージョンを14.03→4.9.2にしたことで、下記getPinTableのアセンブルが正しく動作しなくなってしまったようです。#if 1にしてC言語の方を有効にすると、analogWriteが機能します。
Fujitaさん、ここのアセンブルの修正案をいただくことできないでしょうか?
(pintable.h)
#if 0 // GCC の吐くコードの効率が悪いのでインラインアセンブラを使用#define getPinTable(u8Pin) (&PinTable[u8Pin])#else#define getPinTable(u8Pin) \({ \ PinTableType* p; \ __asm __volatile( \ " mov a, %1 \n" \ " mov x, %2 \n" \ " mulu x \n" \ " addw ax, %3 \n" \ " movw %0, ax \n" \ : "=r"(p) \ : "r"((uint8_t)(u8Pin)), "i"((unsigned)&PinTable[1] - (unsigned)&PinTable[0]), "i"(PinTable) \ : "a", "x" \ ); \ p; \})#endif
とりあえず以下の修正で analogWrite() は動作するようなるようです。
--- gr_common/cores/wiring_analog.c +++ gr_common/cores/wiring_analog.c @@ -395,2 +395,3 @@ void analogWrite(uint8_t pin, int val) { } else { + const PinTableType* p = getPinTable(pin); g_SwPwm[i].valid = false; @@ -398,4 +399,4 @@ void analogWrite(uint8_t pin, int val) { g_SwPwm[i].value = g_SwPwm[i].newValue = val; - g_SwPwm[i].port = getPinTable(pin)->portRegisterAddr; - g_SwPwm[i].mask = getPinTable(pin)->mask; + g_SwPwm[i].port = p->portRegisterAddr; + g_SwPwm[i].mask = p->mask; g_SwPwm[i].valid = true;
確認用スケッチ
/*GR-KURUMI Sketch Template Version: V2.01*/ #include <Arduino.h> // Pin 22,23,24 are assigned to RGB LEDs. #define LED_RED 22 // LOW active #define LED_GREEN 23 // LOW active #define LED_BLUE 24 // LOW active void setup() { } void loop() { analogWrite(LED_RED, 127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 2e3f) + 0.5f))); analogWrite(LED_GREEN, 127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 3e3f) + 0.5f))); analogWrite(LED_BLUE, 127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 5e3f) + 0.5f))); }
問題の原因としてコンパイラの不具合臭いのですが、まだ確認に到っておりません。現在普段使いの PC を修理に出している関係で携帯用のゴミスペック PC しか使える状況になく、作業効率が著しく低下しています。問題原因の確認にまで到りましたら再度報告します。
> 問題原因の確認にまで到りましたら再度報告します。
analogWrite() の getPinTable() を呼び出している箇所で
g_SwPwm[i].port = getPinTable(pin)->portRegisterAddr;
getPinTable() の戻り値 r12 の値を hl に代入せずにメモリアクセスを行っていることが原因のようです。
.loc 1 399 0 ; 399 "gr_common/cores/wiring_analog.c" 1 mov a, r20 mov x, #14 mulu x addw ax, #_PinTable movw r12, ax ; 0 "" 2 .LBE8: movw ax, [hl+12] movw r14, ax movw ax, r8 addw ax, #2 movw de, ax movw ax, r14 movw [de], ax
最適化オプション `-Os' の一部の機能を禁止する `-fno-tree-vrp -fno-expensive-optimizations -fno-gcse' を加えてコンパイルすると前述の r12 → hl の代入は行われることゝなり、恐らくはコンパイラの最適化の不具合と思われます。
.loc 1 399 0 ; 399 "gr_common/cores/wiring_analog.c" 1 mov a, r16 mov x, #14 mulu x addw ax, #_PinTable movw r12, ax ; 0 "" 2 .LVL33: .LBE8: movw hl, r12 movw ax, [hl+12] movw r14, ax movw ax, r8 addw ax, #2 movw de, ax movw ax, r14 movw [de], ax
以上は時間が取れ次第 https://gcc-renesas.com/ja/ に報告しておきます。
2017/09/25 makefile が間違ってたので添付ファイル差し替え
ちなみに、Toolchain の最新より前2つ、
GCC for Renesas 4.9.2.201603-GNURL78 Windows Toolchain (ELF)
GCC for Renesas 4.9.2.201604-GNURL78 Windows Toolchain (ELF)
で確認したところでは最適化オプション `-Os' で問題ありませんでした。最新の
GCC for Renesas 4.9.2.201701-GNURL78 Windows Toolchain (ELF)
固有の問題のようです。
Fujitaさん、ご返信が遅くなり申し訳ありません。多大なるご協力ありがとうございます。
4.9.2.201701で以下のTPで主要ライブラリやサンプルはテストしていたのですが、analogWriteのSoftPWMは、振り返ってみるとテスト漏れしている感じがありますね。
今のところ影響が確認できているのがSoftPWMだけのため、次のWebコンパイラでもこのバージョンを使おうと思いますが、もしGNUサポートから何か連絡がありましたら、ご一報いただけると大変ありがたく存じます。
/* * test.cpp * * Created on: 2017/07/19 * Author: a5034000 *///#define STANDARD_TEST#include <Arduino.h>//#include <LiquidCrystal.h>//#include <Ethernet.h>//#include <Stepper.h>//#define EEPROM_TEST#define FIRMATA_TEST//#define WIRE_TEST//#define SD_TEST//#define RTC_TEST//#define MSTIMER2_TEST//#define MORTOR_TEST//#define SERIAL_TEST//#define IR_TEST//#define TONE_TEST//#define STANBY_TEST//#define WAVP_TEST//#define PULSE_TEST//#define GFX_TEST#ifdef EEPROM_TEST#include <EEPROM.h>#endif#if not defined (FIRMATA_TEST) \ && not defined (WIRE_TEST) \ && not defined (SD_TEST) \ && not defined (RTC_TEST) \ && not defined (MSTIMER2_TEST)\ && not defined (MORTOR_TEST)\ && not defined (SERIAL_TEST)\ && not defined (IR_TEST)\ && not defined (TONE_TEST)\ && not defined (STANBY_TEST)\ && not defined (WAVP_TEST)\ && not defined (PULSE_TEST)\ && not defined (GFX_TEST)#define LED_R_COM 22#define LED_G_COM 23#define LED_B_COM 24#define LED_1 12#define LED_2 13/*GR-ADZUKI Sketch Template Version: V1.00*/void sw1_push() { digitalWrite(LED_R_COM, LOW);}void sw2_push() { digitalWrite(LED_G_COM, LOW);}void P137_pin25() { digitalWrite(LED_B_COM, LOW);}void setup() { Serial.begin(9600);#ifdef EEPROM_TEST for(int i = 0; i < 8*1024; i++) { if(0 == i % 1024) { Serial.println(); Serial.print("reading.."); Serial.println(i, HEX); } Serial.print(EEPROM.read(i),HEX); } for(int i = 0; i < 8*1024; i++) { if(0 == i % 1024) { Serial.println(); Serial.print("writing.."); Serial.println(i, HEX); } EEPROM.write(i, (uint8_t)i); }#endif pinMode(LED_R_COM, OUTPUT); pinMode(LED_G_COM, OUTPUT); pinMode(LED_B_COM, OUTPUT); pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); digitalWrite(LED_R_COM, HIGH); // red LED on digitalWrite(LED_G_COM, HIGH);// green LED on digitalWrite(LED_B_COM, HIGH);// blue LED on digitalWrite(LED_1, HIGH); digitalWrite(LED_2, LOW); pinMode(3, INPUT_PULLUP);// for sw1 pinMode(2, INPUT_PULLUP);// for sw2 pinMode(25, INPUT_PULLUP);// needed external PULLUP attachInterrupt(0, sw2_push, FALLING); attachInterrupt(1, sw1_push, FALLING); attachInterrupt(2, P137_pin25, FALLING); for (int i = 0; i < 31; i++) { Serial.print("pin"); Serial.print(i); Serial.print(":\t"); Serial.print(digitalPinToPort(i), DEC); Serial.print(":\t"); Serial.println((uint8_t) digitalPinToBitMask(i), HEX); } uint16_t original_data = 0b1111000010100101; Serial.println("BIN"); Serial.print("original:\t"); Serial.println(original_data, BIN); Serial.print("lowByte:\t"); Serial.println(lowByte(original_data), BIN); Serial.print("highByte:\t"); Serial.println(highByte(original_data), BIN); Serial.println("HEX"); Serial.print("original:\t"); Serial.println(original_data, HEX); Serial.print("lowByte:\t"); Serial.println(lowByte(original_data), HEX); Serial.print("highByte:\t"); Serial.println(highByte(original_data), HEX);// analogWrite(3, 50);// tone(5, 500); randomSeed(millis());}void loop() { static uint8_t count = 0; static uint32_t old = millis(); static double x = 0; if (millis() - old > 100) { digitalWrite(LED_1, !digitalRead(LED_1)); digitalWrite(LED_2, !digitalRead(LED_2)); Serial.print("millis:"); Serial.print(millis()); Serial.print(" micros:"); Serial.print(micros()); Serial.print(" A2:"); Serial.print(analogRead(A2)); Serial.print(" random:"); Serial.print(random(0, 100)); Serial.print(" x:"); Serial.print(x); Serial.print(" sin"); Serial.print(sin(x)); Serial.print(" cos"); Serial.print(cos(x)); Serial.println(); x += 0.01; if (x > PI) x = 0; old = millis(); } analogWrite(6, count); analogWrite(9, 255 - count); analogWrite(10, count); analogWrite(11, 255 - count); delay(5); count++;}#endif#ifdef FIRMATA_TEST/* Firmata is a generic protocol for communicating with microcontrollers from software on a host computer. It is intended to work with any host computer software package. To download a host software package, please click on the following link to open the list of Firmata client libraries in your default browser. github.com/.../arduino Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See file LICENSE.txt for further informations on licensing terms. Last updated October 16th, 2016 */#include <Servo.h>#include <Wire.h>#include <Firmata.h>#define I2C_WRITE B00000000#define I2C_READ B00001000#define I2C_READ_CONTINUOUSLY B00010000#define I2C_STOP_READING B00011000#define I2C_READ_WRITE_MODE_MASK B00011000#define I2C_10BIT_ADDRESS_MODE_MASK B00100000#define I2C_END_TX_MASK B01000000#define I2C_STOP_TX 1#define I2C_RESTART_TX 0#define I2C_MAX_QUERIES 8#define I2C_REGISTER_NOT_SPECIFIED -1// the minimum interval for sampling analog input#define MINIMUM_SAMPLING_INTERVAL 1/*============================================================================== * GLOBAL VARIABLES *============================================================================*/#ifdef FIRMATA_SERIAL_FEATURESerialFirmata serialFeature;#endif/* analog inputs */int analogInputsToReport = 0; // bitwise array to store pin reporting/* digital input ports */byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silencebyte previousPINs[TOTAL_PORTS];// previous 8 bits sent/* pins configuration */byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else/* timer variables */unsigned long currentMillis; // store the current value from millis()unsigned long previousMillis;// for comparison with currentMillisunsigned int samplingInterval = 19;// how often to run the main loop (in ms)/* i2c data */struct i2c_device_info { byte addr; int reg; byte bytes; byte stopTX;};/* for i2c read continuous more */i2c_device_info query[I2C_MAX_QUERIES];byte i2cRxData[64];boolean isI2CEnabled = false;signed char queryIndex = -1;// default delay time between i2c read request and Wire.requestFrom()unsigned int i2cReadDelayTime = 0;Servo servos[MAX_SERVOS];byte servoPinMap[TOTAL_PINS];byte detachedServos[MAX_SERVOS];byte detachedServoCount = 0;byte servoCount = 0;boolean isResetting = false;// Forward declare a few functions to avoid compiler errors with older versions// of the Arduino IDE.void setPinModeCallback(byte, int);void reportAnalogCallback(byte analogPin, int value);void sysexCallback(byte, byte, byte*);/* utility functions */void wireWrite(byte data){#if ARDUINO >= 100 Wire.write((byte)data);#else Wire.send(data);#endif}byte wireRead(void){#if ARDUINO >= 100 return Wire.read();#else return Wire.receive();#endif}/*============================================================================== * FUNCTIONS *============================================================================*/void attachServo(byte pin, int minPulse, int maxPulse){ if (servoCount < MAX_SERVOS) { // reuse indexes of detached servos until all have been reallocated if (detachedServoCount > 0) { servoPinMap[pin] = detachedServos[detachedServoCount - 1]; if (detachedServoCount > 0) detachedServoCount--; } else { servoPinMap[pin] = servoCount; servoCount++; } if (minPulse > 0 && maxPulse > 0) { servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse); } else { servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin)); } } else { Firmata.sendString("Max servos attached"); }}void detachServo(byte pin){ servos[servoPinMap[pin]].detach(); // if we're detaching the last servo, decrement the count // otherwise store the index of the detached servo if (servoPinMap[pin] == servoCount && servoCount > 0) { servoCount--; } else if (servoCount > 0) { // keep track of detached servos because we want to reuse their indexes // before incrementing the count of attached servos detachedServoCount++; detachedServos[detachedServoCount - 1] = servoPinMap[pin]; } servoPinMap[pin] = 255;}void enableI2CPins(){ byte i; // is there a faster way to do this? would probaby require importing // Arduino.h to get SCL and SDA pins for (i = 0; i < TOTAL_PINS; i++) { if (IS_PIN_I2C(i)) { // mark pins as i2c so they are ignore in non i2c data requests setPinModeCallback(i, PIN_MODE_I2C); } } isI2CEnabled = true; Wire.begin();}/* disable the i2c pins so they can be used for other functions */void disableI2CPins() { isI2CEnabled = false; // disable read continuous mode for all devices queryIndex = -1;}void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) { // allow I2C requests that don't require a register read // for example, some devices using an interrupt pin to signify new data available // do not always require the register read so upon interrupt you call Wire.requestFrom() if (theRegister != I2C_REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); wireWrite((byte)theRegister); Wire.endTransmission(stopTX); // default = true // do not set a value of 0 if (i2cReadDelayTime > 0) { // delay is necessary for some devices such as WiiNunchuck delayMicroseconds(i2cReadDelayTime); } } else { theRegister = 0; // fill the register with a dummy value } Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom // check to be sure correct number of bytes were returned by slave if (numBytes < Wire.available()) { Firmata.sendString("I2C: Too many bytes received"); } else if (numBytes > Wire.available()) { Firmata.sendString("I2C: Too few bytes received"); } i2cRxData[0] = address; i2cRxData[1] = theRegister; for (int i = 0; i < numBytes && Wire.available(); i++) { i2cRxData[2 + i] = wireRead(); } // send slave address, register and received bytes Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);}void outputPort(byte portNumber, byte portValue, byte forceSend){ // pins not configured as INPUT are cleared to zeros portValue = portValue & portConfigInputs[portNumber]; // only send if the value is different than previously sent if (forceSend || previousPINs[portNumber] != portValue) { Firmata.sendDigitalPort(portNumber, portValue); previousPINs[portNumber] = portValue; }}/* ----------------------------------------------------------------------------- * check all the active digital inputs for change of state, then add any events * to the Serial output queue using Serial.print() */void checkDigitalInputs(void){ /* Using non-looping code allows constants to be given to readPort(). * The compiler will apply substantial optimizations if the inputs * to readPort() are compile-time constants. */ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false); if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false); if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false); if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false); if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false); if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false); if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false); if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false); if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false); if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false); if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false); if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false); if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false); if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false); if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false); if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);}// -----------------------------------------------------------------------------/* sets the pin mode to the correct state and sets the relevant bits in the * two bit-arrays that track Digital I/O and PWM status */void setPinModeCallback(byte pin, int mode){ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE) return; if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) { // disable i2c so pins can be used for other functions // the following if statements should reconfigure the pins properly disableI2CPins(); } if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) { if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) { detachServo(pin); } } if (IS_PIN_ANALOG(pin)) { reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting } if (IS_PIN_DIGITAL(pin)) { if (mode == INPUT || mode == PIN_MODE_PULLUP) { portConfigInputs[pin / 8] |= (1 << (pin & 7)); } else { portConfigInputs[pin / 8] &= ~(1 << (pin & 7)); } } Firmata.setPinState(pin, 0); switch (mode) { case PIN_MODE_ANALOG: if (IS_PIN_ANALOG(pin)) { if (IS_PIN_DIGITAL(pin)) { pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver#if ARDUINO <= 100 // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6 digitalWrite(PIN_TO_DIGITAL(pin), LOW);// disable internal pull-ups#endif } Firmata.setPinMode(pin, PIN_MODE_ANALOG); } break; case INPUT: if (IS_PIN_DIGITAL(pin)) { pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver#if ARDUINO <= 100 // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6 digitalWrite(PIN_TO_DIGITAL(pin), LOW);// disable internal pull-ups#endif Firmata.setPinMode(pin, INPUT); } break; case PIN_MODE_PULLUP: if (IS_PIN_DIGITAL(pin)) { pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP); Firmata.setPinMode(pin, PIN_MODE_PULLUP); Firmata.setPinState(pin, 1); } break; case OUTPUT: if (IS_PIN_DIGITAL(pin)) { if (Firmata.getPinMode(pin) == PIN_MODE_PWM) { // Disable PWM if pin mode was previously set to PWM. digitalWrite(PIN_TO_DIGITAL(pin), LOW); } pinMode(PIN_TO_DIGITAL(pin), OUTPUT); Firmata.setPinMode(pin, OUTPUT); } break; case PIN_MODE_PWM: if (IS_PIN_PWM(pin)) { pinMode(PIN_TO_PWM(pin), OUTPUT); analogWrite(PIN_TO_PWM(pin), 0); Firmata.setPinMode(pin, PIN_MODE_PWM); } break; case PIN_MODE_SERVO: if (IS_PIN_DIGITAL(pin)) { Firmata.setPinMode(pin, PIN_MODE_SERVO); if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) { // pass -1 for min and max pulse values to use default values set // by Servo library attachServo(pin, -1, -1); } } break; case PIN_MODE_I2C: if (IS_PIN_I2C(pin)) { // mark the pin as i2c // the user must call I2C_CONFIG to enable I2C for a device Firmata.setPinMode(pin, PIN_MODE_I2C); } break; case PIN_MODE_SERIAL:#ifdef FIRMATA_SERIAL_FEATURE serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);#endif break; default: Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM } // TODO: save status to EEPROM here, if changed}/* * Sets the value of an individual pin. Useful if you want to set a pin value but * are not tracking the digital port state. * Can only be used on pins configured as OUTPUT. * Cannot be used to enable pull-ups on Digital INPUT pins. */void setPinValueCallback(byte pin, int value){ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) { if (Firmata.getPinMode(pin) == OUTPUT) { Firmata.setPinState(pin, value); digitalWrite(PIN_TO_DIGITAL(pin), value); } }}void analogWriteCallback(byte pin, int value){ if (pin < TOTAL_PINS) { switch (Firmata.getPinMode(pin)) { case PIN_MODE_SERVO: if (IS_PIN_DIGITAL(pin)) servos[servoPinMap[pin]].write(value); Firmata.setPinState(pin, value); break; case PIN_MODE_PWM: if (IS_PIN_PWM(pin)) analogWrite(PIN_TO_PWM(pin), value); Firmata.setPinState(pin, value); break; } }}void digitalWriteCallback(byte port, int value){ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0; if (port < TOTAL_PORTS) { // create a mask of the pins on this port that are writable. lastPin = port * 8 + 8; if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS; for (pin = port * 8; pin < lastPin; pin++) { // do not disturb non-digital pins (eg, Rx & Tx) if (IS_PIN_DIGITAL(pin)) { // do not touch pins in PWM, ANALOG, SERVO or other modes if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) { pinValue = ((byte)value & mask) ? 1 : 0; if (Firmata.getPinMode(pin) == OUTPUT) { pinWriteMask |= mask; } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) { // only handle INPUT here for backwards compatibility#if ARDUINO > 100 pinMode(pin, INPUT_PULLUP);#else // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier pinWriteMask |= mask;#endif } Firmata.setPinState(pin, pinValue); } } mask = mask << 1; } writePort(port, (byte)value, pinWriteMask); }}// -----------------------------------------------------------------------------/* sets bits in a bit array (int) to toggle the reporting of the analogIns *///void FirmataClass::setAnalogPinReporting(byte pin, byte state) {//}void reportAnalogCallback(byte analogPin, int value){ if (analogPin < TOTAL_ANALOG_PINS) { if (value == 0) { analogInputsToReport = analogInputsToReport & ~ (1 << analogPin); } else { analogInputsToReport = analogInputsToReport | (1 << analogPin); // prevent during system reset or all analog pin values will be reported // which may report noise for unconnected analog pins if (!isResetting) { // Send pin value immediately. This is helpful when connected via // ethernet, wi-fi or bluetooth so pin states can be known upon // reconnecting. Firmata.sendAnalog(analogPin, analogRead(analogPin)); } } } // TODO: save status to EEPROM here, if changed}void reportDigitalCallback(byte port, int value){ if (port < TOTAL_PORTS) { reportPINs[port] = (byte)value; // Send port value immediately. This is helpful when connected via // ethernet, wi-fi or bluetooth so pin states can be known upon // reconnecting. if (value) outputPort(port, readPort(port, portConfigInputs[port]), true); } // do not disable analog reporting on these 8 pins, to allow some // pins used for digital, others analog. Instead, allow both types // of reporting to be enabled, but check if the pin is configured // as analog when sampling the analog inputs. Likewise, while // scanning digital pins, portConfigInputs will mask off values from any // pins configured as analog}/*============================================================================== * SYSEX-BASED commands *============================================================================*/void sysexCallback(byte command, byte argc, byte *argv){ byte mode; byte stopTX; byte slaveAddress; byte data; int slaveRegister; unsigned int delayTime; switch (command) { case I2C_REQUEST: mode = argv[1] & I2C_READ_WRITE_MODE_MASK; if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) { Firmata.sendString("10-bit addressing not supported"); return; } else { slaveAddress = argv[0]; } // need to invert the logic here since 0 will be default for client // libraries that have not updated to add support for restart tx if (argv[1] & I2C_END_TX_MASK) { stopTX = I2C_RESTART_TX; } else { stopTX = I2C_STOP_TX; // default } switch (mode) { case I2C_WRITE: Wire.beginTransmission(slaveAddress); for (byte i = 2; i < argc; i += 2) { data = argv[i] + (argv[i + 1] << 7); wireWrite(data); } Wire.endTransmission(); delayMicroseconds(70); break; case I2C_READ: if (argc == 6) { // a slave register is specified slaveRegister = argv[2] + (argv[3] << 7); data = argv[4] + (argv[5] << 7);// bytes to read } else { // a slave register is NOT specified slaveRegister = I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7);// bytes to read } readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX); break; case I2C_READ_CONTINUOUSLY: if ((queryIndex + 1) >= I2C_MAX_QUERIES) { // too many queries, just ignore Firmata.sendString("too many queries"); break; } if (argc == 6) { // a slave register is specified slaveRegister = argv[2] + (argv[3] << 7); data = argv[4] + (argv[5] << 7);// bytes to read } else { // a slave register is NOT specified slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7);// bytes to read } queryIndex++; query[queryIndex].addr = slaveAddress; query[queryIndex].reg = slaveRegister; query[queryIndex].bytes = data; query[queryIndex].stopTX = stopTX; break; case I2C_STOP_READING: byte queryIndexToSkip; // if read continuous mode is enabled for only 1 i2c device, disable // read continuous reporting for that device if (queryIndex <= 0) { queryIndex = -1; } else { queryIndexToSkip = 0; // if read continuous mode is enabled for multiple devices, // determine which device to stop reading and remove it's data from // the array, shifiting other array data to fill the space for (byte i = 0; i < queryIndex + 1; i++) { if (query[i].addr == slaveAddress) { queryIndexToSkip = i; break; } } for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) { if (i < I2C_MAX_QUERIES) { query[i].addr = query[i + 1].addr; query[i].reg = query[i + 1].reg; query[i].bytes = query[i + 1].bytes; query[i].stopTX = query[i + 1].stopTX; } } queryIndex--; } break; default: break; } break; case I2C_CONFIG: delayTime = (argv[0] + (argv[1] << 7)); if (delayTime > 0) { i2cReadDelayTime = delayTime; } if (!isI2CEnabled) { enableI2CPins(); } break; case SERVO_CONFIG: if (argc > 4) { // these vars are here for clarity, they'll optimized away by the compiler byte pin = argv[0]; int minPulse = argv[1] + (argv[2] << 7); int maxPulse = argv[3] + (argv[4] << 7); if (IS_PIN_DIGITAL(pin)) { if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) { detachServo(pin); } attachServo(pin, minPulse, maxPulse); setPinModeCallback(pin, PIN_MODE_SERVO); } } break; case SAMPLING_INTERVAL: if (argc > 1) { samplingInterval = argv[0] + (argv[1] << 7); if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) { samplingInterval = MINIMUM_SAMPLING_INTERVAL; } } else { //Firmata.sendString("Not enough data"); } break; case EXTENDED_ANALOG: if (argc > 1) { int val = argv[1]; if (argc > 2) val |= (argv[2] << 7); if (argc > 3) val |= (argv[3] << 14); analogWriteCallback(argv[0], val); } break; case CAPABILITY_QUERY: Firmata.write(START_SYSEX); Firmata.write(CAPABILITY_RESPONSE); for (byte pin = 0; pin < TOTAL_PINS; pin++) { if (IS_PIN_DIGITAL(pin)) { Firmata.write((byte)INPUT); Firmata.write(1); Firmata.write((byte)PIN_MODE_PULLUP); Firmata.write(1); Firmata.write((byte)OUTPUT); Firmata.write(1); } if (IS_PIN_ANALOG(pin)) { Firmata.write(PIN_MODE_ANALOG); Firmata.write(10); // 10 = 10-bit resolution } if (IS_PIN_PWM(pin)) { Firmata.write(PIN_MODE_PWM); Firmata.write(DEFAULT_PWM_RESOLUTION); } if (IS_PIN_DIGITAL(pin)) { Firmata.write(PIN_MODE_SERVO); Firmata.write(14); } if (IS_PIN_I2C(pin)) { Firmata.write(PIN_MODE_I2C); Firmata.write(1); // TODO: could assign a number to map to SCL or SDA }#ifdef FIRMATA_SERIAL_FEATURE serialFeature.handleCapability(pin);#endif Firmata.write(127); } Firmata.write(END_SYSEX); break; case PIN_STATE_QUERY: if (argc > 0) { byte pin = argv[0]; Firmata.write(START_SYSEX); Firmata.write(PIN_STATE_RESPONSE); Firmata.write(pin); if (pin < TOTAL_PINS) { Firmata.write(Firmata.getPinMode(pin)); Firmata.write((byte)Firmata.getPinState(pin) & 0x7F); if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F); if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F); } Firmata.write(END_SYSEX); } break; case ANALOG_MAPPING_QUERY: Firmata.write(START_SYSEX); Firmata.write(ANALOG_MAPPING_RESPONSE); for (byte pin = 0; pin < TOTAL_PINS; pin++) { Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127); } Firmata.write(END_SYSEX); break; case SERIAL_MESSAGE:#ifdef FIRMATA_SERIAL_FEATURE serialFeature.handleSysex(command, argc, argv);#endif break; }}/*============================================================================== * SETUP() *============================================================================*/void systemResetCallback(){ isResetting = true; // initialize a defalt state // TODO: option to load config from EEPROM instead of default#ifdef FIRMATA_SERIAL_FEATURE serialFeature.reset();#endif if (isI2CEnabled) { disableI2CPins(); } for (byte i = 0; i < TOTAL_PORTS; i++) { reportPINs[i] = false; // by default, reporting off portConfigInputs[i] = 0;// until activated previousPINs[i] = 0; } for (byte i = 0; i < TOTAL_PINS; i++) { // pins with analog capability default to analog input // otherwise, pins default to digital output if (IS_PIN_ANALOG(i)) { // turns off pullup, configures everything setPinModeCallback(i, PIN_MODE_ANALOG); } else if (IS_PIN_DIGITAL(i)) { // sets the output to 0, configures portConfigInputs setPinModeCallback(i, OUTPUT); } servoPinMap[i] = 255; } // by default, do not report any analog inputs analogInputsToReport = 0; detachedServoCount = 0; servoCount = 0; /* send digital inputs to set the initial state on the host computer, * since once in the loop(), this firmware will only send on change */ /* TODO: this can never execute, since no pins default to digital input but it will be needed when/if we support EEPROM stored config for (byte i=0; i < TOTAL_PORTS; i++) { outputPort(i, readPort(i, portConfigInputs[i]), true); } */ isResetting = false;}void setup(){ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION); Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback); Firmata.attach(REPORT_ANALOG, reportAnalogCallback); Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); Firmata.attach(SET_PIN_MODE, setPinModeCallback); Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback); Firmata.attach(START_SYSEX, sysexCallback); Firmata.attach(SYSTEM_RESET, systemResetCallback); // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega, // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this: // Serial1.begin(57600); // Firmata.begin(Serial1); // However do not do this if you are using SERIAL_MESSAGE Firmata.begin(57600); while (!Serial) { ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101 } systemResetCallback(); // reset to default config}/*============================================================================== * LOOP() *============================================================================*/void loop(){ byte pin, analogPin; /* DIGITALREAD - as fast as possible, check for changes and output them to the * FTDI buffer using Serial.print() */ checkDigitalInputs(); /* STREAMREAD - processing incoming messagse as soon as possible, while still * checking digital inputs. */ while (Firmata.available()) Firmata.processInput(); // TODO - ensure that Stream buffer doesn't go over 60 bytes currentMillis = millis(); if (currentMillis - previousMillis > samplingInterval) { previousMillis += samplingInterval; /* ANALOGREAD - do all analogReads() at the configured sampling interval */ for (pin = 0; pin < TOTAL_PINS; pin++) { if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) { analogPin = PIN_TO_ANALOG(pin); if (analogInputsToReport & (1 << analogPin)) { Firmata.sendAnalog(analogPin, analogRead(analogPin)); } } } // report i2c data for all device with read continuous mode enabled if (queryIndex > -1) { for (byte i = 0; i < queryIndex + 1; i++) { readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX); } } }#ifdef FIRMATA_SERIAL_FEATURE serialFeature.update();#endif}#endif // FIRMATATEST#ifdef WIRE_TEST#include <Wire.h>#define HMC5883L_ADDRESS 0x1E //7bit ADDRESS//*********************************************************void setup(){ //Initialize Serial and I2C communications Serial.begin(9600); Wire.begin(); //Put the HMC5883 IC into the correct operating mode Wire.beginTransmission(HMC5883L_ADDRESS); Wire.write(0x02);//select mode register Wire.write(0x00);//continuous measurement mode Wire.endTransmission();}//------------------------------------------------------void loop(){ int x,y,z; //triple axis data //set address where to begin reading data Wire.beginTransmission(HMC5883L_ADDRESS); Wire.write(0x03);//select register 3, X MSB register Wire.endTransmission(); //Read data from each axis, 2 registers per axis Wire.requestFrom(HMC5883L_ADDRESS, 6); if(6 <= Wire.available()) { x = Wire.read()<<8; x |= Wire.read(); z = Wire.read()<<8; z |= Wire.read(); y = Wire.read()<<8; y |= Wire.read(); } //Print out values of each axis Serial.print("x: "); Serial.print(x); Serial.print(" y: "); Serial.print(y); Serial.print(" z: "); Serial.println(z); delay(100);}#endif // WIRE_TEST#ifdef SD_TEST#include <SD.h>File myFile;//#define SD2_TESTvoid setup() { Serial.begin(9600); while (!Serial) { } Serial.print("Initializing SD card...");#ifndef SD2_TEST if (!SD.begin(SS)) {#else if (!SD2.begin(SS2)) {#endif Serial.println("initialization failed!"); return; } Serial.println("initialization done.");#ifndef SD2_TEST myFile = SD.open("test.txt", FILE_WRITE);#else myFile = SD2.open("test.txt", FILE_WRITE);#endif if (myFile) { Serial.print("Writing to test.txt..."); myFile.println("testing 1, 2, 3."); // close the file: myFile.close(); Serial.println("done."); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } // re-open the file for reading:#ifndef SD2_TEST myFile = SD.open("test.txt");#else myFile = SD2.open("test.txt");#endif if (myFile) { Serial.println("test.txt:"); // read from the file until there's nothing else in it: while (myFile.available()) { Serial.write(myFile.read()); } // close the file: myFile.close(); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } } void loop() { }#endif#ifdef RTC_TEST#include <RTC.h>#define LED_ERROR 12#define LED_ALARM 13#define LED_ON HIGH#define LED_OFF LOWRTC rtc;void alarm_handler();void setup(){ Serial.begin(9600); pinMode(LED_ALARM, OUTPUT); // LED for alarm pinMode(LED_ERROR, OUTPUT);// LED for error digitalWrite(LED_ALARM, LED_OFF);//turn off digitalWrite(LED_ERROR, LED_OFF);//turn off if(!rtc.begin()) { digitalWrite(LED_ERROR, LED_ON); // error } rtc.setDateTime(2016, 9, 22, 23, 20, 50, RTC_WEEK_SATURDAY); rtc.attachAlarmHandler(alarm_handler); rtc.setAlarmTime(23, 21, RTC_ALARM_EVERYDAY); rtc.alarmOn();}void loop(){ int year, mon, day, hour, min, sec, week; rtc.getDateTime(year, mon, day, hour, min, sec, week); Serial.print(year, DEC);Serial.print("/"); Serial.print(mon, DEC); Serial.print("/"); Serial.print(day, DEC); Serial.print(" "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(min, DEC); Serial.print(":"); Serial.println(sec, DEC); delay(500);}void alarm_handler(){ digitalWrite(LED_ALARM, LED_ON); // led for alarm}#endif#ifdef MSTIMER2_TEST#include <libraries/MsTimer2/MsTimer2.h>volatile unsigned long timerCount = 0;void timer(){ timerCount++;}void setup(){ Serial.begin(9600); Serial.println("start");#if 0 attachMicroIntervalTimerHandler(timer, 1000);#elif 0 MsTimer2::set(1, timer); MsTimer2::start();#elif 1 MsTimer2::setMicros(1000, timer); MsTimer2::start();#endif}void loop(){ static unsigned long lastMicros = micros(); unsigned long currentMicros; do { currentMicros = micros(); }while (currentMicros - lastMicros < 1000000UL); lastMicros = currentMicros; unsigned long securedTimerCount; do { securedTimerCount = timerCount; }while (securedTimerCount != timerCount); Serial.println(securedTimerCount);}#endif#ifdef MORTOR_TEST#include <Servo.h>Servo servo;void setup() { pinMode(13, OUTPUT);// analogWrite(9, 100); servo.attach(4);}void loop() { if(analogRead(A2) < 30) { analogWrite(10, 0); servo.write(0); } else { analogWrite(10, 150); servo.write(180); }}#endif#ifdef SERIAL_TESTvoid setup() { Serial.begin(9600); Serial1.begin(9600, SERIAL_8N1, 64, 64); Serial2.begin(9600, SERIAL_8N1, 256, 64);}void loop() {#if 0 delay(1000); Serial.print("RX_BufSize Ch0:"); Serial.print(Serial.availableForRead()); Serial.print(" Ch1:"); Serial.print(Serial1.availableForRead()); Serial.print(" Ch2:"); Serial.println(Serial2.availableForRead());#endif#if 1 if(Serial.available()) { Serial2.write(Serial.read()); } if(Serial2.available()) { Serial.write(Serial2.read()); }#endif}#endif#ifdef IR_TEST#include <Servo.h>#define IR_PIN 2#define IR_INTERRUPT 0uint8_t g_ir_data = 0;bool g_ir_available = false;void ir_receive_interrupt();void ir_receive_start();uint8_t ir_getData();bool ir_available();Servo servo;void setup() {// setPowerManagementMode(PM_STOP_MODE); Serial.begin(9600); pinMode(IR_PIN, INPUT_PULLUP); ir_receive_start(); servo.attach(4); servo.write(0); pinMode(22, OUTPUT); pinMode(23, OUTPUT); pinMode(24, OUTPUT); digitalWrite(22, HIGH); digitalWrite(23, HIGH); digitalWrite(24, HIGH);}void loop() { static int srv_angle = 0; ir_receive_start(); srv_angle++; servo.write(srv_angle); delay(10); if (srv_angle >= 180) srv_angle = 0;// delay(0xFFFFFFFF); // hold STOP mode until receiving IR signal. if (ir_available()) { Serial.println(ir_getData(), HEX); Serial.flush(); switch (ir_getData()) { case 0xD8: // POWER BUTTON break; case 0xF8: // A BUTTON break; case 0x78: // B BUTTON break; case 0x58: // C BUTTON break; default: break; } }}/************ IR utility function ***************/void ir_receive_interrupt() { unsigned long last_time; detachInterrupt(IR_INTERRUPT); interrupts() ; last_time = micros(); // confirm if reader code is correct uint8_t err = 0; while (!digitalRead(IR_PIN)) { // until change from low to high if ((micros() - last_time) > 10000) { // interval low should be 9ms or less err = true; break; } } while (digitalRead(IR_PIN)) { // until change from high to low if ((micros() - last_time) > 15000) { // interval of reader code should be 13.5ms or less err = true; break; } } if (((micros() - last_time) < 13000) || (err == true)) { // Unknown code attachInterrupt(0, ir_receive_interrupt, FALLING); g_ir_available = false; return; // not available remote controller } // get data uint8_t receive_count = 0; uint8_t temp_ir_data[4] = { 0 }; g_ir_data = 0; last_time = micros(); while ((32 > receive_count) && ((micros() - last_time) < 80000)) { // interval of a frame data should be 76.5ms or less last_time = micros(); while (!digitalRead(IR_PIN) && ((micros() - last_time) < 1000)) { // interval of low state is about 0.56ms. } while (digitalRead(IR_PIN) && ((micros() - last_time) < 2500)) { // interval of a bit is between 1.125ms and 2.25ms } if ((micros() - last_time) > 1500) { bitSet(temp_ir_data[receive_count / 8], receive_count % 8); } receive_count++; } if (temp_ir_data[2] == (uint8_t) ~temp_ir_data[3]) { g_ir_data = temp_ir_data[2]; // set actual data g_ir_available = true; }}void ir_receive_start() { attachInterrupt(IR_INTERRUPT, ir_receive_interrupt, FALLING);}uint8_t ir_getData() { g_ir_available = false; return g_ir_data;}bool ir_available() { return g_ir_available;}#endif#ifdef TONE_TESTvoid setup(){ for(int i = 0; i < 500; i+=10){ tone(5, 500 + i); delay(10); } for(int i = 0; i < 500; i+=10){ tone(5, 1000 - i); delay(10); } noTone(5); delay(500); tone(5, 400, 200); delay(500); tone(5, 400, 1000);}void loop(){}#endif#ifdef STANBY_TEST#include <Arduino.h>void setup(){ Serial.begin(9600); pinMode(13, OUTPUT);}void loop(){ int value; setPowerManagementMode(PM_SNOOZE_MODE, 500, 1023); value = analogRead(A0); Serial.println(value); Serial.flush(); Serial.println(getTemperature(0)); Serial.flush(); setPowerManagementMode(PM_NORMAL_MODE); value = analogRead(A0); Serial.println(value); Serial.flush(); Serial.println(getTemperature(0)); Serial.flush(); delay(100);}#endif#ifdef WAVP_TEST#include <Wavp.h>Wavp wavp(44100, WAVP_OUTPUT_35);void setup(){ Serial.begin(9600); pinMode(24, OUTPUT); digitalWrite(24, LOW);// wavp.play("organ.wav");// analogWrite(6, 50);// analogWrite(9, 100);// analogWrite(10,0);// tone(5, 600);// delay(1000);// noTone(5); wavp.begin(WAVP_SPI1);// digitalWrite(24, HIGH); wavp.play("okoto.wav");// tone(5, 500);// delay(500);// noTone(5); wavp.play("jingle2.wav"); while(1);}void loop(){ tone(3, 500); delay(1000);// wavp.play("1.wav"); tone(3, 500); delay(1000);}#endif#ifdef PULSE_TESTconst int pinPulseOut = 3;const int pinPulseIn = 2;void setup(){ Serial.begin(9600);}void loop(){ for (int i = 1; i <= 255; i++) { analogWrite(pinPulseOut, i); for (int j = 0; j < 10; j++) { noInterrupts(); unsigned long highWidth = pulseIn(pinPulseIn, HIGH, 100000UL); unsigned long lowWidth = pulseIn(pinPulseIn, LOW, 100000UL); interrupts(); char buf[100]; sprintf(buf, "%8ld: high(%3d) low(%3d) => high(%3ld) low(%3ld)", millis(), 8 * i, 8 * (255 - i), highWidth, lowWidth); Serial.println(buf); Serial.flush(); } }}#endif#ifdef GFX_TESTvoid setup(){}void loop(){}#endif
Fujitaさん、ご返信ありがとうございます。
GCC 4.9.2.201701-GNURL78のリリースノートをGoogle翻訳したのが以下ですが、10が前バージョンを使うのにためらうところでしょうかね。
できれば、種々の改善がみられ、テストがあらかた済んでいる201701バージョンを使いたいと思っていますが、いかがですかね?
1. [改善]新しい穴の最適化:特定の8ビットの移動の代わりに16ビットの移動を使用する(コードサイズと速度向上)2. [改善]論理演算( "cstoreqi4"と "cstorehi4")の新しいRTLパターン、ビット操作(「insvmisalign_qi」)、スイッチ文(「casesi」)、8ビット算術演算(「udivqi3」および「umodqi3」)3. [改善点] SFRアドレッシングの改善(コードサイズ縮小)4. [改善]サイズ(-Os)を最適化するときにデフォルトで有効になるリンカの緩和により、改善されていますセクションの破棄(実行可能ファイルの中には実行可能コードとデータサイズの縮小があります)5. [改善点] libgccライブラリのメモリフットプリントが小さくなりました。6. [改善]ファイルの古い8.3命名規則の使用を必要とする制限を削除しました。libgen7. [改善点] Optlibのsnprintfサポートを追加しました。8. [Bug-Fix]最適化の際に関数の引数がスタックに上書きされることがあったまれなケースを修正しましたサイズ(-Os)9. [Bug-Fix] __far関数で32ビット右シフトを実行したときに発生する内部エラーを修正しました。引数10. [Bug-Fix] G13 MCUで不正な結果を返す乗算関連のプリミティブを修正
新しいツールチェーンがリリースされたようです。
新しいツールチェーン GCC for Renesas 4.9.2.201703-GNURL78 で https://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-kurumi/4548/analogwrite-pwm-9-2017/24284#24284 の確認をしてみましたが、
出力コードの不具合は変わらんですね。問題の修正がされる前に現象が再現されなくなることを恐れていましたが良かったです。
> Fujitaさんのクエリには何かございましたか?
リリースノートにある
> 2.[Improvement]objdumpimproved to display the multiplication/division registers by their name instead of their memory-mapped addresses.> 3.[Improvement]The following patterns were added for G10, G13 and G14 cores -udivmodqi4, udivhi3, umodhi3, udivmodhi4, divhi3, modhi3, divmodhi4, udivsi3, umodsi3, divsi3, modsi> 5.[Improvement]Implemented aliases for -mcpu=g10,g13,g14to resemble the manual (s1,s2,s3)> 7.[Bug Fix]Fixed the generation of "es:" before the sfr address.> 8.[Bug Fix]Fixed:mov [de],#IMMis interpreted now as mov [de+0],#IMMmov [hl],#IMMis interpreted now as mov [hl+0],#IMM> 9.[Bug Fix]Fixed the behaviorof lo16, hi16, hi8local symbols to resemblelo16, hi16, hi8global symbols> 11.[Bug Fix]Fixed compile error on accessing sfr with __farpointer.> 14.[Bug Fix]Corrected the save/restore of multiply registers in interrupts.
この辺りが自分が出した要望や報告した不具合だと思います。(業務でもないし面倒なので)まだ確認していませんがうまく対応されてると良いですね。