earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.03k stars 423 forks source link

Compilation Warning on Pico W `warning: left shift count >= width of type [-Wshift-count-overflow]` #2550

Closed eMUQI closed 1 week ago

eMUQI commented 1 week ago

Hi there,

I tried running the following code on Raspberry Pi Pico, Pico W, and Pico 2:

/*
  This Arduino receive and decode infrared (IR) signals from a remote control. It uses 
  the IRremote library to receive the IR signals and map them to corresponding keys like 
  numbers, mathematical operations, and other function keys.

  Board: Raspberry pi pico
  Component: Infrared Receiver
  Library: https://github.com/Arduino-IRremote/Arduino-IRremote (IRremote by shirriff, z3t0, ArminJo)
*/

// Include the necessary libraries
#define SEND_PWM_BY_TIMER 
#include <IRremote.hpp> 

// Define the pin numbers for the IR receiver
const int IR_RECEIVE_PIN = 15;

void setup() {
  Serial.begin(9600);                                     // Start serial communication at 9600 baud rate
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  // Start the IR receiver
}

void loop() {
  // Check if there is any incoming IR signal
  if (IrReceiver.decode()) {
    // IrReceiver.printIRResultShort(&Serial);                 // Print the received data in one line
    // Serial.println(IrReceiver.decodedIRData.command, HEX);  // Print the command in hexadecimal format
    Serial.println(decodeKeyValue(IrReceiver.decodedIRData.command));  // Map and print the decoded IR signal to corresponding key value

    IrReceiver.resume();  // Enable receiving of the next value
  }
}

// Function to map received IR signals to corresponding keys
String decodeKeyValue(long result) {
  // Each case corresponds to a specific IR command
  switch (result) {
    case 0x16:
      return "0";
    case 0xC:
      return "1";
    case 0x18:
      return "2";
    case 0x5E:
      return "3";
    case 0x8:
      return "4";
    case 0x1C:
      return "5";
    case 0x5A:
      return "6";
    case 0x42:
      return "7";
    case 0x52:
      return "8";
    case 0x4A:
      return "9";
    case 0x9:
      return "+";
    case 0x15:
      return "-";
    case 0x7:
      return "EQ";
    case 0xD:
      return "U/SD";
    case 0x19:
      return "CYCLE";
    case 0x44:
      return "PLAY/PAUSE";
    case 0x43:
      return "FORWARD";
    case 0x40:
      return "BACKWARD";
    case 0x45:
      return "POWER";
    case 0x47:
      return "MUTE";
    case 0x46:
      return "MODE";
    case 0x0:
      return "ERROR";
    default:
      return "ERROR";
  }
}

The code compiled and ran successfully on both Pico and Pico 2. However, when compiling on Pico W, I encountered the following warnings:

In file included from C:\Users\Administrator\AppData\Local\Temp\arduino\sketches\CA1AE1E3AC91991AFBFDB186BD7ED54A\sketch\sketch_oct17a.ino.cpp:1:
c:\Users\Administrator\Documents\Arduino\libraries\IRremote\src/IRFeedbackLED.hpp: In function 'void setFeedbackLED(bool)':
C:\Users\Administrator\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\4.1.1\cores\rp2040/Arduino.h:79:66: warning: left shift count >= width of type [-Wshift-count-overflow]
   79 | #define digitalWriteFast(pin, val)  (val ? sio_hw->gpio_set = (1 << pin) : sio_hw->gpio_clr = (1 << pin))
c:\Users\Administrator\Documents\Arduino\libraries\IRremote\src/IRFeedbackLED.hpp:121:13: note: in expansion of macro 'digitalWriteFast'
  121 |             digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
      |             ^~~~~~~~~~~~~~~~

I’m surprised to see this difference between the Pico and Pico W, as I expected them to behave similarly when no networking features are involved (please correct me if I’m wrong).

I’ve raised a related discussion in the IRremote repository, where one of the maintainers suggested that this might be a design oversight. Hence, I’m submitting it here for further clarification.

Link to the discussion: https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1267#discussioncomment-10974259

It is an warning in the Arduino.h and https://github.com/earlephilhower/arduino-pico is responsible for this. The parameters are digitalWriteFast(LED_BUILTIN, LOW) which results in digitalWriteFast(32, 0) which results in (LOW ? ((sio_hw_t )0xd0000000u)->gpio_set = (1 << 32) : ((sio_hw_t )0xd0000000u)->gpio_clr = (1 << 32)) which looks like a design error.

Is there a way to suppress this warning, or could this be an unintended design issue?

Thanks in advance for your assistance!

dquadros commented 1 week ago

In the Pico W the LED is not connected to the microcontroller (RP2040 or RP2350) but to the WiFi/BT chip (CYW43439 ), so you cannot control it by accessing the microcontroller registers (as digitalWriteFast does). The normal digitalWrite tests this special case and instead of using the normal digital IO it sends a command to the CYW43439.

You can try undefining LED_BUILTIN before including IRRemote:

#define SEND_PWM_BY_TIMER 
#undef LED_BULTIN
#include <IRremote.hpp>

You still get a warning that LED feedback is disabled.

earlephilhower commented 1 week ago

Thanks, @dquadros . This is a code issue with the IR library using a call that's not legal on the Pico W because the LED is not accessible by the RP2040 chip directly. You could try undefining the value as suggested, or simply replacing digitalWriteFast with digitalWrite would work. (Also, because the LED is connected to the WiFi chip, it is relatively slow to update compared to the real GPIOs.)