espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.77k stars 7.44k forks source link

ESP32 v2.0.0-rc1 - Using W5500 driver from ESP-IDF and other devices via SPI.h at the same bus #5482

Open swbew opened 3 years ago

swbew commented 3 years ago

Description:

Hey Guys,

I'm trying to implement the esp-idf W5500 driver with lwip using 'direct access' to esp-idf in arduino-esp32. With ESP-IDF 4.4 comes the possibility to use SPI-Ethernet chips in lwip. Additionally I want to use a RC522 RFID-Reader, which is connected to the same SPI bus. For this I want to use the MFRC522 (Arduino) library from here: https://github.com/miguelbalboa/rfid via SPI.h library.

I took the example code from the ESP-IDF to initialize the W5500 from here: https://github.com/espressif/esp-idf/blob/master/examples/ethernet/basic/main/ethernet_example_main.c

Using the W5500 as single device on the SPI bus, works like a charm. But as soon as I access my RC522 RFID reader via SPI.h, the ESP crashes after a few seconds (see test sketch below) with the following Serial output:

assertion "spi_ll_get_running_cmd(hw) == 0" failed: file "IDF/components/hal/spi_hal_iram.c", line 68, function: spi_hal_setup_trans

abort() was called at PC 0x4016eb0b on core 0

Decoded backtrace:

Decoding stack results
0x400ec91d: panic_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/panic.c line 402
0x4008ca2d: esp_system_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/esp_system.c line 128
0x40092b51: abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/newlib/abort.c line 46
0x4016eb0b: __assert_func at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdlib/assert.c line 62
0x40090df1: spi_hal_setup_trans at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/hal/esp32/include/hal/spi_ll.h line 153
0x4008439d: spi_new_trans at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/driver/spi_master.c line 558
0x4008458b: spi_device_polling_start at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/driver/spi_master.c line 938
0x4008466c: spi_device_polling_transmit at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/driver/spi_master.c line 977
0x400ef758: w5500_read at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_eth/src/esp_eth_mac_w5500.c line 96
0x400f0294: emac_w5500_transmit at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_eth/src/esp_eth_mac_w5500.c line 136
0x400ef185: esp_eth_transmit at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_eth/src/esp_eth.c line 328
0x401879af: esp_netif_transmit at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_netif/lwip/esp_netif_lwip.c line 877
0x40109fe9: ethernet_low_level_output at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/port/esp32/netif/ethernetif.c line 118
0x401076e5: ethernet_output at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/netif/ethernet.c line 312
0x40102212: etharp_output_to_arp_index at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/etharp.c line 785
0x401027a5: etharp_output at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/etharp.c line 884
0x4010376d: ip4_output_if_opt_src at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/ip4.c line 1089
0x401037e1: ip4_output_if at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/ip4.c line 890
0x401029eb: icmp_input at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/icmp.c line 250
0x40103447: ip4_input at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/core/ipv4/ip4.c line 790
0x40107641: ethernet_input at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/netif/ethernet.c line 186
0x400f7c7d: tcpip_thread at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/lwip/lwip/src/api/tcpip.c line 180

How can I get Ethernet working with the W5500 board via ESP-IDF while also using SPI.h from arduino-esp32 for RC522 (MFRC522) as a second SPI device on the same bus? Is it planned to support SPI-Ethernet chips in ETH.h with the final release of arduino-esp32 v2.0.0?

Hardware/Environment:

Board WeMos D1 Mini 32
Version/Date arduino-esp32 v2.0.0 RC1
IDE name VSCode + PlatformIO
Flash Frequency 40Mhz
PSRAM enabled no
Upload Speed 115200
Computer OS Windows 10 20H2

Pins used for SPI:

MOSI: 23 MISO: 19 SCK: 18 SS_RFID: 5 SS_W5500: 15 INT_W5500: 25

Sketch:


#include <Arduino.h>
#include <WiFi.h>
#include <ETH.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "driver/spi_master.h"
#include <SPI.h>
#include <MFRC522.h>

MFRC522 mfrc522 = MFRC522();
AsyncWebServer server(80);

const char* PARAM_MESSAGE = "message";
unsigned long rfidCooldown;

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

