Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: driver/winc1500: Initial port for Wi-Fi module against NETDEV_ETH. #7433

Closed
wants to merge 23 commits into from

Conversation

kbumsik
Copy link
Contributor

@kbumsik kbumsik commented Jul 31, 2017

This is my first attempt to port WINC1500 wi-fi module to gnrc_netdev.
The WINC1500 is a Wi-Fi module integrated in arduino-mkr1000. You can also get it a SAM-XPRO-xpro-board-friendly module, ATWINC1500-XPRO.

This module has a full TCP/IP stack so it is intended to be used with its BSD Socket-like API only. However, I realized there is kind of a hidden and undocumented feature called Ethernet Bypass Mode for this module. So I decided to port against gnrc_netdev, instead of RIOT socket API.

Currently, the Wi-Fi connects very well to a router and is able to send packets and receive packets. But I am not sure if it receives and sends correct packet yet so the GNRC doesn't seem to be working well. As I don't have much experience in debugging GNRC I opened this PR as WIP to get some advice.

Related: #7125 #7025 #6666

Alt text

Hardware configuration

This port is currently targeting the following hardware:

The Wi-Fi module may need firmware update to work, since the driver only supports the latest version 19.5.2. To update the firmware, please look at winc1500.h.

Regarding the WINC1500 API code.

There is a pack of files RIOT community won't like - files in winc1500/pkg directory. Since there will be too much things to work otherwise, I decided to keep the original WINC1500 API library under winc1500/pkg for this moment. But it is very offensive to RIOT's coding conventions:

  • CamelCase, Hungarian notations, tabs instead of spaces....
  • Non-reentrant code. and allow only one instance...
  • At least the license is LGPL compatible 3-clause BSD.

I am not sure what to do with this code. So I kept the original code as original as possible for now. I wrapped round the modified code with #ifdef MODULE_WINC1500.

This concern is resolved by moving it to pkg directory. See the comments below. The only problem and biggest problem is:

  • non-reentrant code. and allow only one instance.

This change is Reviewable

@aabadie
Copy link
Contributor

aabadie commented Aug 14, 2017

Great job! I'll be a able to test it next week, when I'll be with the hardware. Thanks a lot for working on this.

There is a pack of files RIOT community won't like - files in winc1500/pkg directory

I would recommend to create a pkg/winc1500 and download/configure/build them on the fly. See how other packages are built. The idea would be to download the external files from another git repository (did you take them from here or from Atmel Studio ? ). Finally, just the minimum adaption code for RIOT will be required and that would this PR easier to review.

@aabadie aabadie added Area: network Area: Networking Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Aug 14, 2017
@aabadie aabadie added this to the Release 2017.10 milestone Aug 14, 2017
@kbumsik
Copy link
Contributor Author

kbumsik commented Aug 14, 2017

I see. The code I downloaded is from the gaint ASF package from Microchip homepage (the link you asked is the version 19.4.4). Should I make a script downloading the ASF or make a git repo for it?
Then will I put the netdev adoption code in pkg/winc1500, not in driver/winc1500 As well?

@aabadie
Copy link
Contributor

aabadie commented Aug 14, 2017

Should I make a script downloading the ASF or make a git repo for it?

With a repo, it will be easy to get only the winc1500 part (in common/components/wifi/winc1500), with the first option you'll have to download the whole archive first (400MB), then extract it (1.6GB) and then remove the unused parts. I will go for the repo.

Then will I put the netdev adoption code in pkg/winc1500, not in driver/winc1500 As well?

I haven't checked your code in detail but I would say that it can be kept in drivers/winc1500. The pkg folder part should just be used for the download, eventually for patching some parts of the ASF code and for adding the Makefile rules to build what's required. Then primitives from ASF can be called from the driver implementation and netdev adaption (I think).

@kbumsik
Copy link
Contributor Author

kbumsik commented Aug 14, 2017

I will go for the repo.

I prefer the git repo too. I am just wondering if you are okay with creating my own github repo for WINC1500 since I cannot find an exact repo available I am looking for.

I haven't checked your code in detail but I would say that it can be kept in drivers/winc1500.

Okay. I will keep the adoption code in drivers/winc1500. I will change it within a few days so you can see how it’s gonna look like.

@aabadie
Copy link
Contributor

aabadie commented Aug 15, 2017

I am just wondering if you are okay with creating my own github repo for WINC1500 since I cannot find an exact repo available I am looking for.

