attachInterrupt() on wifi101 unidentified

Hi ,

My project was to use STM32F429 Nucleo board, and connect the Adafruit WINC1500 breakout for Wifi connection .I use framework as Arduino since I’m more familiar with Arduino that ST.in order to use ATWINC1500 Wifi breakout board Adafruit recommend to use the Wifi101 library .

The library compile and works with no issues on Arduino boards using platform IO .But when i try to use STM32F429 board .There is a compile error saying that

attachInterrupt() unidentified
detachInterrup unidentified .

The issue is with the Arduino interrupt function on the code ,not recognize by the Platformio ide .

void __attribute__((weak)) attachInterruptMultiArch(uint32_t pin, void *chip_isr, uint32_t mode)
{
	attachInterrupt(pin, chip_isr, mode);
}

void __attribute__((weak)) detachInterruptMultiArch(uint32_t pin)
{
	detachInterrupt(pin);
}

Can anyone please help me to solve this issue?

Thanks,
Sam.

Please show the full platformio.ini and code; best would be a complete project upload.

Hi Max,

Thanks for the quick response .
The code I use is the example code given on platformIO that is WIfi101 Library.

platformio.ini

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino

Also this happens when compiling the code.

Yeah the problem is that the caller can’t find the reference to attachInterrupt because the caller is in a .c file and the implementation is in a .cpp file but is not exposed as extern "C", so due to C++ name-mangling, this doesn’t work.

attachInterrupt is definitely there in WInterrupts.cpp.

Simply add the needed glue code in the main CPP file of project. That’s why the function is weak anyways.

extern "C" void attachInterruptMultiArch(uint32_t pin, void *chip_isr, uint32_t mode)
{
   void (*_c)(void) = (void(*)(void))(chip_isr);
   attachInterrupt(pin, _c, mode);
}

extern "C" void detachInterruptMultiArch(uint32_t pin)
{
   detachInterrupt(pin);
}

that plus a platformio.ini of

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
lib_deps = arduino-libraries/WiFi101@^0.16.1

(remember, you should always declare all needed libraries in lib_deps) and the example “WiFi Web Client” in full

#include <Arduino.h>
#include <SPI.h>
#include <WiFi101.h>
#include "arduino_secrets.h" 
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
char server[] = "www.google.com";    // name address for Google (using DNS)

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

void printWiFiStatus();

extern "C" void attachInterruptMultiArch(uint32_t pin, void *chip_isr, uint32_t mode)
{
  void (*_c)(void) = (void(*)(void))(chip_isr);
	attachInterrupt(pin, _c, mode);
}

extern "C" void detachInterruptMultiArch(uint32_t pin)
{
	detachInterrupt(pin);
}

void setup() {


  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}


void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

together with the src/arduino_secrets.h of the form

#ifndef ARDUINO_SECRETS_H
#define ARDUINO_SECRETS_H

#define SECRET_SSID "your wifi here"
#define SECRET_PASS "your password here"

#endif

does compile.

Compiling .pio\build\nucleo_f429zi\src\main.cpp.o
Linking .pio\build\nucleo_f429zi\firmware.elf
Building .pio\build\nucleo_f429zi\firmware.bin
Checking size .pio\build\nucleo_f429zi\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   0.9% (used 2240 bytes from 262144 bytes)
Flash: [          ]   1.6% (used 32944 bytes from 2097152 bytes)
============================= [SUCCESS] Took 5.20 seconds =======================

Thank you so much Max ! Just to be clear, do i have to make the changes on the main or the nm_bsp_arduino.c file? where the attachInterrupt() function exists?

Thanks again .

The main cpp source file of the project, not the library. src/main.cpp in my project’s case. Otherwise it would also be non-portable.

Sidenote: When following Overview | Adafruit ATWINC1500 WiFi Breakout | Adafruit Learning System, the guide also says to inform the library about where CS, IRQ and RST pins are connected to using WiFi.setPins(); .

Also the used SPI object is WINC1501_SPI which by default is mapped to the global SPI object, so the default SPI. If you use custom SPI pins, you will want to call SPI.setMISO(), SPI.setMOSI() and friends before initializing any WiFi stuff, or, in the platformio.ini build_flags = -D WINC1501_SPI=<custom global object name> that you define in your main cpp file too, with the right SPI pins upfront.

Let me know if there’s still trouble – Adafruit anyways recommends to use the check firmware version sketch first, which compiles when using the code

#include <Arduino.h>
#include <SPI.h>
#include <WiFi101.h>
#include <driver/source/nmasic.h>

extern "C" void attachInterruptMultiArch(uint32_t pin, void *chip_isr, uint32_t mode)
{
  void (*_c)(void) = (void (*)(void))(chip_isr);
  attachInterrupt(pin, _c, mode);
}

extern "C" void detachInterruptMultiArch(uint32_t pin)
{
  detachInterrupt(pin);
}

void setup()
{
  // Initialize serial
  Serial.begin(9600);
  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Print a welcome message
  Serial.println("WiFi101 firmware check.");
  Serial.println();

  // Check for the presence of the shield
  Serial.print("WiFi101 shield: ");
  if (WiFi.status() == WL_NO_SHIELD)
  {
    Serial.println("NOT PRESENT");
    return; // don't continue
  }
  Serial.println("DETECTED");

  // Print firmware version on the shield
  String fv = WiFi.firmwareVersion();
  String latestFv;
  Serial.print("Firmware version installed: ");
  Serial.println(fv);

  if (REV(GET_CHIPID()) >= REV_3A0)
  {
    // model B
    latestFv = WIFI_FIRMWARE_LATEST_MODEL_B;
  }
  else
  {
    // model A
    latestFv = WIFI_FIRMWARE_LATEST_MODEL_A;
  }

  // Print required firmware version
  Serial.print("Latest firmware version available : ");
  Serial.println(latestFv);

  // Check if the latest version is installed
  Serial.println();
  if (fv >= latestFv)
  {
    Serial.println("Check result: PASSED");
  }
  else
  {
    Serial.println("Check result: NOT PASSED");
    Serial.println(" - The firmware version on the shield do not match the");
    Serial.println("   version required by the library, you may experience");
    Serial.println("   issues or failures.");
  }
}

void loop()
{
  // do nothing
}

(same additions as above.)

Thank you so much Max for your time .It is indeed working !!! I almost spend few hours try to solve the problem ,and i had no clue what so ever .

Cheers!

Thanks @maxgerhardt for the beautiful fix, which has just been included into the new library WiFiManager_Generic_Lite to provide support to STM32F/L/H/G/WB/MP1 using ATWINC1500/WiFi101

Are the interrupts confirmed working with that code, did you test that? Per STM32 H743ZI Nucleo doesn't support most libraries? - #5 by samsonw it seems to be giving problems on an STM32H7 board, even though it compiles.

It’s OK on STM32F boards.

The H7, because of the STM32 core, is still not supported yet, even the code compiles without error. Hopefully next year :wink:

1 Like