bool setupW5500() {
  WiFi.begin();
  tcpip_adapter_set_default_eth_handlers();

  // Initialize TCP/IP network interface (should be called only once in application)
  ESP_ERROR_CHECK(esp_netif_init());
  esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
  esp_netif_t *eth_netif = esp_netif_new(&cfg);
  // Set default handlers to process TCP/IP stuffs
  ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif));

  esp_eth_mac_t *eth_mac = NULL;
  esp_eth_phy_t *eth_phy = NULL;

  gpio_install_isr_service(0);

  spi_bus_config_t buscfg = {
    .mosi_io_num = 23,
    .miso_io_num = 19,
    .sclk_io_num = 18,
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
  };
  ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, 1));

  spi_device_handle_t spi_handle = NULL;
  spi_device_interface_config_t devcfg = {
      .command_bits = 16, // Actually it's the address phase in W5500 SPI frame
      .address_bits = 8,  // Actually it's the control phase in W5500 SPI frame
      .mode = 0,
      .clock_speed_hz = 12 * 1000 * 1000,
      .spics_io_num = 15,
      .queue_size = 20
  };
  ESP_ERROR_CHECK(spi_bus_add_device(SPI3_HOST, &devcfg, &spi_handle));
  /* w5500 ethernet driver is based on spi driver */
  eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
  w5500_config.int_gpio_num = 25;

  eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  phy_config.reset_gpio_num = -1;

  eth_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
  if(eth_mac == NULL){
      log_e("esp_eth_mac_new_esp32 failed");
      return false;
  }

  eth_phy = esp_eth_phy_new_w5500(&phy_config);
  if(eth_phy == NULL){
      log_e("esp_eth_phy_new failed");
      return false;
  }

  esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(eth_mac, eth_phy);
  esp_eth_handle_t eth_handle = NULL;
  ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config, &eth_handle));

  uint8_t macArr[] = { 0x02, 0x00, 0x00, 0x12, 0x34, 0x56 };
  ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, macArr));

  /* attach Ethernet driver to TCP/IP stack */
  ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
  /* start Ethernet driver state machine */
  ESP_ERROR_CHECK(esp_eth_start(eth_handle));

return true;
}

void setupRFID(){
  SPI.begin();
  mfrc522.PCD_SetAntennaGain(112);
  delay(50);
  mfrc522.PCD_Init(5, 0);
  delay(50);
  Serial.printf("[ INFO ] RFID SS_PIN: %u and Gain Factor: %u", 5, 112);
  Serial.println("");
  delay(50);
}

void setupWebserver() {
      server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

    // Send a GET request to <IP>/get?message=<message>
    server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
        String message;
        if (request->hasParam(PARAM_MESSAGE)) {
            message = request->getParam(PARAM_MESSAGE)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, GET: " + message);
    });

    // Send a POST request to <IP>/post with a form field message set to <message>
    server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
        String message;
        if (request->hasParam(PARAM_MESSAGE, true)) {
            message = request->getParam(PARAM_MESSAGE, true)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, POST: " + message);
    });

    server.onNotFound(notFound);
    server.begin();

    Serial.print("IP Address: ");
    Serial.println(ETH.localIP());
}

bool rfidloop() {
  mfrc522.PCD_Init();
  delay(50);

  if (! mfrc522.PICC_IsNewCardPresent()) {
    delay(50);
    return false;
  }
  if (! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return false;
  }

  rfidCooldown = millis() + 2000;
  Serial.println("[ RFID ] Card detected to read!");
  mfrc522.PICC_HaltA();

  Serial.print(F("[ INFO ] PICC's UID: "));
  String uid = "";
  for (int i = 0; i < mfrc522.uid.size; ++i) {
    uid += String(mfrc522.uid.uidByte[i], HEX);
  }
  Serial.println(uid);
  return true;
}

void setup() {
    Serial.begin(9600);
    setupRFID();  //comment this line to get Ethernet working

    setupW5500();    //comment this line to get RFID working
    setupWebserver(); //comment this line to get RFID working
}

void loop() {
  if (rfidCooldown < millis()) {
    rfidloop();
  }
}
swbew commented 3 years ago

just a little push for this...

Is it basically planned to also support SPI LAN modules in the final version 2.0? In the coding I saw with the condition on the DM9051 that there was a 'to do' note. I would also like to contribute with the implementation, but unfortunately I don't seem to have any more in-depth knowledge about the peculiarities in using SPI in ESP-IDF. Maybe a little hint could help.

iot4all commented 3 years ago

Yes - support of SPI-LAN would increase ESP possibilities a lot. The integrated ESP-WLAN + separate LAN-module (i.e. cheap and powerful Wiznet 5500) would deliver connections for nearly all cirumstances. Many people looking for that.

Would be great to hear about your planning about SPI-LAN. How I can support you?

swbew commented 3 years ago

As you can see above it already works with v2.0.0 RC1, if you use only the W5500 device on the SPI bus, using ESP-IDF. If you add another SPI device via Arduino-ESP32s SPI library the ESP crashes.