Yes, in a first step you can create your own repo containing only the winc1500 related files. We'll see later if we want to host it under the RIOT-OS organization.

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 2, 2017

@aabadie I resolved the pkg issue as you wish. I created a repo containing the original driver and then made RIOT-specific git-patch in pkg/winc1500 directory. You may take a look.

@aabadie
Copy link
Contributor

aabadie commented Oct 2, 2017

That's awesome @kbumsik, I'll see if I can try this week (quite busy)

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a rather big PR, I have lots of comments :)
But in general you made a very good work (not to say awesome again), the test application is very nice. I overlooked a bit the internal implementation of the driver due to lack of time. I'll go back to it later.

@@ -31,6 +31,21 @@
extern "C" {
#endif


/**
* @name winc1500 configuration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be @brief

.en_pin = GPIO_PIN(PA, 28), /* Internally pulled-down */ \
.wake_pin = GPIO_PIN(PB, 8), \
.spi_clk = WINC1500_SPI_CLOCK}
/** @} */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed

USEMODULE += netdev_eth
USEMODULE += core_mbox
ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
# XXX: this can be modelled as a dependency for gnrc_netdev_default as soon
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation is only 2 spaces (4 in total for the 2 lines)

endif
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_spi
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing newline at end of file

@@ -133,3 +133,7 @@ endif
ifneq (,$(filter sx127%,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sx127x/include
endif
ifneq (,$(filter winc1500,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/winc1500/include
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent (2 spaces)

Copy link
Contributor Author

@kbumsik kbumsik Oct 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 4 spaces indentation is used eveywhere in this file though. I am keeping it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, but this is because your branch is not up-to-date with latest master. The 2 spaces indent is the default for Makefile and have recently been changed in this file by #7576

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. I will make it 2 spaces then.


#else
typedef int dont_be_pedantic;
#endif /* MODULE_GNRC_NETDEV */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing newline at end of file


/**
* @brief Define stack parameters for the MAC layer thread
* @{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

# set board specific peripheral configurations
ifneq (,$(filter samr21-xpro,$(BOARD)))
# Settings for SAMR21-XPRO Board
CFLAGS += -DWINC1500_SPI=\(\SPI_DEV\(1\)\)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since some Atmel extensions exists for Samr21-xpro and samd21-xpro boards (and maybe others), I think you can add a winc1500_params.h in the corresponding boards include directories.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds better to me too. But in which file you want me add? boards/<board>/include/board.h files for each boards or driver/winc1500/include/winc1500_params.h?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should go in boards/sam{d,r,l}21-xpro/include/winc1500_params.h. It will then be included in place of the driver one. See boards/nz32-sc151/include/sx127x_params.h and drivers/sc127x/include/sx127x_params.h as example.

Copy link
Contributor Author

@kbumsik kbumsik Oct 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for a kind advice :) I looked at the examples. Because they are the same name, I am just wondering if it is alway guaranteed to include the boards include first, before the driver include?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am just wondering if it is alway guaranteed to include the boards include first

Normally it is.

| 19 | GND |
| 20 | VCC |

### ATECC508A Crypto device Connection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this also available in the ATWINC1500 ? or only related to the atmel extension ?

Copy link
Contributor Author

@kbumsik kbumsik Oct 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ATECCx08 is something like a tiny companion chip with ATWINC1500, although it is a separated chip. MKR1000 also has that chip (ATECC108) inside of the ATSAM25 module. I guess this crypto module is used for Atmel's built-in SSL socket implementation. So I thought it is worth noting here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

*/

/**
* @ingroup driver_winc1500
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong group, it should be tests

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 2, 2017

Fixed indentation and doxygen mistakes. I commented on other issues.

* ## Introduction
* WINC1500 (or ATWINC1500) is a Wi-Fi chipset from Atmel. This chipset is
* designed to be used with microcontrollers(MCUs). This is offered as Wi-Fi
* only modules to interface with a MCU thorugh SPI and complete MCU modules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/thorugh/through/

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of new comments. Maybe @miri64 could also help reviewing the netdev adaption.

break;
}
mbox_put(&dev->event_mbox, &msg);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing newline

addr += sizeof(event_info.prng_result);
recv_size = event_info.prng_result.u16PrngSize;
is_done = 1;
if(hif_receive(addr, event_info.prng_result.pu8RngBuff,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space missing after if

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 4, 2017

Typo fixed, and moved the module configuration. It is good to have the reviewer :) I will try to rebase it this weekend. Looks like there are going to be a lot of changes on gnrc soon in the master though :P

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 9, 2017

Branch is rebased to the latest master and cleaned the commit messages.

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had another look at the changes and found some other minor things.
There's something that seems wrong to me regarding the way the device descriptor is accessed: using extern is wrong to me. What's the reason for doing that ?

int winc1500_scan(void);

/**
* @brief Retrive information of an access point.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/retrive/retrieve/

int winc1500_connect_list(const winc1500_ap_t ap_info[]);

/**
* @brief Retrive information of a connected access point.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/retrive/retrieve/

Copy link
Contributor Author

@kbumsik kbumsik Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I am going to install a spell checker.

* @brief Flags for device internal states (see datasheet)
*/
typedef enum {
WINC1500_EVENT_NOTHING = (0),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe document the values, otherwise Murdock will complain

#endif
} winc1500_event_info_t;

extern winc1500_t winc1500; /**< winc1500 object */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a problem since it prevents having multiple devices. This is very unlikely to happen but is not the way other device drivers are handled by RIOT.
In the auto_init file, there should a static array of device descriptor defined. Only use devices descriptor from there.

Copy link
Contributor Author

@kbumsik kbumsik Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I don't like this either...please see my follow-up comment in the discussion. I was not sure if I should force making it as array regardless of the Atmel's WINC1500 API limitation...

/**
* @brief Prevent other threads from entering the function concurrently.
*/
static inline void _lock(winc1500_t *dev) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curly brace should be on next line (same issue below)

* @brief Wait for specific desired event, or return error when an event in
* a 'black list'.
*/
static int wait_for_event(msg_t *response, uint16_t event, uint16_t error_event)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a bad design. Why not passing the device descriptor pointer as argument ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I can put the device descriptor pointer here at least. I will put that pointer parameter as much as I can do for now. I am aware this is bad design. (see the comment in the discussion below)

return WINC1500_OK;
#endif
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one empty line is enough (I saw the same issue above)

for (int i = 0; i < count; i++) {
m2m_wifi_send_ethernet_pkt(vector[i].iov_base, vector[i].iov_len);
len += vector[i].iov_len;
/* TODO: what if the module's buffer full? */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am working on this :) Please note that it is WIP for this moment.


static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
{
/* winc1500_t *dev = (winc1500_t *) netdev; */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually the correct way normally

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I commented out here because winc1500_t *dev is not used in that function. I think extern global parameter problem doesn't exist at least in winc1500_netdev.c.

#endif
/** @} */

extern winc1500_t winc1500; /** Located in winc1500.c */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you should define an array of devices instead of accessing an external variable

Copy link
Contributor Author

@kbumsik kbumsik Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my other comments. Here I did something similar to auto_init_encx24j600.c. I need to discuss about it.

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 9, 2017

Oh sorry I forgot to mention about that problem, which is the biggest reason I set WIP for this PR. This is because of one of the Atmel's WINC1500 API problem I listed first:

Non-reentrant code. and allow only one instance.

The WINC1500 API from Atmel cannot support multiple instances by its design (it doesn't have even device descriptor struct). If I strictly follow RIOT API design I have to re-engineer the WINC1500 API thoroughly. I spent around a month to work around but I ended up with using only one winc1500_t device descriptor to use everywhere. FYI, that global one is also used in pkg/winc1500/winc1500/bsp/source/nm_bsp_riot.c and pkg/winc1500/winc1500/bus_wrapper/source/nm_bus_wrapper.c for SPI bus for WINC1500 API.

So currently I removed device descriptor pointer parameter to the function defined in winc1500.c to tell there is no more than one device allowed. But I mean this is for now, I can put the descriptor pointer parameter back. But I am not sure what is the best way to deal with the Atmel's WINC1500 API's single device design...

Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure your device can work with just netdev. Other network stacks might want to benefit from the WiFi driver as well ;-).

#include "mbox.h"
#include "periph/spi.h"
#include "periph/gpio.h"
#ifdef MODULE_GNRC_NETDEV
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below: can you check for MODULE_GNRC? This way it's more portable. If all goes right, gnrc_netdev will be deprecated in favor for gnrc_netif2 at the end of the week.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I will test for MODULE_GNRC. Is gnrc_netif2 related to #7424 ? Looks like I need to keep track of the new gnrc_netif2.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I need to keep track of the new gnrc_netif2.

If your recv netdev-method just outputs Ethernet frames, the send method expect them and all MAC is done by the device, you really don't have to (only maybe for the initialization). The abstraction of netdev_eth should take care of that

Copy link
Contributor Author

@kbumsik kbumsik Oct 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this Wi-Fi module will take care of MAC. Good. I will focus on netdev_eth then.

/* Private functions */
/* -------------------------------------------------------------------------- */
#ifdef MODULE_GNRC_NETDEV
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#ifndef MODULE_GNRC_NETDEV

instead?

Copy link
Contributor Author

@kbumsik kbumsik Oct 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change them. Should I consider using MODULE_GNRC here too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry. There were some minutes between this comment and the previous ^^

/* Wake up handler */
#ifdef MODULE_GNRC_NETDEV
/* When GNRC enabled it doesn't need to wake it up here. */
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use #ifndef?

done:
#ifdef MODULE_GNRC_NETDEV
/* When GNRC enabled this function doesn't need to sleep handler here. */
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dito

* @}
*/

#ifdef MODULE_GNRC_NETDEV
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks more like netdev specific-code. gnrc_netdev is just the glue-code between GNRC and netdev. netdev can be used with other network stacks (like lwIP).

Copy link
Contributor Author

@kbumsik kbumsik Oct 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So using MODULE_NETDEV_ETH here might be best?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since without netdev this functions won't be used, optimization throws them out anyway, so no guard is needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(but yes, if a guard is needed (e.g. for struct members), then MODULE_NETDEV_ETH would be better).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After tried. It needs the guard because of a lot of NETDEV specific struct members in the code. So I will keep the guard.

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 11, 2017

@miri64 Thank you for your comments. After looking at your lwip stack adapter layer test example I finally understand how network layer modules look like. This PR is not on GNRC layer but NETDEV_ETH so I fixed all #ifdef blocks for MODULE_NETDEV_ETH.

@kbumsik kbumsik changed the title WIP: driver/winc1500: Initial port for Wi-Fi module against gnrc_netdev. WIP: driver/winc1500: Initial port for Wi-Fi module against NETDEV_ETH. Oct 11, 2017
@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 13, 2017

After getting a proper debugging environment with a router that I can Wireshark to, I figured out the problem with my driver and was able to fix. Now WINC1500 sends packets correctly and I can ping to other device very well 😄 !

There are some optimization problems left (other than the design issue mentioned in previous comments):

  • The module driver gets down under high peak network loads (>20 packets/ms). The module stops receiving after the peak. This is probably because of lossy interrupts at the peak.
  • It currently needs additional 1500s bytes of buffer to send ethernet frames to the module. I am working on a workaround to remove the buffer.

Anyway. @aabadie could you test the WiFi module if it works correctly on your device too, when you have time? :)

@aabadie
Copy link
Contributor

aabadie commented Oct 13, 2017

Now WINC1500 sends packets correctly and I can ping to other device very well 😄 !

Super cool!

I'll test asap so probably not before next wednesday.

@kbumsik
Copy link
Contributor Author

kbumsik commented Sep 1, 2018

@aabadie Thank you for posting the test result! I will look at netdev implementation to see if there is something missing.
In gnrc_networking example, does it need any steps to acquire a global ipv6 address? or it supposed to get a global address automatically?

Copy link
Member

@bergzand bergzand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick check over the netdev interface implementation here. Feel free to ignore those comments about the netstats for now. I'll give you a heads up as soon as things need to be changed here. The issue on dropping frames should be fixed though, that one can cause nasty issues with GNRC


#ifdef MODULE_NETSTATS_L2
memset(&netdev->stats, 0, sizeof(netstats_t));
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed as soon as #9793 is merged


#ifdef MODULE_NETSTATS_L2
netdev->stats.tx_bytes += len;
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed as soon as #9793 is merged

#ifdef MODULE_NETSTATS_L2
netdev->stats.rx_count++;
netdev->stats.rx_bytes += len;
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And another one that can be removed as soon as #9793 is merged

return len;
}

static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add functionality here to drop the frame when recv is called with NULL as buf and with non-zero length (https://github.com/RIOT-OS/RIOT/blob/master/drivers/include/net/netdev.h#L319)

Copy link
Contributor Author

@kbumsik kbumsik Oct 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bergzand I see. There is something not clear to me: should if drop the packet when returning -ENOBUFS, when buffer is smaller than the packet?

@aabadie
Copy link
Contributor

aabadie commented Sep 1, 2018

In gnrc_networking example, does it need any steps to acquire a global ipv6 address? or it supposed to get a global address automatically?

Normally with gnrc_networking, the global address is set automatically (at least with 802.15.4 radios). I think something is missing in the driver implementation of netdev interface but I'm not sure. @miri64 or @bergzand could help here.

Copy link
Contributor Author

@kbumsik kbumsik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finished the long overdue. As @aabadie requested I added multiple instance support and removed the global variables shared within the driver files. I did this by re-engineered the original Atmel driver so that the Atmel driver is now accept individual devices (winc1500_t *dev is added in almost all functions) and is re-entrant. There is one problem though. I added in-line comment about that.

I will look into other issues suggested in the other comments now.

#ifdef MODULE_NETDEV_ETH
/* Import winc1500 objects from auto_init_winc1500.c */
extern winc1500_t winc1500_devs[];
winc1500_t *winc1500_dev = &winc1500_devs[0];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently the only use of global variable. This is needed after adding multiple WiFi modules support.
Because, in the application code, the user need to select a WiFi device when asking for scanning/connecting/etc, the user should select one of the device descriptors winc1500_devs defined in auto_init_winc1500.c.
@aabadie What do you think about this?

@aabadie
Copy link
Contributor

aabadie commented Oct 19, 2018

Thanks for your efforts with working on this @kbumsik !

I've just tested again this PR and it's still working as before. Only the first ping timeout and the long ipv6 address is not set, but I think this is not related to this PR but rather something missing in netdev_eth.

What do you think about this?

I had a closer look at the test application and since it includes auto_init_gnrc_netif module, it implicitly includes auto_init which calls the auto_init_winc1500 function automatically at boot. So there's no need in defining the new array of devices in the application. The array of device in auto_init could also be made static (like with other radio devices).
The question now is how to retrieve the device pointer from the application. This can be done by adding an extra parameter to the shell commands indicating the number of the device. This number correspond simply to the thread pid the device is attached to. This is what is used by ifconfig for example:

ifconfig <device number>

From this pid you should be able to get the corresponding netif pointer with gnrc_netif_iter, then from the netif pointer you can access to the netdev device. You can then call the scan/connect/disconnect functions with it.
You have "examples" in the shell commands, see ifconfig function.

@kbumsik
Copy link
Contributor Author

kbumsik commented Oct 19, 2018

I've just tested again this PR and it's still working as before. Only the first ping timeout and the long ipv6 address is not set, but I think this is not related to this PR but rather something missing in netdev_eth.

That's great! Then it is very close to removing the "WIP" tag :)

This number correspond simply to the thread pid the device is attached to. This is what is used by ifconfig

Thanks for the advice. I had a quick look and it seems possible to implement.

But there is still one question not solved by changing the shell commands: What if an application doesn't want to use the shell commands and still want to use auto_init? (I'm not sure if it is a common practice for RIOT though.) In that case how to provide an interface that allows the application to retrieve the device pointer?

@miri64
Copy link
Member

miri64 commented Nov 20, 2018

But there is still one question not solved by changing the shell commands: What if an application doesn't want to use the shell commands and still want to use auto_init? (I'm not sure if it is a common practice for RIOT though.) In that case how to provide an interface that allows the application to retrieve the device pointer?

The shell_commands module and the auto_init module are independent from each other (or at least they should be). The device pointer is contained in the network interface information, which can be retrieved via gnrc_netif_iter(). Likewise can the interface's PID be accessed there. The latter should be used to interact with the interface (and in turn the device) from the stack and application level using gnrc_netapi.

Sorry for the late reply. I hope I could answer your question anyway.

@aabadie aabadie added this to the Release 2019.01 milestone Dec 3, 2018
@miri64
Copy link
Member

miri64 commented Feb 26, 2019

Ping @kbumsik?

@miri64
Copy link
Member

miri64 commented Aug 5, 2019

No reply for nearly half a year. I'm closing this as archived

@miri64 miri64 closed this Aug 5, 2019
@miri64 miri64 added the State: archived State: The PR has been archived for possible future re-adaptation label Aug 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: network Area: Networking State: archived State: The PR has been archived for possible future re-adaptation Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants