Skip to content

Commit 3a2a0c9

Browse files
committed
Implementation of unified EMAC driver for Renesas mbed boards
Implementation of unified EMAC driver for Renesas mbed boards Based on the driver so far, Renesas implemented the emac driver for GR-PEACH and VK-RZ/A1H. The mainly changes is below. - Add the connection part with LWIP according to the unified emac specification. - Add three new multicast functions(add, remove, set_all). The Greentea test netsocket and emac test passed.
1 parent 942209e commit 3a2a0c9

File tree

5 files changed

+471
-2
lines changed

5 files changed

+471
-2
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#include "cmsis_os.h"
2+
#include "netsocket/nsapi_types.h"
3+
#include "mbed_shared_queues.h"
4+
#include "ethernet_api.h"
5+
#include "ethernetext_api.h"
6+
#include "rza1_emac.h"
7+
8+
#define RZ_A1_ETH_IF_NAME "en"
9+
10+
// Weak so a module can override
11+
MBED_WEAK EMAC &EMAC::get_default_instance() {
12+
return RZ_A1_EMAC::get_instance();
13+
}
14+
15+
RZ_A1_EMAC &RZ_A1_EMAC::get_instance() {
16+
static RZ_A1_EMAC emac;
17+
return emac;
18+
}
19+
20+
RZ_A1_EMAC::RZ_A1_EMAC() : hwaddr(), hwaddr_set(false), power_on(false), connect_sts(false),
21+
link_mode_last(NEGO_FAIL), recvThread(osPriorityNormal, 896)
22+
{
23+
}
24+
25+
uint32_t RZ_A1_EMAC::get_mtu_size() const
26+
{
27+
return 1500;
28+
}
29+
30+
uint32_t RZ_A1_EMAC::get_align_preference() const
31+
{
32+
return 0;
33+
}
34+
35+
void RZ_A1_EMAC::get_ifname(char *name, uint8_t size) const
36+
{
37+
memcpy(name, RZ_A1_ETH_IF_NAME, (size < sizeof(RZ_A1_ETH_IF_NAME)) ? size : sizeof(RZ_A1_ETH_IF_NAME));
38+
}
39+
40+
uint8_t RZ_A1_EMAC::get_hwaddr_size() const
41+
{
42+
return 6;
43+
}
44+
45+
bool RZ_A1_EMAC::get_hwaddr(uint8_t *addr) const
46+
{
47+
return false;
48+
}
49+
50+
void RZ_A1_EMAC::set_hwaddr(const uint8_t *addr)
51+
{
52+
memcpy(hwaddr, addr, sizeof(hwaddr));
53+
hwaddr_set = true;
54+
55+
/* Reconnect */
56+
if (power_on != false) {
57+
ethernet_cfg_t ethcfg;
58+
ethcfg.int_priority = 6;
59+
ethcfg.recv_cb = &_recv_callback;
60+
ethcfg.ether_mac = NULL;
61+
ethcfg.ether_mac = (char *)hwaddr;
62+
ethernetext_init(&ethcfg);
63+
}
64+
}
65+
66+
bool RZ_A1_EMAC::link_out(emac_mem_buf_t *buf)
67+
{
68+
emac_mem_buf_t *copy_buf = buf;
69+
uint32_t retry_cnt;
70+
bool result = false;
71+
int write_size;
72+
int total_write_size = 0;
73+
74+
while ((copy_buf != NULL) && (memory_manager->get_ptr(copy_buf) != NULL) && (memory_manager->get_len(copy_buf) != 0)) {
75+
for (retry_cnt = 0; retry_cnt < 100; retry_cnt++) {
76+
write_size = ethernet_write((char *)memory_manager->get_ptr(copy_buf), memory_manager->get_len(copy_buf));
77+
if (write_size != 0) {
78+
total_write_size += write_size;
79+
break;
80+
}
81+
osDelay(1);
82+
}
83+
copy_buf = memory_manager->get_next(copy_buf);
84+
}
85+
memory_manager->free(buf);
86+
87+
if (total_write_size > 0) {
88+
if (ethernet_send() == 1) {
89+
result = true;
90+
}
91+
}
92+
93+
return result;
94+
}
95+
96+
bool RZ_A1_EMAC::power_up()
97+
{
98+
if (power_on != false) {
99+
return true;
100+
}
101+
102+
ethernet_cfg_t ethcfg;
103+
ethcfg.int_priority = 6;
104+
ethcfg.recv_cb = &_recv_callback;
105+
ethcfg.ether_mac = NULL;
106+
if (hwaddr_set) {
107+
ethcfg.ether_mac = (char *)hwaddr;
108+
}
109+
ethernetext_init(&ethcfg);
110+
111+
/* task */
112+
recvThread.start(mbed::callback(this, &RZ_A1_EMAC::recv_task));
113+
phy_task_handle = mbed::mbed_event_queue()->call_every(200, mbed::callback(this, &RZ_A1_EMAC::phy_task));
114+
115+
power_on = true;
116+
return true;
117+
}
118+
119+
void RZ_A1_EMAC::power_down()
120+
{
121+
power_on = false;
122+
}
123+
124+
void RZ_A1_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
125+
{
126+
emac_link_input_cb = input_cb;
127+
}
128+
129+
void RZ_A1_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
130+
{
131+
emac_link_state_cb = state_cb;
132+
}
133+
134+
void RZ_A1_EMAC::add_multicast_group(const uint8_t *addr)
135+
{
136+
ethernetext_add_multicast_group(addr);
137+
}
138+
139+
void RZ_A1_EMAC::remove_multicast_group(const uint8_t *addr)
140+
{
141+
ethernetext_remove_multicast_group(addr);
142+
}
143+
144+
void RZ_A1_EMAC::set_all_multicast(bool all)
145+
{
146+
ethernetext_set_all_multicast(all);
147+
}
148+
149+
void RZ_A1_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
150+
{
151+
memory_manager = &mem_mngr;
152+
}
153+
154+
155+
void RZ_A1_EMAC::_recv_callback(void) {
156+
get_instance().recv_callback();
157+
}
158+
159+
void RZ_A1_EMAC::recv_callback(void) {
160+
recvThread.signal_set(1);
161+
}
162+
163+
void RZ_A1_EMAC::recv_task(void) {
164+
uint16_t recv_size;
165+
emac_mem_buf_t *buf;
166+
int cnt;
167+
168+
while (1) {
169+
rtos::Thread::signal_wait(1);
170+
for (cnt = 0; cnt < 16; cnt++) {
171+
recv_size = ethernet_receive();
172+
if (recv_size == 0) {
173+
break;
174+
}
175+
buf = memory_manager->alloc_heap(recv_size, 0);
176+
if (buf != NULL) {
177+
(void)ethernet_read((char *)memory_manager->get_ptr(buf), memory_manager->get_len(buf));
178+
emac_link_input_cb(buf);
179+
}
180+
}
181+
}
182+
}
183+
184+
void RZ_A1_EMAC::phy_task(void)
185+
{
186+
if (ethernet_link() == 1) {
187+
int link_mode = ethernetext_chk_link_mode();
188+
if (link_mode != link_mode_last) {
189+
if (connect_sts != false) {
190+
emac_link_state_cb(false);
191+
}
192+
if (link_mode != NEGO_FAIL) {
193+
ethernetext_set_link_mode(link_mode);
194+
emac_link_state_cb(true);
195+
connect_sts = true;
196+
}
197+
link_mode_last = link_mode;
198+
}
199+
} else {
200+
if (connect_sts != false) {
201+
emac_link_state_cb(false);
202+
link_mode_last = NEGO_FAIL;
203+
connect_sts = false;
204+
}
205+
}
206+
}
207+
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef RZ_A1_EMAC_H
18+
#define RZ_A1_EMAC_H
19+
20+
#include "EMAC.h"
21+
#include "rtos/Thread.h"
22+
23+
class RZ_A1_EMAC : public EMAC {
24+
public:
25+
RZ_A1_EMAC();
26+
27+
static RZ_A1_EMAC &get_instance();
28+
29+
/**
30+
* Return maximum transmission unit
31+
*
32+
* @return MTU in bytes
33+
*/
34+
virtual uint32_t get_mtu_size() const;
35+
36+
/**
37+
* Gets memory buffer alignment preference
38+
*
39+
* Gets preferred memory buffer alignment of the Emac device. IP stack may or may not
40+
* align link out memory buffer chains using the alignment.
41+
*
42+
* @return Memory alignment requirement in bytes
43+
*/
44+
virtual uint32_t get_align_preference() const;
45+
46+
/**
47+
* Return interface name
48+
*
49+
* @param name Pointer to where the name should be written
50+
* @param size Maximum number of character to copy
51+
*/
52+
virtual void get_ifname(char *name, uint8_t size) const;
53+
54+
/**
55+
* Returns size of the underlying interface HW address size.
56+
*
57+
* @return HW address size in bytes
58+
*/
59+
virtual uint8_t get_hwaddr_size() const;
60+
61+
/**
62+
* Return interface-supplied HW address
63+
*
64+
* Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size
65+
*
66+
* HW address need not be provided if this interface does not have its own HW
67+
* address configuration; stack will choose address from central system
68+
* configuration if the function returns false and does not write to addr.
69+
*
70+
* @param addr HW address for underlying interface
71+
* @return true if HW address is available
72+
*/
73+
virtual bool get_hwaddr(uint8_t *addr) const;
74+
75+
/**
76+
* Set HW address for interface
77+
*
78+
* Provided address has to be of correct size, see @a get_hwaddr_size
79+
*
80+
* Called to set the MAC address to actually use - if @a get_hwaddr is provided
81+
* the stack would normally use that, but it could be overridden, eg for test
82+
* purposes.
83+
*
84+
* @param addr Address to be set
85+
*/
86+
virtual void set_hwaddr(const uint8_t *addr);
87+
88+
/**
89+
* Sends the packet over the link
90+
*
91+
* That can not be called from an interrupt context.
92+
*
93+
* @param buf Packet to be send
94+
* @return True if the packet was send successfully, False otherwise
95+
*/
96+
virtual bool link_out(emac_mem_buf_t *buf);
97+
98+
/**
99+
* Initializes the HW
100+
*
101+
* @return True on success, False in case of an error.
102+
*/
103+
virtual bool power_up();
104+
105+
/**
106+
* Deinitializes the HW
107+
*
108+
*/
109+
virtual void power_down();
110+
111+
/**
112+
* Sets a callback that needs to be called for packets received for that interface
113+
*
114+
* @param input_cb Function to be register as a callback
115+
*/
116+
virtual void set_link_input_cb(emac_link_input_cb_t input_cb);
117+
118+
/**
119+
* Sets a callback that needs to be called on link status changes for given interface
120+
*
121+
* @param state_cb Function to be register as a callback
122+
*/
123+
virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb);
124+
125+
/** Add device to a multicast group
126+
*
127+
* @param address A multicast group hardware address
128+
*/
129+
virtual void add_multicast_group(const uint8_t *address);
130+
131+
/** Remove device from a multicast group
132+
*
133+
* @param address A multicast group hardware address
134+
*/
135+
virtual void remove_multicast_group(const uint8_t *address);
136+
137+
/** Request reception of all multicast packets
138+
*
139+
* @param all True to receive all multicasts
140+
* False to receive only multicasts addressed to specified groups
141+
*/
142+
virtual void set_all_multicast(bool all);
143+
144+
/** Sets memory manager that is used to handle memory buffers
145+
*
146+
* @param mem_mngr Pointer to memory manager
147+
*/
148+
virtual void set_memory_manager(EMACMemoryManager &mem_mngr);
149+
150+
private:
151+
EMACMemoryManager *memory_manager; /**< Memory manager */
152+
uint8_t hwaddr[6];
153+
bool hwaddr_set;
154+
bool power_on;
155+
emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */
156+
emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */
157+
bool connect_sts;
158+
int link_mode_last;
159+
rtos::Thread recvThread;
160+
int phy_task_handle; /**< Handle for phy task event */
161+
162+
static void _recv_callback(void);
163+
void recv_callback(void);
164+
void recv_task(void);
165+
void phy_task(void);
166+
167+
};
168+
169+
#endif /* RZ_A1_EMAC_H */

0 commit comments

Comments
 (0)