I really would like to implement this in Arduino-ESP32s ETH library, but my skills in ESP-IDF are reaching there limits. Maybe @me-no-dev has a hint, how to do this!?

VojtechBartoska commented 2 years ago

Hello @swbew , sorry for late reply. Are you able to test your issue on development version 2.0.3-RC1 to check if this is still valid? You can take a look on Docs where is explained how to choose development release version in Arduino IDE.

VojtechBartoska commented 2 years ago

Hello,

as there was no answer in last 14 days, I'm closing the issue as expired to keep our backlog manageable. If it's still needed, please reopen the issue.

Thanks for understanding.

mkrasselt1 commented 2 years ago

https://github.com/johnnytolengo/w5500lwip/ We are using this quite successfully, works for over a year like a charm as a websocket client, only problem is, dhcp is broken and sometimes the connection needs a few attempts to get it stable... maybee it helps someone or you could improve on it: Edit: It integrates into lightweight ip stack and replaces the wifi hardware connection to keep the existing sketches working

swbew commented 2 years ago

@VojtechBartoska Sorry for the late reply. I tested again with 2.0.3-RC1 with (nearly) the same result... assert failed: spi_hal_setup_trans IDF/components/hal/spi_hal_iram.c:68 (spi_ll_get_running_cmd(hw) == 0)

Decoded backtrace:

0x40083dad: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c line 402
0x4008c211: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c line 128
0x40091e41: __assert_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/assert.c line 85
0x400901ed: spi_hal_setup_trans at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/spi_ll.h line 149
0x400818e4: spi_new_trans at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/spi_master.c line 561
0x40081afe: spi_device_polling_start at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/spi_master.c line 958
0x40081be0: spi_device_polling_transmit at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/spi_master.c line 1000
0x400ea3e9: w5500_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_eth/src/esp_eth_mac_w5500.c line 96
0x400ea50c: emac_w5500_read_phy_reg at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_eth/src/esp_eth_mac_w5500.c line 387
0x40148b35: eth_phy_reg_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_eth/src/esp_eth.c line 70
0x400eb373: w5500_get_link at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_eth/src/esp_eth_phy_w5500.c line 65
0x40148b1f: eth_check_link_timer_cb at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_eth/src/esp_eth.c line 161
0x40106297: timer_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_timer/src/esp_timer.c line 360
VojtechBartoska commented 2 years ago

thanks for testing @swbew, we will take a look.

mkrasselt1 commented 2 years ago

We got it working - will post the code soon

mkrasselt1 commented 2 years ago

https://github.com/mkrasselt1/esp32-lan-w5500 Check it out here, i home i removed all references to our software project from it, use it by include and

#include "w5500/w5500-lwIP.h"
Wiznet5500lwIP ethernet(CS_WIZNET);
WiFi.begin();
WiFi.mode(WIFI_OFF);
uint8_t mac[6];
WiFi.macAddress(mac);
IPAddress _IP(192,168,188,100);
IPAddress _GW(192,168,188,1);
IPAddress _NM(255,255,255,0);
IPAddress _DNS(8,8,8,8);
//static
ethernet.begin(mac, _IP, _NM,_GW, _DNS)
//dhcp
ethernet.begin(mac)

like this you can use all existing libraries for tcp stuff like async websocket client, mqtt and soon :)

Note: this is only using the w5500 as a phy interface, tcp processing is completly done in the esp main processor -> no offloading at all

tsctrl commented 2 years ago

hi @mkrasselt1 is this will work with Wifi too? mean wifi and eth work side by side together getting data in sync?

instead of WIFI_OFF to WIFI_AP or STA?

tsctrl commented 2 years ago

Hi @mkrasselt1 tested your codes not working and it trigger wdt on my end.

abort() was called at PC 0x4010e940 on core 0
esp_system/esp_system.c:128
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

  Id   Target Id          Frame
* 1    process 1073486160 0x40081dad in panic_abort (details=0x3ffb1536 \"abort() was called at PC 0x4010e940 on core 0\") at esp_system/panic.c:402
  2    process 1073486520 0x4008c981 in vPortExitCritical (mux=<optimized out>) at freertos/port/xtensa/include/freertos/portmacro.h:571
  3    process 1073488992 0x40177ad2 in esp_pm_impl_waiti () athal/esp32/include/hal/cpu_ll.h:183
  4    process 1073507440 0x40089e56 in xQueueReceive (xQueue=0x3ffc617c, pvBuffer=0x3ffc6bcc, xTicksToWait=<optimiz  4    process 1073507440 0x40089e56 in xQueueReceive (xQueue=0x3ffc617c, pvBuffer=0x3ffc6bcc, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  5    process 1073491464 0x4008c5c4 in prvProcessTimerOrBlockTask (xListWasEmpty=<optimized out>, xNextExpireTime=0) at hal/esp32/include/hal/cpu_ll.h:39
  6    process 1073412864 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffaf68c, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  7    process 1073511096 0x40089e56 in xQueueReceive (xQueue=0x3ffc6fe0, pvBuffer=0x3ffc79e0, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  8    process 1073515568 0x40089e56 in xQueueReceive (xQueue=0x3ffc6ed4, pvBuffer=0x3ffc8b8c, xTicksToWait=<optimiz  8    process 1073515568 0x40089e56 in xQueueReceive (xQueue=0x3ffc6ed4, pvBuffer=0x3ffc8b8c, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  9    process 1073413524 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffafd30, xTicksToWait=<optimized out>) at C:/  9    process 1073413524 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffafd30, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  10   process 1073523548 0x40089e56 in xQueueReceive (xQueue=0x3ffc9844, pvBuffer=0x3ffcaab0, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  11   process 1073479636 0x4000bff0 in ?? ()

edit: i have: remove the storage undefined error. xQueueReceive from xQueueGenericReceive which is not available in 4.4.1 add delay, change core, change priority with the same result.

mkrasselt1 commented 2 years ago

hi @mkrasselt1 is this will work with Wifi too? mean wifi and eth work side by side together getting data in sync?

instead of WIFI_OFF to WIFI_AP or STA?

Sadly not to my knowledge - because its replaces the output of the phy interface from. Wifi to able to reuse existing libraries - but - this should be possible by adding another interface to lwip stack - and the router. But we did not yet figured it out.

mkrasselt1 commented 2 years ago

Hi @mkrasselt1 tested your codes not working and it trigger wdt on my end.

abort() was called at PC 0x4010e940 on core 0
esp_system/esp_system.c:128
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

  Id   Target Id          Frame
* 1    process 1073486160 0x40081dad in panic_abort (details=0x3ffb1536 \"abort() was called at PC 0x4010e940 on core 0\") at esp_system/panic.c:402
  2    process 1073486520 0x4008c981 in vPortExitCritical (mux=<optimized out>) at freertos/port/xtensa/include/freertos/portmacro.h:571
  3    process 1073488992 0x40177ad2 in esp_pm_impl_waiti () athal/esp32/include/hal/cpu_ll.h:183
  4    process 1073507440 0x40089e56 in xQueueReceive (xQueue=0x3ffc617c, pvBuffer=0x3ffc6bcc, xTicksToWait=<optimiz  4    process 1073507440 0x40089e56 in xQueueReceive (xQueue=0x3ffc617c, pvBuffer=0x3ffc6bcc, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  5    process 1073491464 0x4008c5c4 in prvProcessTimerOrBlockTask (xListWasEmpty=<optimized out>, xNextExpireTime=0) at hal/esp32/include/hal/cpu_ll.h:39
  6    process 1073412864 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffaf68c, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  7    process 1073511096 0x40089e56 in xQueueReceive (xQueue=0x3ffc6fe0, pvBuffer=0x3ffc79e0, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  8    process 1073515568 0x40089e56 in xQueueReceive (xQueue=0x3ffc6ed4, pvBuffer=0x3ffc8b8c, xTicksToWait=<optimiz  8    process 1073515568 0x40089e56 in xQueueReceive (xQueue=0x3ffc6ed4, pvBuffer=0x3ffc8b8c, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  9    process 1073413524 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffafd30, xTicksToWait=<optimized out>) at C:/  9    process 1073413524 0x40089fc0 in xQueueSemaphoreTake (xQueue=0x3ffafd30, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  10   process 1073523548 0x40089e56 in xQueueReceive (xQueue=0x3ffc9844, pvBuffer=0x3ffcaab0, xTicksToWait=<optimized out>) at hal/esp32/include/hal/cpu_ll.h:39
  11   process 1073479636 0x4000bff0 in ?? ()

edit: i have: remove the storage undefined error. xQueueReceive from xQueueGenericReceive which is not available in 4.4.1 add delay, change core, change priority with the same result.

I will look into this because it's working fine on multiple devices running 3.1.0 (yes we are a bit behind on this))

tsctrl commented 2 years ago

hi @mkrasselt1 i am able to initialize the module with ip, and dns works too. but wificlient are not connected to the w5500. wificlient.connect(url) return unable to reach error. i guess there is something missing on where to bridge/initialize the client to the w5500 class.

do you have the details on that part? which client are you using to do a http call? your help are much appreciated, thanks!