Merge remote-tracking branch 'origin/main' into main
This commit is contained in:
commit
eb93317aef
|
@ -14,6 +14,33 @@ hold/accumulate various objects.
|
|||
Classes
|
||||
-------
|
||||
|
||||
.. function:: deque(iterable, maxlen[, flags])
|
||||
|
||||
Deques (double-ended queues) are a list-like container that support O(1)
|
||||
appends and pops from either side of the deque. New deques are created
|
||||
using the following arguments:
|
||||
|
||||
- *iterable* must be the empty tuple, and the new deque is created empty.
|
||||
|
||||
- *maxlen* must be specified and the deque will be bounded to this
|
||||
maximum length. Once the deque is full, any new items added will
|
||||
discard items from the opposite end.
|
||||
|
||||
- The optional *flags* can be 1 to check for overflow when adding items.
|
||||
|
||||
As well as supporting `bool` and `len`, deque objects have the following
|
||||
methods:
|
||||
|
||||
.. method:: deque.append(x)
|
||||
|
||||
Add *x* to the right side of the deque.
|
||||
Raises IndexError if overflow checking is enabled and there is no more room left.
|
||||
|
||||
.. method:: deque.popleft()
|
||||
|
||||
Remove and return an item from the left side of the deque.
|
||||
Raises IndexError if no items are present.
|
||||
|
||||
.. function:: namedtuple(name, fields)
|
||||
|
||||
This is factory function to create a new namedtuple type with a specific
|
||||
|
|
|
@ -39,8 +39,6 @@ with the ``u`` prefix dropped:
|
|||
sys.rst
|
||||
uctypes.rst
|
||||
uselect.rst
|
||||
usocket.rst
|
||||
ussl.rst
|
||||
uzlib.rst
|
||||
|
||||
Omitted functions in the ``string`` library
|
||||
|
|
|
@ -81,6 +81,9 @@ Functions
|
|||
in a row and the lock-depth will increase, and then `heap_unlock()` must be
|
||||
called the same number of times to make the heap available again.
|
||||
|
||||
If the REPL becomes active with the heap locked then it will be forcefully
|
||||
unlocked.
|
||||
|
||||
.. function:: kbd_intr(chr)
|
||||
|
||||
Set the character that will raise a `KeyboardInterrupt` exception. By
|
||||
|
|
|
@ -10,41 +10,101 @@ This module implements regular expression operations. Regular expression
|
|||
syntax supported is a subset of CPython ``re`` module (and actually is
|
||||
a subset of POSIX extended regular expressions).
|
||||
|
||||
Supported operators are:
|
||||
Supported operators and special sequences are:
|
||||
|
||||
``'.'``
|
||||
``.``
|
||||
Match any character.
|
||||
|
||||
``'[...]'``
|
||||
``[...]``
|
||||
Match set of characters. Individual characters and ranges are supported,
|
||||
including negated sets (e.g. ``[^a-c]``).
|
||||
|
||||
``'^'``
|
||||
``^``
|
||||
Match the start of the string.
|
||||
|
||||
``'$'``
|
||||
``$``
|
||||
Match the end of the string.
|
||||
|
||||
``'?'``
|
||||
``?``
|
||||
Match zero or one of the previous sub-pattern.
|
||||
|
||||
``'*'``
|
||||
``*``
|
||||
Match zero or more of the previous sub-pattern.
|
||||
|
||||
``'+'``
|
||||
``+``
|
||||
Match one or more of the previous sub-pattern.
|
||||
|
||||
``'??'``
|
||||
``??``
|
||||
Non-greedy version of ``?``, match zero or one, with the preference
|
||||
for zero.
|
||||
|
||||
``'*?'``
|
||||
``*?``
|
||||
Non-greedy version of ``*``, match zero or more, with the preference
|
||||
for the shortest match.
|
||||
|
||||
``'+?'``
|
||||
``+?``
|
||||
Non-greedy version of ``+``, match one or more, with the preference
|
||||
for the shortest match.
|
||||
|
||||
``'|'``
|
||||
``|``
|
||||
Match either the left-hand side or the right-hand side sub-patterns of
|
||||
this operator.
|
||||
|
||||
``'(...)'``
|
||||
``(...)``
|
||||
Grouping. Each group is capturing (a substring it captures can be accessed
|
||||
with `match.group()` method).
|
||||
|
||||
**NOT SUPPORTED**: Counted repetitions (``{m,n}``), more advanced assertions
|
||||
(``\b``, ``\B``), named groups (``(?P<name>...)``), non-capturing groups
|
||||
(``(?:...)``), etc.
|
||||
``\d``
|
||||
Matches digit. Equivalent to ``[0-9]``.
|
||||
|
||||
``\D``
|
||||
Matches non-digit. Equivalent to ``[^0-9]``.
|
||||
|
||||
``\s``
|
||||
Matches whitespace. Equivalent to ``[ \t-\r]``.
|
||||
|
||||
``\S``
|
||||
Matches non-whitespace. Equivalent to ``[^ \t-\r]``.
|
||||
|
||||
``\w``
|
||||
Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``.
|
||||
|
||||
``\W``
|
||||
Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``.
|
||||
|
||||
``\``
|
||||
Escape character. Any other character following the backslash, except
|
||||
for those listed above, is taken literally. For example, ``\*`` is
|
||||
equivalent to literal ``*`` (not treated as the ``*`` operator).
|
||||
Note that ``\r``, ``\n``, etc. are not handled specially, and will be
|
||||
equivalent to literal letters ``r``, ``n``, etc. Due to this, it's
|
||||
not recommended to use raw Python strings (``r""``) for regular
|
||||
expressions. For example, ``r"\r\n"`` when used as the regular
|
||||
expression is equivalent to ``"rn"``. To match CR character followed
|
||||
by LF, use ``"\r\n"``.
|
||||
|
||||
**NOT SUPPORTED**:
|
||||
|
||||
* counted repetitions (``{m,n}``)
|
||||
* named groups (``(?P<name>...)``)
|
||||
* non-capturing groups (``(?:...)``)
|
||||
* more advanced assertions (``\b``, ``\B``)
|
||||
* special character escapes like ``\r``, ``\n`` - use Python's own escaping
|
||||
instead
|
||||
* etc.
|
||||
|
||||
Example::
|
||||
|
||||
import ure
|
||||
|
||||
# As ure doesn't support escapes itself, use of r"" strings is not
|
||||
# recommended.
|
||||
regex = ure.compile("[\r\n]")
|
||||
|
||||
regex.split("line1\rline2\nline3\r\n")
|
||||
|
||||
# Result:
|
||||
# ['line1', 'line2', 'line3', '', '']
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
@ -64,6 +124,22 @@ Functions
|
|||
string for first position which matches regex (which still may be
|
||||
0 if regex is anchored).
|
||||
|
||||
.. function:: sub(regex_str, replace, string, count=0, flags=0)
|
||||
|
||||
Compile *regex_str* and search for it in *string*, replacing all matches
|
||||
with *replace*, and returning the new string.
|
||||
|
||||
*replace* can be a string or a function. If it is a string then escape
|
||||
sequences of the form ``\<number>`` and ``\g<number>`` can be used to
|
||||
expand to the corresponding group (or an empty string for unmatched groups).
|
||||
If *replace* is a function then it must take a single argument (the match)
|
||||
and should return a replacement string.
|
||||
|
||||
If *count* is specified and non-zero then substitution will stop after
|
||||
this many substitutions are made. The *flags* argument is ignored.
|
||||
|
||||
Note: availability of this function depends on MicroPython port.
|
||||
|
||||
.. data:: DEBUG
|
||||
|
||||
Flag value, display debug information about compiled expression.
|
||||
|
@ -79,8 +155,10 @@ Compiled regular expression. Instances of this class are created using
|
|||
|
||||
.. method:: regex.match(string)
|
||||
regex.search(string)
|
||||
regex.sub(replace, string, count=0, flags=0)
|
||||
|
||||
Similar to the module-level functions :meth:`match` and :meth:`search`.
|
||||
Similar to the module-level functions :meth:`match`, :meth:`search`
|
||||
and :meth:`sub`.
|
||||
Using methods is (much) more efficient if the same regex is applied to
|
||||
multiple strings.
|
||||
|
||||
|
@ -93,9 +171,31 @@ Compiled regular expression. Instances of this class are created using
|
|||
Match objects
|
||||
-------------
|
||||
|
||||
Match objects as returned by `match()` and `search()` methods.
|
||||
Match objects as returned by `match()` and `search()` methods, and passed
|
||||
to the replacement function in `sub()`.
|
||||
|
||||
.. method:: match.group([index])
|
||||
|
||||
Return matching (sub)string. *index* is 0 for entire match,
|
||||
1 and above for each capturing group. Only numeric groups are supported.
|
||||
|
||||
.. method:: match.groups()
|
||||
|
||||
Return a tuple containing all the substrings of the groups of the match.
|
||||
|
||||
Note: availability of this method depends on MicroPython port.
|
||||
|
||||
.. method:: match.start([index])
|
||||
match.end([index])
|
||||
|
||||
Return the index in the original string of the start or end of the
|
||||
substring group that was matched. *index* defaults to the entire
|
||||
group, otherwise it will select a group.
|
||||
|
||||
Note: availability of these methods depends on MicroPython port.
|
||||
|
||||
.. method:: match.span([index])
|
||||
|
||||
Returns the 2-tuple ``(match.start(index), match.end(index))``.
|
||||
|
||||
Note: availability of this method depends on MicroPython port.
|
||||
|
|
|
@ -13,19 +13,91 @@ module is to define data structure layout with about the same power as the
|
|||
C language allows, and then access it using familiar dot-syntax to reference
|
||||
sub-fields.
|
||||
|
||||
.. warning::
|
||||
|
||||
``uctypes`` module allows access to arbitrary memory addresses of the
|
||||
machine (including I/O and control registers). Uncareful usage of it
|
||||
may lead to crashes, data loss, and even hardware malfunction.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`struct`
|
||||
Standard Python way to access binary data structures (doesn't scale
|
||||
well to large and complex structures).
|
||||
|
||||
Usage examples::
|
||||
|
||||
import uctypes
|
||||
|
||||
# Example 1: Subset of ELF file header
|
||||
# https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
|
||||
ELF_HEADER = {
|
||||
"EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8),
|
||||
"EI_DATA": 0x5 | uctypes.UINT8,
|
||||
"e_machine": 0x12 | uctypes.UINT16,
|
||||
}
|
||||
|
||||
# "f" is an ELF file opened in binary mode
|
||||
buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN))
|
||||
header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN)
|
||||
assert header.EI_MAG == b"\x7fELF"
|
||||
assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN."
|
||||
print("machine:", hex(header.e_machine))
|
||||
|
||||
|
||||
# Example 2: In-memory data structure, with pointers
|
||||
COORD = {
|
||||
"x": 0 | uctypes.FLOAT32,
|
||||
"y": 4 | uctypes.FLOAT32,
|
||||
}
|
||||
|
||||
STRUCT1 = {
|
||||
"data1": 0 | uctypes.UINT8,
|
||||
"data2": 4 | uctypes.UINT32,
|
||||
"ptr": (8 | uctypes.PTR, COORD),
|
||||
}
|
||||
|
||||
# Suppose you have address of a structure of type STRUCT1 in "addr"
|
||||
# uctypes.NATIVE is optional (used by default)
|
||||
struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE)
|
||||
print("x:", struct1.ptr[0].x)
|
||||
|
||||
|
||||
# Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block
|
||||
WWDG_LAYOUT = {
|
||||
"WWDG_CR": (0, {
|
||||
# BFUINT32 here means size of the WWDG_CR register
|
||||
"WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
}),
|
||||
"WWDG_CFR": (4, {
|
||||
"EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
}),
|
||||
}
|
||||
|
||||
WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT)
|
||||
|
||||
WWDG.WWDG_CFR.WDGTB = 0b10
|
||||
WWDG.WWDG_CR.WDGA = 1
|
||||
print("Current counter:", WWDG.WWDG_CR.T)
|
||||
|
||||
Defining structure layout
|
||||
-------------------------
|
||||
|
||||
Structure layout is defined by a "descriptor" - a Python dictionary which
|
||||
encodes field names as keys and other properties required to access them as
|
||||
associated values. Currently, uctypes requires explicit specification of
|
||||
offsets for each field. Offset are given in bytes from a structure start.
|
||||
associated values::
|
||||
|
||||
{
|
||||
"field1": <properties>,
|
||||
"field2": <properties>,
|
||||
...
|
||||
}
|
||||
|
||||
Currently, ``uctypes`` requires explicit specification of offsets for each
|
||||
field. Offset are given in bytes from the structure start.
|
||||
|
||||
Following are encoding examples for various field types:
|
||||
|
||||
|
@ -33,7 +105,7 @@ Following are encoding examples for various field types:
|
|||
|
||||
"field_name": offset | uctypes.UINT32
|
||||
|
||||
in other words, value is scalar type identifier ORed with field offset
|
||||
in other words, the value is a scalar type identifier ORed with a field offset
|
||||
(in bytes) from the start of the structure.
|
||||
|
||||
* Recursive structures::
|
||||
|
@ -43,9 +115,11 @@ Following are encoding examples for various field types:
|
|||
"b1": 1 | uctypes.UINT8,
|
||||
})
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is offset, and second is
|
||||
i.e. value is a 2-tuple, first element of which is an offset, and second is
|
||||
a structure descriptor dictionary (note: offsets in recursive descriptors
|
||||
are relative to the structure it defines).
|
||||
are relative to the structure it defines). Of course, recursive structures
|
||||
can be specified not just by a literal dictionary, but by referring to a
|
||||
structure descriptor dictionary (defined earlier) by name.
|
||||
|
||||
* Arrays of primitive types::
|
||||
|
||||
|
@ -53,42 +127,42 @@ Following are encoding examples for various field types:
|
|||
|
||||
i.e. value is a 2-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, and second is scalar element type ORed number of elements
|
||||
in array.
|
||||
in the array.
|
||||
|
||||
* Arrays of aggregate types::
|
||||
|
||||
"arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 3-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, second is a number of elements in array, and third is
|
||||
descriptor of element type.
|
||||
with offset, second is a number of elements in the array, and third is
|
||||
a descriptor of element type.
|
||||
|
||||
* Pointer to a primitive type::
|
||||
|
||||
"ptr": (offset | uctypes.PTR, uctypes.UINT8),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, and second is scalar element type.
|
||||
with offset, and second is a scalar element type.
|
||||
|
||||
* Pointer to an aggregate type::
|
||||
|
||||
"ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, second is descriptor of type pointed to.
|
||||
with offset, second is a descriptor of type pointed to.
|
||||
|
||||
* Bitfields::
|
||||
|
||||
"bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN,
|
||||
|
||||
i.e. value is type of scalar value containing given bitfield (typenames are
|
||||
similar to scalar types, but prefixes with "BF"), ORed with offset for
|
||||
i.e. value is a type of scalar value containing given bitfield (typenames are
|
||||
similar to scalar types, but prefixes with ``BF``), ORed with offset for
|
||||
scalar value containing the bitfield, and further ORed with values for
|
||||
bit offset and bit length of the bitfield within scalar value, shifted by
|
||||
BF_POS and BF_LEN positions, respectively. Bitfield position is counted
|
||||
from the least significant bit, and is the number of right-most bit of a
|
||||
field (in other words, it's a number of bits a scalar needs to be shifted
|
||||
right to extract the bitfield).
|
||||
bit position and bit length of the bitfield within the scalar value, shifted by
|
||||
BF_POS and BF_LEN bits, respectively. A bitfield position is counted
|
||||
from the least significant bit of the scalar (having position of 0), and
|
||||
is the number of right-most bit of a field (in other words, it's a number
|
||||
of bits a scalar needs to be shifted right to extract the bitfield).
|
||||
|
||||
In the example above, first a UINT16 value will be extracted at offset 0
|
||||
(this detail may be important when accessing hardware registers, where
|
||||
|
@ -128,10 +202,11 @@ Module contents
|
|||
Layout type for a native structure - with data endianness and alignment
|
||||
conforming to the ABI of the system on which MicroPython runs.
|
||||
|
||||
.. function:: sizeof(struct)
|
||||
.. function:: sizeof(struct, layout_type=NATIVE)
|
||||
|
||||
Return size of data structure in bytes. Argument can be either structure
|
||||
class or specific instantiated structure object (or its aggregate field).
|
||||
Return size of data structure in bytes. The *struct* argument can be
|
||||
either a structure class or a specific instantiated structure object
|
||||
(or its aggregate field).
|
||||
|
||||
.. function:: addressof(obj)
|
||||
|
||||
|
@ -153,6 +228,35 @@ Module contents
|
|||
so it can be both written too, and you will access current value
|
||||
at the given memory address.
|
||||
|
||||
.. data:: UINT8
|
||||
INT8
|
||||
UINT16
|
||||
INT16
|
||||
UINT32
|
||||
INT32
|
||||
UINT64
|
||||
INT64
|
||||
|
||||
Integer types for structure descriptors. Constants for 8, 16, 32,
|
||||
and 64 bit types are provided, both signed and unsigned.
|
||||
|
||||
.. data:: FLOAT32
|
||||
FLOAT64
|
||||
|
||||
Floating-point types for structure descriptors.
|
||||
|
||||
.. data:: VOID
|
||||
|
||||
``VOID`` is an alias for ``UINT8``, and is provided to conviniently define
|
||||
C's void pointers: ``(uctypes.PTR, uctypes.VOID)``.
|
||||
|
||||
.. data:: PTR
|
||||
ARRAY
|
||||
|
||||
Type constants for pointers and arrays. Note that there is no explicit
|
||||
constant for structures, it's implicit: an aggregate type without ``PTR``
|
||||
or ``ARRAY`` flags is a structure.
|
||||
|
||||
Structure descriptors and instantiating structure objects
|
||||
---------------------------------------------------------
|
||||
|
||||
|
@ -165,7 +269,7 @@ following sources:
|
|||
system. Lookup these addresses in datasheet for a particular MCU/SoC.
|
||||
* As a return value from a call to some FFI (Foreign Function Interface)
|
||||
function.
|
||||
* From uctypes.addressof(), when you want to pass arguments to an FFI
|
||||
* From `uctypes.addressof()`, when you want to pass arguments to an FFI
|
||||
function, or alternatively, to access some data for I/O (for example,
|
||||
data read from a file or network socket).
|
||||
|
||||
|
@ -183,30 +287,41 @@ the standard subscript operator ``[]`` - both read and assigned to.
|
|||
|
||||
If a field is a pointer, it can be dereferenced using ``[0]`` syntax
|
||||
(corresponding to C ``*`` operator, though ``[0]`` works in C too).
|
||||
Subscripting a pointer with other integer values but 0 are supported too,
|
||||
Subscripting a pointer with other integer values but 0 are also supported,
|
||||
with the same semantics as in C.
|
||||
|
||||
Summing up, accessing structure fields generally follows C syntax,
|
||||
Summing up, accessing structure fields generally follows the C syntax,
|
||||
except for pointer dereference, when you need to use ``[0]`` operator
|
||||
instead of ``*``.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Accessing non-scalar fields leads to allocation of intermediate objects
|
||||
1. Accessing non-scalar fields leads to allocation of intermediate objects
|
||||
to represent them. This means that special care should be taken to
|
||||
layout a structure which needs to be accessed when memory allocation
|
||||
is disabled (e.g. from an interrupt). The recommendations are:
|
||||
|
||||
* Avoid nested structures. For example, instead of
|
||||
* Avoid accessing nested structures. For example, instead of
|
||||
``mcu_registers.peripheral_a.register1``, define separate layout
|
||||
descriptors for each peripheral, to be accessed as
|
||||
``peripheral_a.register1``.
|
||||
* Avoid other non-scalar data, like array. For example, instead of
|
||||
``peripheral_a.register[0]`` use ``peripheral_a.register0``.
|
||||
``peripheral_a.register1``. Or just cache a particular peripheral:
|
||||
``peripheral_a = mcu_registers.peripheral_a``. If a register
|
||||
consists of multiple bitfields, you would need to cache references
|
||||
to a particular register: ``reg_a = mcu_registers.peripheral_a.reg_a``.
|
||||
* Avoid other non-scalar data, like arrays. For example, instead of
|
||||
``peripheral_a.register[0]`` use ``peripheral_a.register0``. Again,
|
||||
an alternative is to cache intermediate values, e.g.
|
||||
``register0 = peripheral_a.register[0]``.
|
||||
|
||||
Note that these recommendations will lead to decreased readability
|
||||
and conciseness of layouts, so they should be used only if the need
|
||||
to access structure fields without allocation is anticipated (it's
|
||||
even possible to define 2 parallel layouts - one for normal usage,
|
||||
and a restricted one to use when memory allocation is prohibited).
|
||||
2. Range of offsets supported by the ``uctypes`` module is limited.
|
||||
The exact range supported is considered an implementation detail,
|
||||
and the general suggestion is to split structure definitions to
|
||||
cover from a few kilobytes to a few dozen of kilobytes maximum.
|
||||
In most cases, this is a natural situation anyway, e.g. it doesn't make
|
||||
sense to define all registers of an MCU (spread over 32-bit address
|
||||
space) in one structure, but rather a peripheral block by peripheral
|
||||
block. In some extreme cases, you may need to split a structure in
|
||||
several parts artificially (e.g. if accessing native data structure
|
||||
with multi-megabyte array in the middle, though that would be a very
|
||||
synthetic case).
|
||||
|
|
|
@ -47,13 +47,18 @@ Methods
|
|||
|
||||
*eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``.
|
||||
|
||||
It is OK to call this function multiple times for the same *obj*.
|
||||
Successive calls will update *obj*'s eventmask to the value of
|
||||
*eventmask* (i.e. will behave as `modify()`).
|
||||
|
||||
.. method:: poll.unregister(obj)
|
||||
|
||||
Unregister *obj* from polling.
|
||||
|
||||
.. method:: poll.modify(obj, eventmask)
|
||||
|
||||
Modify the *eventmask* for *obj*.
|
||||
Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError`
|
||||
is raised with error of ENOENT.
|
||||
|
||||
.. method:: poll.poll(timeout=-1)
|
||||
|
||||
|
|
|
@ -1,336 +0,0 @@
|
|||
*******************************
|
||||
:mod:`usocket` -- socket module
|
||||
*******************************
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: usocket
|
||||
:synopsis: socket module
|
||||
|
||||
|see_cpython_module| :mod:`cpython:socket`.
|
||||
|
||||
This module provides access to the BSD socket interface.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
For efficiency and consistency, socket objects in MicroPython implement a ``stream``
|
||||
(file-like) interface directly. In CPython, you need to convert a socket to
|
||||
a file-like object using `makefile()` method. This method is still supported
|
||||
by MicroPython (but is a no-op), so where compatibility with CPython matters,
|
||||
be sure to use it.
|
||||
|
||||
Socket address format(s)
|
||||
------------------------
|
||||
|
||||
The native socket address format of the ``usocket`` module is an opaque data type
|
||||
returned by `getaddrinfo` function, which must be used to resolve textual address
|
||||
(including numeric addresses)::
|
||||
|
||||
sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1]
|
||||
# You must use getaddrinfo() even for numeric addresses
|
||||
sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1]
|
||||
# Now you can use that address
|
||||
sock.connect(addr)
|
||||
|
||||
Using `getaddrinfo` is the most efficient (both in terms of memory and processing
|
||||
power) and portable way to work with addresses.
|
||||
|
||||
However, ``socket`` module (note the difference with native MicroPython
|
||||
``usocket`` module described here) provides CPython-compatible way to specify
|
||||
addresses using tuples, as described below.
|
||||
|
||||
Summing up:
|
||||
|
||||
* Always use `getaddrinfo` when writing portable applications.
|
||||
* Tuple addresses described below can be used as a shortcut for
|
||||
quick hacks and interactive use, if your port supports them.
|
||||
|
||||
Tuple address format for ``socket`` module:
|
||||
|
||||
* IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with
|
||||
dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and
|
||||
integer port number in the range 1-65535. Note the domain names are not
|
||||
accepted as *ipv4_address*, they should be resolved first using
|
||||
`usocket.getaddrinfo()`.
|
||||
* IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address*
|
||||
is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``,
|
||||
and *port* is an integer port number in the range 1-65535. *flowinfo*
|
||||
must be 0. *scopeid* is the interface scope identifier for link-local
|
||||
addresses. Note the domain names are not accepted as *ipv6_address*,
|
||||
they should be resolved first using `usocket.getaddrinfo()`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
|
||||
|
||||
Create a new socket using the given address family, socket type and
|
||||
protocol number. Note that specifying *proto* in most cases is not
|
||||
required (and not recommended, as some MicroPython ports may omit
|
||||
``IPPROTO_*`` constants). Instead, *type* argument will select needed
|
||||
protocol automatically::
|
||||
|
||||
# Create STREAM TCP socket
|
||||
socket(AF_INET, SOCK_STREAM)
|
||||
# Create DGRAM UDP socket
|
||||
socket(AF_INET, SOCK_DGRAM)
|
||||
|
||||
.. function:: getaddrinfo(host, port)
|
||||
|
||||
Translate the host/port argument into a sequence of 5-tuples that contain all the
|
||||
necessary arguments for creating a socket connected to that service. The list of
|
||||
5-tuples has following structure::
|
||||
|
||||
(family, type, proto, canonname, sockaddr)
|
||||
|
||||
The following example shows how to connect to a given url::
|
||||
|
||||
s = usocket.socket()
|
||||
s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case
|
||||
of error in this function. MicroPython doesn't have ``socket.gaierror``
|
||||
and raises OSError directly. Note that error numbers of `getaddrinfo()`
|
||||
form a separate namespace and may not match error numbers from
|
||||
:py:mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are
|
||||
represented by negative numbers, whereas standard system errors are
|
||||
positive numbers (error numbers are accessible using ``e.args[0]`` property
|
||||
from an exception object). The use of negative values is a provisional
|
||||
detail which may change in the future.
|
||||
|
||||
.. function:: inet_ntop(af, bin_addr)
|
||||
|
||||
Convert a binary network address *bin_addr* of the given address family *af*
|
||||
to a textual representation::
|
||||
|
||||
>>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
|
||||
'127.0.0.1'
|
||||
|
||||
.. function:: inet_pton(af, txt_addr)
|
||||
|
||||
Convert a textual network address *txt_addr* of the given address family *af*
|
||||
to a binary representation::
|
||||
|
||||
>>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
|
||||
b'\x01\x02\x03\x04'
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: AF_INET
|
||||
AF_INET6
|
||||
|
||||
Address family types. Availability depends on a particular ``MicroPython port``.
|
||||
|
||||
.. data:: SOCK_STREAM
|
||||
SOCK_DGRAM
|
||||
|
||||
Socket types.
|
||||
|
||||
.. data:: IPPROTO_UDP
|
||||
IPPROTO_TCP
|
||||
|
||||
IP protocol numbers. Availability depends on a particular ``MicroPython port``.
|
||||
Note that you don't need to specify these in a call to `usocket.socket()`,
|
||||
because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and
|
||||
`SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants
|
||||
is as an argument to `usocket.socket.setsockopt()`.
|
||||
|
||||
.. data:: usocket.SOL_*
|
||||
|
||||
Socket option levels (an argument to `usocket.socket.setsockopt()`). The exact
|
||||
inventory depends on a ``MicroPython port``.
|
||||
|
||||
.. data:: usocket.SO_*
|
||||
|
||||
Socket options (an argument to `usocket.socket.setsockopt()`). The exact
|
||||
inventory depends on a ``MicroPython port``.
|
||||
|
||||
Constants specific to WiPy:
|
||||
|
||||
.. data:: IPPROTO_SEC
|
||||
|
||||
Special protocol value to create SSL-compatible socket.
|
||||
|
||||
class socket
|
||||
============
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: socket.close()
|
||||
|
||||
Mark the socket closed and release all resources. Once that happens, all future operations
|
||||
on the socket object will fail. The remote end will receive EOF indication if
|
||||
supported by protocol.
|
||||
|
||||
Sockets are automatically closed when they are garbage-collected, but it is recommended
|
||||
to `close()` them explicitly as soon you finished working with them.
|
||||
|
||||
.. method:: socket.bind(address)
|
||||
|
||||
Bind the socket to *address*. The socket must not already be bound.
|
||||
|
||||
.. method:: socket.listen([backlog])
|
||||
|
||||
Enable a server to accept connections. If *backlog* is specified, it must be at least 0
|
||||
(if it's lower, it will be set to 0); and specifies the number of unaccepted connections
|
||||
that the system will allow before refusing new connections. If not specified, a default
|
||||
reasonable value is chosen.
|
||||
|
||||
.. method:: socket.accept()
|
||||
|
||||
Accept a connection. The socket must be bound to an address and listening for connections.
|
||||
The return value is a pair (conn, address) where conn is a new socket object usable to send
|
||||
and receive data on the connection, and address is the address bound to the socket on the
|
||||
other end of the connection.
|
||||
|
||||
.. method:: socket.connect(address)
|
||||
|
||||
Connect to a remote socket at *address*.
|
||||
|
||||
.. method:: socket.send(bytes)
|
||||
|
||||
Send data to the socket. The socket must be connected to a remote socket.
|
||||
Returns number of bytes sent, which may be smaller than the length of data
|
||||
("short write").
|
||||
|
||||
.. method:: socket.sendall(bytes)
|
||||
|
||||
Send all data to the socket. The socket must be connected to a remote socket.
|
||||
Unlike `send()`, this method will try to send all of data, by sending data
|
||||
chunk by chunk consecutively.
|
||||
|
||||
The behavior of this method on non-blocking sockets is undefined. Due to this,
|
||||
on MicroPython, it's recommended to use `write()` method instead, which
|
||||
has the same "no short writes" policy for blocking sockets, and will return
|
||||
number of bytes sent on non-blocking sockets.
|
||||
|
||||
.. method:: socket.recv(bufsize)
|
||||
|
||||
Receive data from the socket. The return value is a bytes object representing the data
|
||||
received. The maximum amount of data to be received at once is specified by bufsize.
|
||||
|
||||
.. method:: socket.sendto(bytes, address)
|
||||
|
||||
Send data to the socket. The socket should not be connected to a remote socket, since the
|
||||
destination socket is specified by *address*.
|
||||
|
||||
.. method:: socket.recvfrom(bufsize)
|
||||
|
||||
Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a
|
||||
bytes object representing the data received and *address* is the address of the socket sending
|
||||
the data.
|
||||
|
||||
.. method:: socket.setsockopt(level, optname, value)
|
||||
|
||||
Set the value of the given socket option. The needed symbolic constants are defined in the
|
||||
socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing
|
||||
a buffer.
|
||||
|
||||
.. method:: socket.settimeout(value)
|
||||
|
||||
**Note**: Not every port supports this method, see below.
|
||||
|
||||
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
|
||||
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
|
||||
will raise an `OSError` exception if the timeout period value has elapsed before the operation has
|
||||
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
|
||||
is put in blocking mode.
|
||||
|
||||
Not every ``MicroPython port`` supports this method. A more portable and
|
||||
generic solution is to use `uselect.poll` object. This allows to wait on
|
||||
multiple objects at the same time (and not just on sockets, but on generic
|
||||
``stream`` objects which support polling). Example::
|
||||
|
||||
# Instead of:
|
||||
s.settimeout(1.0) # time in seconds
|
||||
s.read(10) # may timeout
|
||||
|
||||
# Use:
|
||||
poller = uselect.poll()
|
||||
poller.register(s, uselect.POLLIN)
|
||||
res = poller.poll(1000) # time in milliseconds
|
||||
if not res:
|
||||
# s is still not ready for input, i.e. operation timed out
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.timeout`` exception in case of timeout,
|
||||
which is an `OSError` subclass. MicroPython raises an OSError directly
|
||||
instead. If you use ``except OSError:`` to catch the exception,
|
||||
your code will work both in MicroPython and CPython.
|
||||
|
||||
.. method:: socket.setblocking(flag)
|
||||
|
||||
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
|
||||
else to blocking mode.
|
||||
|
||||
This method is a shorthand for certain `settimeout()` calls:
|
||||
|
||||
* ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)``
|
||||
* ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)``
|
||||
|
||||
.. method:: socket.makefile(mode='rb', buffering=0)
|
||||
|
||||
Return a file object associated with the socket. The exact returned type depends on the arguments
|
||||
given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb').
|
||||
CPython's arguments: *encoding*, *errors* and *newline* are not supported.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
As MicroPython doesn't support buffered streams, values of *buffering*
|
||||
parameter is ignored and treated as if it was 0 (unbuffered).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
Closing the file object returned by makefile() WILL close the
|
||||
original socket as well.
|
||||
|
||||
.. method:: socket.read([size])
|
||||
|
||||
Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it
|
||||
reads all data available from the socket until EOF; as such the method will not return until
|
||||
the socket is closed. This function tries to read as much data as
|
||||
requested (no "short reads"). This may be not possible with
|
||||
non-blocking socket though, and then less data will be returned.
|
||||
|
||||
.. method:: socket.readinto(buf[, nbytes])
|
||||
|
||||
Read bytes into the *buf*. If *nbytes* is specified then read at most
|
||||
that many bytes. Otherwise, read at most *len(buf)* bytes. Just as
|
||||
`read()`, this method follows "no short reads" policy.
|
||||
|
||||
Return value: number of bytes read and stored into *buf*.
|
||||
|
||||
.. method:: socket.readline()
|
||||
|
||||
Read a line, ending in a newline character.
|
||||
|
||||
Return value: the line read.
|
||||
|
||||
.. method:: socket.write(buf)
|
||||
|
||||
Write the buffer of bytes to the socket. This function will try to
|
||||
write all data to a socket (no "short writes"). This may be not possible
|
||||
with a non-blocking socket though, and returned value will be less than
|
||||
the length of *buf*.
|
||||
|
||||
Return value: number of bytes written.
|
||||
|
||||
.. exception:: usocket.error
|
||||
|
||||
MicroPython does NOT have this exception.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython used to have a ``socket.error`` exception which is now deprecated,
|
||||
and is an alias of `OSError`. In MicroPython, use `OSError` directly.
|
|
@ -1,50 +0,0 @@
|
|||
:mod:`ussl` -- SSL/TLS module
|
||||
=============================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: ussl
|
||||
:synopsis: TLS/SSL wrapper for socket objects
|
||||
|
||||
|see_cpython_module| :mod:`cpython:ssl`.
|
||||
|
||||
This module provides access to Transport Layer Security (previously and
|
||||
widely known as “Secure Sockets Layer”) encryption and peer authentication
|
||||
facilities for network sockets, both client-side and server-side.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
|
||||
|
||||
Takes a ``stream`` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
|
||||
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
|
||||
an SSL context. Returned object has the usual ``stream`` interface methods like
|
||||
``read()``, ``write()``, etc. In MicroPython, the returned object does not expose
|
||||
socket interface and methods like ``recv()``, ``send()``. In particular, a
|
||||
server-side SSL socket should be created from a normal socket returned from
|
||||
:meth:`~usocket.socket.accept()` on a non-SSL listening server socket.
|
||||
|
||||
Depending on the underlying module implementation in a particular
|
||||
``MicroPython port``, some or all keyword arguments above may be not supported.
|
||||
|
||||
.. warning::
|
||||
|
||||
Some implementations of ``ussl`` module do NOT validate server certificates,
|
||||
which makes an SSL connection established prone to man-in-the-middle attacks.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. data:: ssl.SSLError
|
||||
|
||||
This exception does NOT exist. Instead its base class, OSError, is used.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: ussl.CERT_NONE
|
||||
ussl.CERT_OPTIONAL
|
||||
ussl.CERT_REQUIRED
|
||||
|
||||
Supported values for *cert_reqs* parameter.
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
|
||||
#define MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
|
||||
|
||||
#include "py/mphal.h"
|
||||
|
||||
enum {
|
||||
MP_QSPI_IOCTL_INIT,
|
||||
MP_QSPI_IOCTL_DEINIT,
|
||||
MP_QSPI_IOCTL_BUS_ACQUIRE,
|
||||
MP_QSPI_IOCTL_BUS_RELEASE,
|
||||
};
|
||||
|
||||
typedef struct _mp_qspi_proto_t {
|
||||
int (*ioctl)(void *self, uint32_t cmd);
|
||||
void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
|
||||
void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
|
||||
uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len);
|
||||
void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
|
||||
} mp_qspi_proto_t;
|
||||
|
||||
typedef struct _mp_soft_qspi_obj_t {
|
||||
mp_hal_pin_obj_t cs;
|
||||
mp_hal_pin_obj_t clk;
|
||||
mp_hal_pin_obj_t io0;
|
||||
mp_hal_pin_obj_t io1;
|
||||
mp_hal_pin_obj_t io2;
|
||||
mp_hal_pin_obj_t io3;
|
||||
} mp_soft_qspi_obj_t;
|
||||
|
||||
extern const mp_qspi_proto_t mp_soft_qspi_proto;
|
||||
|
||||
#endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "drivers/bus/qspi.h"
|
||||
|
||||
#define CS_LOW(self) mp_hal_pin_write(self->cs, 0)
|
||||
#define CS_HIGH(self) mp_hal_pin_write(self->cs, 1)
|
||||
|
||||
#ifdef MICROPY_HW_SOFTQSPI_SCK_LOW
|
||||
|
||||
// Use externally provided functions for SCK control and IO reading
|
||||
#define SCK_LOW(self) MICROPY_HW_SOFTQSPI_SCK_LOW(self)
|
||||
#define SCK_HIGH(self) MICROPY_HW_SOFTQSPI_SCK_HIGH(self)
|
||||
#define NIBBLE_READ(self) MICROPY_HW_SOFTQSPI_NIBBLE_READ(self)
|
||||
|
||||
#else
|
||||
|
||||
// Use generic pin functions for SCK control and IO reading
|
||||
#define SCK_LOW(self) mp_hal_pin_write(self->clk, 0)
|
||||
#define SCK_HIGH(self) mp_hal_pin_write(self->clk, 1)
|
||||
#define NIBBLE_READ(self) ( \
|
||||
mp_hal_pin_read(self->io0) \
|
||||
| (mp_hal_pin_read(self->io1) << 1) \
|
||||
| (mp_hal_pin_read(self->io2) << 2) \
|
||||
| (mp_hal_pin_read(self->io3) << 3))
|
||||
|
||||
#endif
|
||||
|
||||
STATIC void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
|
||||
mp_hal_pin_write(self->io0, v & 1);
|
||||
mp_hal_pin_write(self->io1, (v >> 1) & 1);
|
||||
mp_hal_pin_write(self->io2, (v >> 2) & 1);
|
||||
mp_hal_pin_write(self->io3, (v >> 3) & 1);
|
||||
}
|
||||
|
||||
STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
|
||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
|
||||
|
||||
switch (cmd) {
|
||||
case MP_QSPI_IOCTL_INIT:
|
||||
mp_hal_pin_high(self->cs);
|
||||
mp_hal_pin_output(self->cs);
|
||||
|
||||
// Configure pins
|
||||
mp_hal_pin_write(self->clk, 0);
|
||||
mp_hal_pin_output(self->clk);
|
||||
// mp_hal_pin_write(self->clk, 1);
|
||||
mp_hal_pin_output(self->io0);
|
||||
mp_hal_pin_input(self->io1);
|
||||
mp_hal_pin_write(self->io2, 1);
|
||||
mp_hal_pin_output(self->io2);
|
||||
mp_hal_pin_write(self->io3, 1);
|
||||
mp_hal_pin_output(self->io3);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
// Will run as fast as possible, limited only by CPU speed and GPIO time
|
||||
mp_hal_pin_input(self->io1);
|
||||
mp_hal_pin_output(self->io0);
|
||||
if (self->io3) {
|
||||
mp_hal_pin_write(self->io2, 1);
|
||||
mp_hal_pin_output(self->io2);
|
||||
mp_hal_pin_write(self->io3, 1);
|
||||
mp_hal_pin_output(self->io3);
|
||||
}
|
||||
if (src) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
uint8_t data_out = src[i];
|
||||
uint8_t data_in = 0;
|
||||
for (int j = 0; j < 8; ++j, data_out <<= 1) {
|
||||
mp_hal_pin_write(self->io0, (data_out >> 7) & 1);
|
||||
mp_hal_pin_write(self->clk, 1);
|
||||
data_in = (data_in << 1) | mp_hal_pin_read(self->io1);
|
||||
mp_hal_pin_write(self->clk, 0);
|
||||
}
|
||||
if (dest != NULL) {
|
||||
dest[i] = data_in;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
uint8_t data_in = 0;
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
mp_hal_pin_write(self->clk, 1);
|
||||
data_in = (data_in << 1) | mp_hal_pin_read(self->io1);
|
||||
mp_hal_pin_write(self->clk, 0);
|
||||
}
|
||||
if (dest != NULL) {
|
||||
dest[i] = data_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *buf) {
|
||||
// Make all IO lines input
|
||||
mp_hal_pin_input(self->io2);
|
||||
mp_hal_pin_input(self->io3);
|
||||
mp_hal_pin_input(self->io0);
|
||||
mp_hal_pin_input(self->io1);
|
||||
|
||||
// Will run as fast as possible, limited only by CPU speed and GPIO time
|
||||
while (len--) {
|
||||
SCK_HIGH(self);
|
||||
uint8_t data_in = NIBBLE_READ(self);
|
||||
SCK_LOW(self);
|
||||
SCK_HIGH(self);
|
||||
*buf++ = (data_in << 4) | NIBBLE_READ(self);
|
||||
SCK_LOW(self);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *buf) {
|
||||
// Make all IO lines output
|
||||
mp_hal_pin_output(self->io2);
|
||||
mp_hal_pin_output(self->io3);
|
||||
mp_hal_pin_output(self->io0);
|
||||
mp_hal_pin_output(self->io1);
|
||||
|
||||
// Will run as fast as possible, limited only by CPU speed and GPIO time
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
nibble_write(self, buf[i] >> 4);
|
||||
SCK_HIGH(self);
|
||||
SCK_LOW(self);
|
||||
|
||||
nibble_write(self, buf[i]);
|
||||
SCK_HIGH(self);
|
||||
SCK_LOW(self);
|
||||
}
|
||||
|
||||
// mp_hal_pin_input(self->io1);
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
|
||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
|
||||
uint32_t cmd_buf = cmd | data << 8;
|
||||
CS_LOW(self);
|
||||
mp_soft_qspi_transfer(self, 1 + len, (uint8_t *)&cmd_buf, NULL);
|
||||
CS_HIGH(self);
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
|
||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
|
||||
uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr};
|
||||
CS_LOW(self);
|
||||
mp_soft_qspi_transfer(self, 4, cmd_buf, NULL);
|
||||
mp_soft_qspi_transfer(self, len, src, NULL);
|
||||
CS_HIGH(self);
|
||||
}
|
||||
|
||||
STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
|
||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
|
||||
uint32_t cmd_buf = cmd;
|
||||
CS_LOW(self);
|
||||
mp_soft_qspi_transfer(self, 1 + len, (uint8_t *)&cmd_buf, (uint8_t *)&cmd_buf);
|
||||
CS_HIGH(self);
|
||||
return cmd_buf >> 8;
|
||||
}
|
||||
|
||||
STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
|
||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
|
||||
uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr};
|
||||
CS_LOW(self);
|
||||
mp_soft_qspi_transfer(self, 1, cmd_buf, NULL);
|
||||
mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
|
||||
mp_soft_qspi_qread(self, len, dest);
|
||||
CS_HIGH(self);
|
||||
}
|
||||
|
||||
const mp_qspi_proto_t mp_soft_qspi_proto = {
|
||||
.ioctl = mp_soft_qspi_ioctl,
|
||||
.write_cmd_data = mp_soft_qspi_write_cmd_data,
|
||||
.write_cmd_addr_data = mp_soft_qspi_write_cmd_addr_data,
|
||||
.read_cmd = mp_soft_qspi_read_cmd,
|
||||
.read_cmd_qaddr_qdata = mp_soft_qspi_read_cmd_qaddr_qdata,
|
||||
};
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "drivers/bus/spi.h"
|
||||
|
||||
int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) {
|
||||
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t *)self_in;
|
||||
|
||||
switch (cmd) {
|
||||
case MP_SPI_IOCTL_INIT:
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
mp_hal_pin_output(self->sck);
|
||||
mp_hal_pin_output(self->mosi);
|
||||
mp_hal_pin_input(self->miso);
|
||||
break;
|
||||
|
||||
case MP_SPI_IOCTL_DEINIT:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t *)self_in;
|
||||
uint32_t delay_half = self->delay_half;
|
||||
|
||||
// only MSB transfer is implemented
|
||||
|
||||
// If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured
|
||||
// delay_half is equal to this value, then the software SPI implementation
|
||||
// will run as fast as possible, limited only by CPU speed and GPIO time.
|
||||
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
|
||||
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
uint8_t data_out = src[i];
|
||||
uint8_t data_in = 0;
|
||||
for (int j = 0; j < 8; ++j, data_out <<= 1) {
|
||||
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
|
||||
mp_hal_pin_write(self->sck, 1 - self->polarity);
|
||||
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
}
|
||||
if (dest != NULL) {
|
||||
dest[i] = data_in;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
uint8_t data_out = src[i];
|
||||
uint8_t data_in = 0;
|
||||
for (int j = 0; j < 8; ++j, data_out <<= 1) {
|
||||
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
|
||||
if (self->phase == 0) {
|
||||
mp_hal_delay_us_fast(delay_half);
|
||||
mp_hal_pin_write(self->sck, 1 - self->polarity);
|
||||
} else {
|
||||
mp_hal_pin_write(self->sck, 1 - self->polarity);
|
||||
mp_hal_delay_us_fast(delay_half);
|
||||
}
|
||||
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
|
||||
if (self->phase == 0) {
|
||||
mp_hal_delay_us_fast(delay_half);
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
} else {
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
mp_hal_delay_us_fast(delay_half);
|
||||
}
|
||||
}
|
||||
if (dest != NULL) {
|
||||
dest[i] = data_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mp_spi_proto_t mp_soft_spi_proto = {
|
||||
.ioctl = mp_soft_spi_ioctl,
|
||||
.transfer = mp_soft_spi_transfer,
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
This is the driver for the WIZnet5x00 series of Ethernet controllers.
|
||||
|
||||
Adapted for MicroPython.
|
||||
|
||||
Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary
|
||||
Taken on: 30 August 2014
|
|
@ -1,718 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file socket.c
|
||||
//! \brief SOCKET APIs Implements file.
|
||||
//! \details SOCKET APIs like as Berkeley Socket APIs.
|
||||
//! \version 1.0.3
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2018/10/09> Nick Moore fixes for CircuitPython
|
||||
//! <2014/05/01> V1.0.3. Refer to M20140501
|
||||
//! 1. Implicit type casting -> Explicit type casting.
|
||||
//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
|
||||
//! 3. Validation a destination ip in connect() & sendto():
|
||||
//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
|
||||
//! Copy 4 byte addr value into temporary uint32 variable and then compares it.
|
||||
//! <2013/12/20> V1.0.2 Refer to M20131220
|
||||
//! Remove Warning.
|
||||
//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
|
||||
//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mpthread.h"
|
||||
#include "socket.h"
|
||||
|
||||
#define SOCK_ANY_PORT_NUM 0xC000;
|
||||
|
||||
static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
static uint16_t sock_io_mode = 0;
|
||||
static uint16_t sock_is_sending = 0;
|
||||
static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
|
||||
static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
|
||||
|
||||
#if _WIZCHIP_ == 5200
|
||||
static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
|
||||
#endif
|
||||
|
||||
#define CHECK_SOCKNUM() \
|
||||
do{ \
|
||||
if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKMODE(mode) \
|
||||
do{ \
|
||||
if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKINIT() \
|
||||
do{ \
|
||||
if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
|
||||
}while(0); \
|
||||
|
||||
#define CHECK_SOCKDATA() \
|
||||
do{ \
|
||||
if(len == 0) return SOCKERR_DATALEN; \
|
||||
}while(0); \
|
||||
|
||||
void WIZCHIP_EXPORT(socket_reset)(void) {
|
||||
sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
sock_io_mode = 0;
|
||||
sock_is_sending = 0;
|
||||
/*
|
||||
memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
|
||||
memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
|
||||
*/
|
||||
|
||||
#if _WIZCHIP_ == 5200
|
||||
memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
switch(protocol)
|
||||
{
|
||||
case Sn_MR_TCP :
|
||||
case Sn_MR_UDP :
|
||||
case Sn_MR_MACRAW :
|
||||
break;
|
||||
#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_IPRAW :
|
||||
case Sn_MR_PPPoE :
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(flag & 0x10) return SOCKERR_SOCKFLAG;
|
||||
#endif
|
||||
|
||||
if(flag != 0)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case Sn_MR_TCP:
|
||||
if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
|
||||
break;
|
||||
case Sn_MR_UDP:
|
||||
if(flag & SF_IGMP_VER2)
|
||||
{
|
||||
if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
|
||||
}
|
||||
#if _WIZCHIP_ == 5500
|
||||
if(flag & SF_UNI_BLOCK)
|
||||
{
|
||||
if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
setSn_MR(sn, (protocol | (flag & 0xF0)));
|
||||
if(!port)
|
||||
{
|
||||
port = sock_any_port++;
|
||||
if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
|
||||
}
|
||||
setSn_PORT(sn,port);
|
||||
setSn_CR(sn,Sn_CR_OPEN);
|
||||
while(getSn_CR(sn));
|
||||
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
sock_remained_size[sn] = 0;
|
||||
sock_pack_info[sn] = 0;
|
||||
while(getSn_SR(sn) == SOCK_CLOSED);
|
||||
return (int8_t)sn;
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(close)(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
|
||||
setSn_CR(sn,Sn_CR_CLOSE);
|
||||
/* wait to process the command... */
|
||||
while( getSn_CR(sn) );
|
||||
/* clear all interrupt of the socket. */
|
||||
setSn_IR(sn, 0xFF);
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
sock_remained_size[sn] = 0;
|
||||
sock_pack_info[sn] = 0;
|
||||
while(getSn_SR(sn) != SOCK_CLOSED);
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(listen)(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKINIT();
|
||||
setSn_CR(sn,Sn_CR_LISTEN);
|
||||
while(getSn_CR(sn));
|
||||
while(getSn_SR(sn) != SOCK_LISTEN)
|
||||
{
|
||||
if(getSn_CR(sn) == SOCK_CLOSED)
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_SOCKCLOSED;
|
||||
}
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
|
||||
int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKINIT();
|
||||
//M20140501 : For avoiding fatal error on memory align mismatched
|
||||
//if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
|
||||
{
|
||||
uint32_t taddr;
|
||||
taddr = ((uint32_t)addr[0] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
|
||||
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
|
||||
if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
|
||||
}
|
||||
//
|
||||
|
||||
if(port == 0) return SOCKERR_PORTZERO;
|
||||
setSn_DIPR(sn,addr);
|
||||
setSn_DPORT(sn,port);
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR(wizchip_getsubn());
|
||||
#endif
|
||||
setSn_CR(sn,Sn_CR_CONNECT);
|
||||
while(getSn_CR(sn));
|
||||
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
|
||||
while(getSn_SR(sn) != SOCK_ESTABLISHED)
|
||||
{
|
||||
if (getSn_SR(sn) == SOCK_CLOSED) {
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
#endif
|
||||
return SOCKERR_SOCKCLOSED;
|
||||
}
|
||||
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
#endif
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
MICROPY_THREAD_YIELD();
|
||||
}
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
#endif
|
||||
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
setSn_CR(sn,Sn_CR_DISCON);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
|
||||
while(getSn_SR(sn) != SOCK_CLOSED)
|
||||
{
|
||||
if(getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len)
|
||||
{
|
||||
uint8_t tmp=0;
|
||||
uint16_t freesize=0;
|
||||
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKDATA();
|
||||
tmp = getSn_SR(sn);
|
||||
if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
|
||||
if( sock_is_sending & (1<<sn) )
|
||||
{
|
||||
tmp = getSn_IR(sn);
|
||||
if(tmp & Sn_IR_SENDOK)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_SENDOK);
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(getSn_TX_RD(sn) != sock_next_rd[sn])
|
||||
{
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
while(getSn_CR(sn));
|
||||
return SOCKERR_BUSY;
|
||||
}
|
||||
#endif
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
}
|
||||
else if(tmp & Sn_IR_TIMEOUT)
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
else return SOCK_BUSY;
|
||||
}
|
||||
freesize = getSn_TxMAX(sn);
|
||||
if (len > freesize) len = freesize; // check size not to exceed MAX size.
|
||||
while(1)
|
||||
{
|
||||
freesize = getSn_TX_FSR(sn);
|
||||
tmp = getSn_SR(sn);
|
||||
if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
}
|
||||
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
|
||||
if(len <= freesize) break;
|
||||
MICROPY_THREAD_YIELD();
|
||||
}
|
||||
wiz_send_data(sn, buf, len);
|
||||
#if _WIZCHIP_ == 5200
|
||||
sock_next_rd[sn] = getSn_TX_RD(sn) + len;
|
||||
#endif
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
sock_is_sending |= (1 << sn);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
uint16_t recvsize = 0;
|
||||
CHECK_SOCKNUM();
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
CHECK_SOCKDATA();
|
||||
|
||||
recvsize = getSn_RxMAX(sn);
|
||||
if(recvsize < len) len = recvsize;
|
||||
while(1)
|
||||
{
|
||||
recvsize = getSn_RX_RSR(sn);
|
||||
tmp = getSn_SR(sn);
|
||||
if (tmp != SOCK_ESTABLISHED)
|
||||
{
|
||||
if(tmp == SOCK_CLOSE_WAIT)
|
||||
{
|
||||
if(recvsize != 0) break;
|
||||
else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
|
||||
{
|
||||
// dpgeorge: Getting here seems to be an orderly shutdown of the
|
||||
// socket, and trying to get POSIX behaviour we return 0 because:
|
||||
// "If no messages are available to be received and the peer has per‐
|
||||
// formed an orderly shutdown, recv() shall return 0".
|
||||
// TODO this return value clashes with SOCK_BUSY in non-blocking mode.
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKERR_SOCKSTATUS;
|
||||
}
|
||||
}
|
||||
if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
|
||||
if(recvsize != 0) break;
|
||||
MICROPY_THREAD_YIELD();
|
||||
};
|
||||
if(recvsize < len) len = recvsize;
|
||||
wiz_recv_data(sn, buf, len);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
uint16_t freesize = 0;
|
||||
CHECK_SOCKNUM();
|
||||
switch(getSn_MR(sn) & 0x0F)
|
||||
{
|
||||
case Sn_MR_UDP:
|
||||
case Sn_MR_MACRAW:
|
||||
break;
|
||||
default:
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
CHECK_SOCKDATA();
|
||||
//M20140501 : For avoiding fatal error on memory align mismatched
|
||||
//if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
|
||||
if ((addr[0] | addr[1] | addr[2] | addr[3]) == 0) return SOCKERR_IPINVALID;
|
||||
if(port == 0) return SOCKERR_PORTZERO;
|
||||
tmp = getSn_SR(sn);
|
||||
if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
|
||||
|
||||
setSn_DIPR(sn,addr);
|
||||
setSn_DPORT(sn,port);
|
||||
freesize = getSn_TxMAX(sn);
|
||||
if (len > freesize) len = freesize; // check size not to exceed MAX size.
|
||||
while(1)
|
||||
{
|
||||
freesize = getSn_TX_FSR(sn);
|
||||
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
|
||||
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
|
||||
if(len <= freesize) break;
|
||||
MICROPY_THREAD_YIELD();
|
||||
};
|
||||
wiz_send_data(sn, buf, len);
|
||||
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR(wizchip_getsubn());
|
||||
#endif
|
||||
|
||||
setSn_CR(sn,Sn_CR_SEND);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn));
|
||||
while(1)
|
||||
{
|
||||
tmp = getSn_IR(sn);
|
||||
if(tmp & Sn_IR_SENDOK)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_SENDOK);
|
||||
break;
|
||||
}
|
||||
//M:20131104
|
||||
//else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
|
||||
else if(tmp & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
#endif
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
////////////
|
||||
MICROPY_THREAD_YIELD();
|
||||
}
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
setSUBR((uint8_t*)"\x00\x00\x00\x00");
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
|
||||
{
|
||||
uint8_t mr;
|
||||
uint8_t head[8];
|
||||
uint16_t pack_len=0;
|
||||
|
||||
CHECK_SOCKNUM();
|
||||
//CHECK_SOCKMODE(Sn_MR_UDP);
|
||||
switch((mr=getSn_MR(sn)) & 0x0F)
|
||||
{
|
||||
case Sn_MR_UDP:
|
||||
case Sn_MR_MACRAW:
|
||||
break;
|
||||
#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_IPRAW:
|
||||
case Sn_MR_PPPoE:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return SOCKERR_SOCKMODE;
|
||||
}
|
||||
CHECK_SOCKDATA();
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
pack_len = getSn_RX_RSR(sn);
|
||||
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
|
||||
if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
|
||||
if(pack_len != 0) break;
|
||||
MICROPY_THREAD_YIELD();
|
||||
};
|
||||
}
|
||||
sock_pack_info[sn] = PACK_COMPLETED;
|
||||
switch (mr & 0x07)
|
||||
{
|
||||
case Sn_MR_UDP :
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 8);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
// read peer's IP address, port number & packet length
|
||||
addr[0] = head[0];
|
||||
addr[1] = head[1];
|
||||
addr[2] = head[2];
|
||||
addr[3] = head[3];
|
||||
*port = head[4];
|
||||
*port = (*port << 8) + head[5];
|
||||
sock_remained_size[sn] = head[6];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
//
|
||||
// Need to packet length check (default 1472)
|
||||
//
|
||||
wiz_recv_data(sn, buf, pack_len); // data copy.
|
||||
break;
|
||||
case Sn_MR_MACRAW :
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 2);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
// read peer's IP address, port number & packet length
|
||||
sock_remained_size[sn] = head[0];
|
||||
sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
|
||||
sock_remained_size[sn] -= 2; // len includes 2 len bytes
|
||||
if(sock_remained_size[sn] > 1514)
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
return SOCKFATAL_PACKLEN;
|
||||
}
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
wiz_recv_data(sn,buf,pack_len);
|
||||
break;
|
||||
#if ( _WIZCHIP_ < 5200 )
|
||||
case Sn_MR_IPRAW:
|
||||
if(sock_remained_size[sn] == 0)
|
||||
{
|
||||
wiz_recv_data(sn, head, 6);
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
while(getSn_CR(sn));
|
||||
addr[0] = head[0];
|
||||
addr[1] = head[1];
|
||||
addr[2] = head[2];
|
||||
addr[3] = head[3];
|
||||
sock_remained_size[sn] = head[4];
|
||||
sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
|
||||
sock_pack_info[sn] = PACK_FIRST;
|
||||
}
|
||||
//
|
||||
// Need to packet length check
|
||||
//
|
||||
if(len < sock_remained_size[sn]) pack_len = len;
|
||||
else pack_len = sock_remained_size[sn];
|
||||
wiz_recv_data(sn, buf, pack_len); // data copy.
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
wiz_recv_ignore(sn, pack_len); // data copy.
|
||||
sock_remained_size[sn] = pack_len;
|
||||
break;
|
||||
}
|
||||
setSn_CR(sn,Sn_CR_RECV);
|
||||
/* wait to process the command... */
|
||||
while(getSn_CR(sn)) ;
|
||||
sock_remained_size[sn] -= pack_len;
|
||||
//M20140501 : replace 0x01 with PACK_REMAINED
|
||||
//if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
|
||||
if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
|
||||
//
|
||||
return pack_len;
|
||||
}
|
||||
|
||||
|
||||
int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
CHECK_SOCKNUM();
|
||||
switch(cstype)
|
||||
{
|
||||
case CS_SET_IOMODE:
|
||||
tmp = *((uint8_t*)arg);
|
||||
if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn);
|
||||
else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
|
||||
else return SOCKERR_ARG;
|
||||
break;
|
||||
case CS_GET_IOMODE:
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
|
||||
*((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
|
||||
//
|
||||
break;
|
||||
case CS_GET_MAXTXBUF:
|
||||
*((uint16_t*)arg) = getSn_TxMAX(sn);
|
||||
break;
|
||||
case CS_GET_MAXRXBUF:
|
||||
*((uint16_t*)arg) = getSn_RxMAX(sn);
|
||||
break;
|
||||
case CS_CLR_INTERRUPT:
|
||||
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
|
||||
setSn_IR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case CS_GET_INTERRUPT:
|
||||
*((uint8_t*)arg) = getSn_IR(sn);
|
||||
break;
|
||||
case CS_SET_INTMASK:
|
||||
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
|
||||
setSn_IMR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case CS_GET_INTMASK:
|
||||
*((uint8_t*)arg) = getSn_IMR(sn);
|
||||
default:
|
||||
return SOCKERR_ARG;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
|
||||
{
|
||||
// M20131220 : Remove warning
|
||||
//uint8_t tmp;
|
||||
CHECK_SOCKNUM();
|
||||
switch(sotype)
|
||||
{
|
||||
case SO_TTL:
|
||||
setSn_TTL(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case SO_TOS:
|
||||
setSn_TOS(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
case SO_MSS:
|
||||
setSn_MSSR(sn,*(uint16_t*)arg);
|
||||
break;
|
||||
case SO_DESTIP:
|
||||
setSn_DIPR(sn, (uint8_t*)arg);
|
||||
break;
|
||||
case SO_DESTPORT:
|
||||
setSn_DPORT(sn, *(uint16_t*)arg);
|
||||
break;
|
||||
#if _WIZCHIP_ != 5100
|
||||
case SO_KEEPALIVESEND:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
#if _WIZCHIP_ > 5200
|
||||
if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
|
||||
#endif
|
||||
setSn_CR(sn,Sn_CR_SEND_KEEP);
|
||||
while(getSn_CR(sn) != 0)
|
||||
{
|
||||
// M20131220
|
||||
//if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
|
||||
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
|
||||
{
|
||||
setSn_IR(sn, Sn_IR_TIMEOUT);
|
||||
return SOCKERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if _WIZCHIP_ > 5200
|
||||
case SO_KEEPALIVEAUTO:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
setSn_KPALVTR(sn,*(uint8_t*)arg);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
return SOCKERR_ARG;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
||||
|
||||
int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
|
||||
{
|
||||
CHECK_SOCKNUM();
|
||||
switch(sotype)
|
||||
{
|
||||
case SO_FLAG:
|
||||
*(uint8_t*)arg = getSn_MR(sn) & 0xF0;
|
||||
break;
|
||||
case SO_TTL:
|
||||
*(uint8_t*) arg = getSn_TTL(sn);
|
||||
break;
|
||||
case SO_TOS:
|
||||
*(uint8_t*) arg = getSn_TOS(sn);
|
||||
break;
|
||||
case SO_MSS:
|
||||
*(uint8_t*) arg = getSn_MSSR(sn);
|
||||
case SO_DESTIP:
|
||||
getSn_DIPR(sn, (uint8_t*)arg);
|
||||
break;
|
||||
case SO_DESTPORT:
|
||||
*(uint16_t*) arg = getSn_DPORT(sn);
|
||||
break;
|
||||
#if _WIZCHIP_ > 5200
|
||||
case SO_KEEPALIVEAUTO:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
*(uint16_t*) arg = getSn_KPALVTR(sn);
|
||||
break;
|
||||
#endif
|
||||
case SO_SENDBUF:
|
||||
*(uint16_t*) arg = getSn_TX_FSR(sn);
|
||||
case SO_RECVBUF:
|
||||
*(uint16_t*) arg = getSn_RX_RSR(sn);
|
||||
case SO_STATUS:
|
||||
*(uint8_t*) arg = getSn_SR(sn);
|
||||
break;
|
||||
case SO_REMAINSIZE:
|
||||
if(getSn_MR(sn) == Sn_MR_TCP)
|
||||
*(uint16_t*)arg = getSn_RX_RSR(sn);
|
||||
else
|
||||
*(uint16_t*)arg = sock_remained_size[sn];
|
||||
break;
|
||||
case SO_PACKINFO:
|
||||
CHECK_SOCKMODE(Sn_MR_TCP);
|
||||
*(uint8_t*)arg = sock_pack_info[sn];
|
||||
break;
|
||||
default:
|
||||
return SOCKERR_SOCKOPT;
|
||||
}
|
||||
return SOCK_OK;
|
||||
}
|
|
@ -1,472 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file socket.h
|
||||
//! \brief SOCKET APIs Header file.
|
||||
//! \details SOCKET APIs like as berkeley socket api.
|
||||
//! \version 1.0.2
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2014/05/01> V1.0.2. Refer to M20140501
|
||||
//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED
|
||||
//! 2. Add the comment as zero byte udp data reception in getsockopt().
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/**
|
||||
* @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
|
||||
* @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface.
|
||||
* But there is a little bit of difference.
|
||||
* @details
|
||||
* <b> Comparison between WIZnet and Berkeley SOCKET APIs </b>
|
||||
* <table>
|
||||
* <tr> <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td> </tr>
|
||||
* <tr> <td>socket()</td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>bind()</b></td> <td>X</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>listen()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>connect()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>accept()</b></td> <td>X</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>recv()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>send()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>recvfrom()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>sendto()</b></td> <td>O</td> <td>O</td> </tr>
|
||||
* <tr> <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td> </tr>
|
||||
* </table>
|
||||
* There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
|
||||
* not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
|
||||
* and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
|
||||
* When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
|
||||
* When the listen SOCKET accepts a connection request from a client, it keeps listening.
|
||||
* After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
|
||||
* Following figure shows network flow diagram by Berkeley SOCKET API.
|
||||
* @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>"
|
||||
* But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
|
||||
* Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
|
||||
* it is changed in order to communicate with the client.
|
||||
* And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
|
||||
* If there're many listen SOCKET with same listen port number and a client requests a connection,
|
||||
* the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
|
||||
* Following figure shows network flow diagram by WIZnet SOCKET API.
|
||||
* @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>"
|
||||
*/
|
||||
#ifndef _WIZCHIP_SOCKET_H_
|
||||
#define _WIZCHIP_SOCKET_H_
|
||||
|
||||
// use this macro for exported names to avoid name clashes
|
||||
#define WIZCHIP_EXPORT(name) wizchip_ ## name
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
|
||||
#define SOCKET uint8_t ///< SOCKET type define for legacy driver
|
||||
|
||||
#define SOCK_OK 1 ///< Result is OK about socket process.
|
||||
#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
|
||||
#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
|
||||
|
||||
#define SOCK_ERROR 0
|
||||
#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
|
||||
#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
|
||||
#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized
|
||||
#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
|
||||
#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
|
||||
#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
|
||||
#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
|
||||
#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument.
|
||||
#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
|
||||
#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
|
||||
#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
|
||||
#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
|
||||
#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
|
||||
|
||||
#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
|
||||
|
||||
/*
|
||||
* SOCKET FLAG
|
||||
*/
|
||||
#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
|
||||
#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.
|
||||
#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack.
|
||||
#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode.
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
#define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
|
||||
#define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
|
||||
#define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
|
||||
#define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
|
||||
#endif
|
||||
|
||||
#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
|
||||
|
||||
/*
|
||||
* UDP & MACRAW Packet Infomation
|
||||
*/
|
||||
#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet.
|
||||
#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
|
||||
#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
|
||||
|
||||
// resets all global state associated with the socket interface
|
||||
void WIZCHIP_EXPORT(socket_reset)(void);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Open a socket.
|
||||
* @details Initializes the socket with 'sn' passed as parameter and open.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
|
||||
* @param port Port number to be bined.
|
||||
* @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
|
||||
* Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
|
||||
* @sa Sn_MR
|
||||
*
|
||||
* @return @b Success : The socket number @b 'sn' passed as parameter\n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
|
||||
* @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n
|
||||
* @ref SOCKERR_SOCKFLAG - Invaild socket flag.
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Close a socket.
|
||||
* @details It closes the socket with @b'sn' passed as parameter.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
*
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(close)(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Listen to a connection request from a client.
|
||||
* @details It is listening to a connection request from a client.
|
||||
* If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n
|
||||
* @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(listen)(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Try to connect a server.
|
||||
* @details It requests connection to the server with destination IP address and port number passed as parameter.\n
|
||||
* @note It is valid only in TCP client mode.
|
||||
* In block io mode, it does not return until connection is completed.
|
||||
* In Non-block io mode, it return @ref SOCK_BUSY immediately.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* @param port Destination port number.
|
||||
*
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid socket mode\n
|
||||
* @ref SOCKERR_SOCKINIT - Socket is not initialized\n
|
||||
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
|
||||
* @ref SOCKERR_PORTZERO - Server port zero\n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n
|
||||
* @ref SOCK_BUSY - In non-block io mode, it returned immediately\n
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Try to disconnect a connection socket.
|
||||
* @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
|
||||
* @note It is valid only in TCP server or client mode. \n
|
||||
* In block io mode, it does not return until disconnection is completed. \n
|
||||
* In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
|
||||
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @return @b Success : @ref SOCK_OK \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Send data to the connected peer in TCP socket.
|
||||
* @details It is used to send outgoing data to the connected socket.
|
||||
* @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
|
||||
* In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
|
||||
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer containing data to be sent.
|
||||
* @param len The byte length of data in buf.
|
||||
* @return @b Success : The sent data size \n
|
||||
* @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Receive data from the connected peer.
|
||||
* @details It is used to read incoming data from the connected socket.\n
|
||||
* It waits for data as much as the application wants to receive.
|
||||
* @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
|
||||
* In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n
|
||||
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to read incoming data.
|
||||
* @param len The max data length of data in buf.
|
||||
* @return @b Success : The real received data size \n
|
||||
* @b Fail :\n
|
||||
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Sends datagram to the peer with destination IP address and port number passed as parameter.
|
||||
* @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
|
||||
* Even if the connectionless socket has been previously connected to a specific address,
|
||||
* the address and port number parameters override the destination address for that particular datagram only.
|
||||
* @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>.
|
||||
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to send outgoing data.
|
||||
* @param len The byte length of data in buf.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* @param port Destination port number.
|
||||
*
|
||||
* @return @b Success : The sent data size \n
|
||||
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
|
||||
* @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
|
||||
* @ref SOCKERR_PORTZERO - Server port zero\n
|
||||
* @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n
|
||||
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
|
||||
* @ref SOCK_BUSY - Socket is busy.
|
||||
*/
|
||||
int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Receive datagram of UDP or MACRAW
|
||||
* @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
|
||||
* This function is used to receive UDP and MAC_RAW mode, and handle the header as well.
|
||||
* This function can divide to received the packet data.
|
||||
* On the MACRAW SOCKET, the addr and port parameters are ignored.
|
||||
* @note In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer
|
||||
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer.
|
||||
*
|
||||
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
|
||||
* @param buf Pointer buffer to read incoming data.
|
||||
* @param len The max data length of data in buf.
|
||||
* When the received packet size <= len, receives data as packet sized.
|
||||
* When others, receives data as len.
|
||||
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
|
||||
* It is valid only when the first call recvfrom for receiving the packet.
|
||||
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
|
||||
* @param port Pointer variable of destination port number.
|
||||
* It is valid only when the first call recvform for receiving the packet.
|
||||
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
|
||||
*
|
||||
* @return @b Success : This function return real received data size for success.\n
|
||||
* @b Fail : @ref SOCKERR_DATALEN - zero data length \n
|
||||
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
|
||||
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
|
||||
* @ref SOCKBUSY - Socket is busy.
|
||||
*/
|
||||
int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// SOCKET CONTROL & OPTION //
|
||||
/////////////////////////////
|
||||
#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt().
|
||||
#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt().
|
||||
|
||||
/**
|
||||
* @defgroup DATA_TYPE DATA TYPE
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The kind of Socket Interrupt.
|
||||
* @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SIK_CONNECTED = (1 << 0), ///< connected
|
||||
SIK_DISCONNECTED = (1 << 1), ///< disconnected
|
||||
SIK_RECEIVED = (1 << 2), ///< data received
|
||||
SIK_TIMEOUT = (1 << 3), ///< timeout occurred
|
||||
SIK_SENT = (1 << 4), ///< send ok
|
||||
SIK_ALL = 0x1F, ///< all interrupt
|
||||
}sockint_kind;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The type of @ref ctlsocket().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
|
||||
CS_GET_IOMODE, ///< get socket IO mode
|
||||
CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory
|
||||
CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory
|
||||
CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind
|
||||
CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind
|
||||
CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind
|
||||
CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind
|
||||
}ctlsock_type;
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket().
|
||||
SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() )
|
||||
SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() )
|
||||
SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
|
||||
SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
|
||||
SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
|
||||
#if _WIZCHIP_ != 5100
|
||||
SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode
|
||||
#if _WIZCHIP_ > 5200
|
||||
SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode
|
||||
#endif
|
||||
#endif
|
||||
SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
|
||||
SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
|
||||
SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
|
||||
SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
|
||||
SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
|
||||
}sockopt_type;
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief Control socket.
|
||||
* @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
|
||||
* Refer to @ref ctlsock_type.
|
||||
* @param sn socket number
|
||||
* @param cstype type of control socket. refer to @ref ctlsock_type.
|
||||
* @param arg Data type and value is determined according to @ref ctlsock_type. \n
|
||||
* <table>
|
||||
* <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr>
|
||||
* <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr>
|
||||
* <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc. </td></tr>
|
||||
* </table>
|
||||
* @return @b Success @ref SOCK_OK \n
|
||||
* @b fail @ref SOCKERR_ARG - Invalid argument\n
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief set socket options
|
||||
* @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
|
||||
*
|
||||
* @param sn socket number
|
||||
* @param sotype socket option type. refer to @ref sockopt_type
|
||||
* @param arg Data type and value is determined according to <I>sotype</I>. \n
|
||||
* <table>
|
||||
* <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
|
||||
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
|
||||
* </table>
|
||||
* @return
|
||||
* - @b Success : @ref SOCK_OK \n
|
||||
* - @b Fail
|
||||
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
|
||||
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
|
||||
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
|
||||
* - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup WIZnet_socket_APIs
|
||||
* @brief get socket options
|
||||
* @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
|
||||
* @param sn socket number
|
||||
* @param sotype socket option type. refer to @ref sockopt_type
|
||||
* @param arg Data type and value is determined according to <I>sotype</I>. \n
|
||||
* <table>
|
||||
* <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr>
|
||||
* <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr>
|
||||
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
|
||||
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
|
||||
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr>
|
||||
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
|
||||
* <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr>
|
||||
* <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr>
|
||||
* <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr>
|
||||
* </table>
|
||||
* @return
|
||||
* - @b Success : @ref SOCK_OK \n
|
||||
* - @b Fail
|
||||
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
|
||||
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
|
||||
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
|
||||
* @note
|
||||
* The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
|
||||
* When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero,
|
||||
* This means the zero byte UDP data(UDP Header only) received.
|
||||
*/
|
||||
int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
|
||||
|
||||
#endif // _WIZCHIP_SOCKET_H_
|
|
@ -1,206 +0,0 @@
|
|||
// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5500.c
|
||||
//! \brief W5500 HAL Interface.
|
||||
//! \version 1.0.1
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2014/05/01> V1.0.2
|
||||
//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
|
||||
//! Fixed the problem on porting into under 32bit MCU
|
||||
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
|
||||
//! Thank for your interesting and serious advices.
|
||||
//! <2013/10/21> 1st Release
|
||||
//! <2013/12/20> V1.0.1
|
||||
//! 1. Remove warning
|
||||
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
|
||||
//! for loop optimized(removed). refer to M20131220
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "w5200.h"
|
||||
|
||||
#define SMASK (0x7ff) /* tx buffer mask */
|
||||
#define RMASK (0x7ff) /* rx buffer mask */
|
||||
#define SSIZE (2048) /* max tx buffer size */
|
||||
#define RSIZE (2048) /* max rx buffer size */
|
||||
|
||||
#define TXBUF_BASE (0x8000)
|
||||
#define RXBUF_BASE (0xc000)
|
||||
#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */
|
||||
#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */
|
||||
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel) {
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
uint8_t spi_data[4] = {
|
||||
AddrSel >> 8,
|
||||
AddrSel,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
|
||||
uint8_t ret;
|
||||
WIZCHIP.IF.SPI._read_bytes(&ret, 1);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
uint8_t spi_data[5] = {
|
||||
AddrSel >> 8,
|
||||
AddrSel,
|
||||
0x80,
|
||||
0x01,
|
||||
wb,
|
||||
};
|
||||
WIZCHIP.IF.SPI._write_bytes(spi_data, 5);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
uint8_t spi_data[4] = {
|
||||
AddrSel >> 8,
|
||||
AddrSel,
|
||||
0x00 | ((len >> 8) & 0x7f),
|
||||
len & 0xff,
|
||||
};
|
||||
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
|
||||
WIZCHIP.IF.SPI._read_bytes(pBuf, len);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
uint8_t spi_data[4] = {
|
||||
AddrSel >> 8,
|
||||
AddrSel,
|
||||
0x80 | ((len >> 8) & 0x7f),
|
||||
len & 0xff,
|
||||
};
|
||||
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
|
||||
WIZCHIP.IF.SPI._write_bytes(pBuf, len);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn) {
|
||||
uint16_t val = 0, val1 = 0;
|
||||
do {
|
||||
val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
|
||||
if (val1 != 0) {
|
||||
val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
|
||||
}
|
||||
} while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn) {
|
||||
uint16_t val = 0, val1 = 0;
|
||||
do {
|
||||
val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
|
||||
if (val1 != 0) {
|
||||
val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
|
||||
}
|
||||
} while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t ptr = getSn_TX_WR(sn);
|
||||
uint16_t offset = ptr & SMASK;
|
||||
uint32_t addr = offset + SBASE(sn);
|
||||
|
||||
if (offset + len > SSIZE) {
|
||||
// implement wrap-around circular buffer
|
||||
uint16_t size = SSIZE - offset;
|
||||
WIZCHIP_WRITE_BUF(addr, wizdata, size);
|
||||
WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size);
|
||||
} else {
|
||||
WIZCHIP_WRITE_BUF(addr, wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
setSn_TX_WR(sn, ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t ptr = getSn_RX_RD(sn);
|
||||
uint16_t offset = ptr & RMASK;
|
||||
uint16_t addr = RBASE(sn) + offset;
|
||||
|
||||
if (offset + len > RSIZE) {
|
||||
// implement wrap-around circular buffer
|
||||
uint16_t size = RSIZE - offset;
|
||||
WIZCHIP_READ_BUF(addr, wizdata, size);
|
||||
WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size);
|
||||
} else {
|
||||
WIZCHIP_READ_BUF(addr, wizdata, len);
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn, ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len) {
|
||||
uint16_t ptr = getSn_RX_RD(sn);
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn, ptr);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,246 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file w5500.c
|
||||
//! \brief W5500 HAL Interface.
|
||||
//! \version 1.0.1
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2014/05/01> V1.0.2
|
||||
//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
|
||||
//! Fixed the problem on porting into under 32bit MCU
|
||||
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
|
||||
//! Thank for your interesting and serious advices.
|
||||
//! <2013/10/21> 1st Release
|
||||
//! <2013/12/20> V1.0.1
|
||||
//! 1. Remove warning
|
||||
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
|
||||
//! for loop optimized(removed). refer to M20131220
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
//#include <stdio.h>
|
||||
#include "w5500.h"
|
||||
|
||||
#define _W5500_SPI_VDM_OP_ 0x00
|
||||
#define _W5500_SPI_FDM_OP_LEN1_ 0x01
|
||||
#define _W5500_SPI_FDM_OP_LEN2_ 0x02
|
||||
#define _W5500_SPI_FDM_OP_LEN4_ 0x03
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
#define LPC_SSP0 (0)
|
||||
|
||||
static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) {
|
||||
WIZCHIP.IF.SPI._read_bytes(buf, len);
|
||||
}
|
||||
|
||||
static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) {
|
||||
WIZCHIP.IF.SPI._write_bytes(buf, len);
|
||||
}
|
||||
|
||||
uint8_t WIZCHIP_READ(uint32_t AddrSel)
|
||||
{
|
||||
uint8_t ret;
|
||||
uint8_t spi_data[3];
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
//ret = WIZCHIP.IF.SPI._read_byte();
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
|
||||
Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
|
||||
{
|
||||
uint8_t spi_data[4];
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
//WIZCHIP.IF.SPI._write_byte(wb);
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
spi_data[3] = wb;
|
||||
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint8_t spi_data[3];
|
||||
//uint16_t i;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
//for(i = 0; i < len; i++)
|
||||
// pBuf[i] = WIZCHIP.IF.SPI._read_byte();
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
|
||||
Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
|
||||
{
|
||||
uint8_t spi_data[3];
|
||||
//uint16_t i;
|
||||
|
||||
WIZCHIP_CRITICAL_ENTER();
|
||||
WIZCHIP.CS._select();
|
||||
|
||||
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
|
||||
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
|
||||
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
|
||||
//for(i = 0; i < len; i++)
|
||||
// WIZCHIP.IF.SPI._write_byte(pBuf[i]);
|
||||
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
|
||||
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
|
||||
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
|
||||
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
|
||||
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len);
|
||||
|
||||
WIZCHIP.CS._deselect();
|
||||
WIZCHIP_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_TX_FSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_TX_FSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getSn_RX_RSR(uint8_t sn)
|
||||
{
|
||||
uint16_t val=0,val1=0;
|
||||
|
||||
do
|
||||
{
|
||||
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
if (val1 != 0)
|
||||
{
|
||||
val = WIZCHIP_READ(Sn_RX_RSR(sn));
|
||||
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
|
||||
}
|
||||
}while (val != val1);
|
||||
return val;
|
||||
}
|
||||
|
||||
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
uint32_t addrsel = 0;
|
||||
|
||||
if(len == 0) return;
|
||||
ptr = getSn_TX_WR(sn);
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
|
||||
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
|
||||
//
|
||||
WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
|
||||
|
||||
ptr += len;
|
||||
setSn_TX_WR(sn,ptr);
|
||||
}
|
||||
|
||||
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
uint32_t addrsel = 0;
|
||||
|
||||
if(len == 0) return;
|
||||
ptr = getSn_RX_RD(sn);
|
||||
//M20140501 : implict type casting -> explict type casting
|
||||
//addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
|
||||
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
|
||||
//
|
||||
WIZCHIP_READ_BUF(addrsel, wizdata, len);
|
||||
ptr += len;
|
||||
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
||||
|
||||
|
||||
void wiz_recv_ignore(uint8_t sn, uint16_t len)
|
||||
{
|
||||
uint16_t ptr = 0;
|
||||
|
||||
ptr = getSn_RX_RD(sn);
|
||||
ptr += len;
|
||||
setSn_RX_RD(sn,ptr);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,662 +0,0 @@
|
|||
//****************************************************************************/
|
||||
//!
|
||||
//! \file wizchip_conf.c
|
||||
//! \brief WIZCHIP Config Header File.
|
||||
//! \version 1.0.1
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2014/05/01> V1.0.1 Refer to M20140501
|
||||
//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte()
|
||||
// Issued by Mathias ClauBen.
|
||||
//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
|
||||
//! For remove the warning when pointer type size is not 32bit.
|
||||
//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************/
|
||||
//A20140501 : for use the type - ptrdiff_t
|
||||
#include <stddef.h>
|
||||
//
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
#include "socket.h"
|
||||
|
||||
/**
|
||||
* @brief Default function to enable interrupt.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_cris_enter(void) {};
|
||||
/**
|
||||
* @brief Default function to disable interrupt.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_cris_exit(void) {};
|
||||
/**
|
||||
* @brief Default function to select chip.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_cs_select(void) {};
|
||||
/**
|
||||
* @brief Default function to deselect chip.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_cs_deselect(void) {};
|
||||
/**
|
||||
* @brief Default function to read in direct or indirect interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
//M20140501 : Explict pointer type casting
|
||||
//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); };
|
||||
uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); };
|
||||
/**
|
||||
* @brief Default function to write in direct or indirect interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
|
||||
//M20140501 : Explict pointer type casting
|
||||
//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; };
|
||||
void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; };
|
||||
|
||||
/**
|
||||
* @brief Default function to read in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {}
|
||||
/**
|
||||
* @brief Default function to write in SPI interface.
|
||||
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
|
||||
* null function is called.
|
||||
*/
|
||||
void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {}
|
||||
|
||||
/**
|
||||
* @\ref _WIZCHIP instance
|
||||
*/
|
||||
_WIZCHIP WIZCHIP =
|
||||
{
|
||||
.id = _WIZCHIP_ID_,
|
||||
.if_mode = _WIZCHIP_IO_MODE_,
|
||||
.CRIS._enter = wizchip_cris_enter,
|
||||
.CRIS._exit = wizchip_cris_exit,
|
||||
.CS._select = wizchip_cs_select,
|
||||
.CS._deselect = wizchip_cs_deselect,
|
||||
.IF.BUS._read_byte = wizchip_bus_readbyte,
|
||||
.IF.BUS._write_byte = wizchip_bus_writebyte
|
||||
// .IF.SPI._read_byte = wizchip_spi_readbyte,
|
||||
// .IF.SPI._write_byte = wizchip_spi_writebyte
|
||||
};
|
||||
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
static uint8_t _SUBN_[4]; // subnet
|
||||
#endif
|
||||
static uint8_t _DNS_[4]; // DNS server ip address
|
||||
static dhcp_mode _DHCP_; // DHCP mode
|
||||
|
||||
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
|
||||
{
|
||||
if(!cris_en || !cris_ex)
|
||||
{
|
||||
WIZCHIP.CRIS._enter = wizchip_cris_enter;
|
||||
WIZCHIP.CRIS._exit = wizchip_cris_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.CRIS._enter = cris_en;
|
||||
WIZCHIP.CRIS._exit = cris_ex;
|
||||
}
|
||||
}
|
||||
|
||||
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
|
||||
{
|
||||
if(!cs_sel || !cs_desel)
|
||||
{
|
||||
WIZCHIP.CS._select = wizchip_cs_select;
|
||||
WIZCHIP.CS._deselect = wizchip_cs_deselect;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.CS._select = cs_sel;
|
||||
WIZCHIP.CS._deselect = cs_desel;
|
||||
}
|
||||
}
|
||||
|
||||
void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
|
||||
{
|
||||
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
|
||||
|
||||
if(!bus_rb || !bus_wb)
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
|
||||
WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.BUS._read_byte = bus_rb;
|
||||
WIZCHIP.IF.BUS._write_byte = bus_wb;
|
||||
}
|
||||
}
|
||||
|
||||
void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t))
|
||||
{
|
||||
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
|
||||
|
||||
if(!spi_rb || !spi_wb)
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes;
|
||||
WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
WIZCHIP.IF.SPI._read_bytes = spi_rb;
|
||||
WIZCHIP.IF.SPI._write_bytes = spi_wb;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
uint8_t* ptmp[2] = {0,0};
|
||||
switch(cwtype)
|
||||
{
|
||||
case CW_RESET_WIZCHIP:
|
||||
wizchip_sw_reset();
|
||||
break;
|
||||
case CW_INIT_WIZCHIP:
|
||||
if(arg != 0)
|
||||
{
|
||||
ptmp[0] = (uint8_t*)arg;
|
||||
ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
|
||||
}
|
||||
return wizchip_init(ptmp[0], ptmp[1]);
|
||||
case CW_CLR_INTERRUPT:
|
||||
wizchip_clrinterrupt(*((intr_kind*)arg));
|
||||
break;
|
||||
case CW_GET_INTERRUPT:
|
||||
*((intr_kind*)arg) = wizchip_getinterrupt();
|
||||
break;
|
||||
case CW_SET_INTRMASK:
|
||||
wizchip_setinterruptmask(*((intr_kind*)arg));
|
||||
break;
|
||||
case CW_GET_INTRMASK:
|
||||
*((intr_kind*)arg) = wizchip_getinterruptmask();
|
||||
break;
|
||||
#if _WIZCHIP_ > 5100
|
||||
case CW_SET_INTRTIME:
|
||||
setINTLEVEL(*(uint16_t*)arg);
|
||||
break;
|
||||
case CW_GET_INTRTIME:
|
||||
*(uint16_t*)arg = getINTLEVEL();
|
||||
break;
|
||||
#endif
|
||||
case CW_GET_ID:
|
||||
((uint8_t*)arg)[0] = WIZCHIP.id[0];
|
||||
((uint8_t*)arg)[1] = WIZCHIP.id[1];
|
||||
((uint8_t*)arg)[2] = WIZCHIP.id[2];
|
||||
((uint8_t*)arg)[3] = WIZCHIP.id[3];
|
||||
((uint8_t*)arg)[4] = WIZCHIP.id[4];
|
||||
((uint8_t*)arg)[5] = 0;
|
||||
break;
|
||||
#if _WIZCHIP_ == 5500
|
||||
case CW_RESET_PHY:
|
||||
wizphy_reset();
|
||||
break;
|
||||
case CW_SET_PHYCONF:
|
||||
wizphy_setphyconf((wiz_PhyConf*)arg);
|
||||
break;
|
||||
case CW_GET_PHYCONF:
|
||||
wizphy_getphyconf((wiz_PhyConf*)arg);
|
||||
break;
|
||||
case CW_GET_PHYSTATUS:
|
||||
break;
|
||||
case CW_SET_PHYPOWMODE:
|
||||
return wizphy_setphypmode(*(uint8_t*)arg);
|
||||
#endif
|
||||
case CW_GET_PHYPOWMODE:
|
||||
tmp = wizphy_getphypmode();
|
||||
if((int8_t)tmp == -1) return -1;
|
||||
*(uint8_t*)arg = tmp;
|
||||
break;
|
||||
case CW_GET_PHYLINK:
|
||||
tmp = wizphy_getphylink();
|
||||
if((int8_t)tmp == -1) return -1;
|
||||
*(uint8_t*)arg = tmp;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
|
||||
{
|
||||
|
||||
switch(cntype)
|
||||
{
|
||||
case CN_SET_NETINFO:
|
||||
wizchip_setnetinfo((wiz_NetInfo*)arg);
|
||||
break;
|
||||
case CN_GET_NETINFO:
|
||||
wizchip_getnetinfo((wiz_NetInfo*)arg);
|
||||
break;
|
||||
case CN_SET_NETMODE:
|
||||
return wizchip_setnetmode(*(netmode_type*)arg);
|
||||
case CN_GET_NETMODE:
|
||||
*(netmode_type*)arg = wizchip_getnetmode();
|
||||
break;
|
||||
case CN_SET_TIMEOUT:
|
||||
wizchip_settimeout((wiz_NetTimeout*)arg);
|
||||
break;
|
||||
case CN_GET_TIMEOUT:
|
||||
wizchip_gettimeout((wiz_NetTimeout*)arg);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wizchip_sw_reset(void)
|
||||
{
|
||||
uint8_t gw[4], sn[4], sip[4];
|
||||
uint8_t mac[6];
|
||||
getSHAR(mac);
|
||||
getGAR(gw); getSUBR(sn); getSIPR(sip);
|
||||
setMR(MR_RST);
|
||||
getMR(); // for delay
|
||||
setSHAR(mac);
|
||||
setGAR(gw);
|
||||
setSUBR(sn);
|
||||
setSIPR(sip);
|
||||
}
|
||||
|
||||
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
|
||||
{
|
||||
int8_t i;
|
||||
int8_t tmp = 0;
|
||||
wizchip_sw_reset();
|
||||
if(txsize)
|
||||
{
|
||||
tmp = 0;
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
tmp += txsize[i];
|
||||
if(tmp > 16) return -1;
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
setSn_TXBUF_SIZE(i, txsize[i]);
|
||||
}
|
||||
if(rxsize)
|
||||
{
|
||||
tmp = 0;
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
tmp += rxsize[i];
|
||||
if(tmp > 16) return -1;
|
||||
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||
setSn_RXBUF_SIZE(i, rxsize[i]);
|
||||
}
|
||||
|
||||
WIZCHIP_EXPORT(socket_reset)();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wizchip_clrinterrupt(intr_kind intr)
|
||||
{
|
||||
uint8_t ir = (uint8_t)intr;
|
||||
uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
|
||||
#if _WIZCHIP_ < 5500
|
||||
ir |= (1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == 5200
|
||||
ir |= (1 << 6);
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < 5200
|
||||
sir &= 0x0F;
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == 5100
|
||||
ir |= sir;
|
||||
setIR(ir);
|
||||
#else
|
||||
setIR(ir);
|
||||
setSIR(sir);
|
||||
#endif
|
||||
}
|
||||
|
||||
intr_kind wizchip_getinterrupt(void)
|
||||
{
|
||||
uint8_t ir = 0;
|
||||
uint8_t sir = 0;
|
||||
uint16_t ret = 0;
|
||||
#if _WIZCHIP_ == 5100
|
||||
ir = getIR();
|
||||
sir = ir 0x0F;
|
||||
#else
|
||||
ir = getIR();
|
||||
sir = getSIR();
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < 5500
|
||||
ir &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == 5200
|
||||
ir &= ~(1 << 6);
|
||||
#endif
|
||||
ret = sir;
|
||||
ret = (ret << 8) + ir;
|
||||
return (intr_kind)ret;
|
||||
}
|
||||
|
||||
void wizchip_setinterruptmask(intr_kind intr)
|
||||
{
|
||||
uint8_t imr = (uint8_t)intr;
|
||||
uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
|
||||
#if _WIZCHIP_ < 5500
|
||||
imr &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == 5200
|
||||
imr &= ~(1 << 6);
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < 5200
|
||||
simr &= 0x0F;
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == 5100
|
||||
imr |= simr;
|
||||
setIMR(imr);
|
||||
#else
|
||||
setIMR(imr);
|
||||
setSIMR(simr);
|
||||
#endif
|
||||
}
|
||||
|
||||
intr_kind wizchip_getinterruptmask(void)
|
||||
{
|
||||
uint8_t imr = 0;
|
||||
uint8_t simr = 0;
|
||||
uint16_t ret = 0;
|
||||
#if _WIZCHIP_ == 5100
|
||||
imr = getIMR();
|
||||
simr = imr 0x0F;
|
||||
#else
|
||||
imr = getIMR();
|
||||
simr = getSIMR();
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ < 5500
|
||||
imr &= ~(1<<4); // IK_WOL
|
||||
#endif
|
||||
#if _WIZCHIP_ == 5200
|
||||
imr &= ~(1 << 6); // IK_DEST_UNREACH
|
||||
#endif
|
||||
ret = simr;
|
||||
ret = (ret << 8) + imr;
|
||||
return (intr_kind)ret;
|
||||
}
|
||||
|
||||
int8_t wizphy_getphylink(void)
|
||||
{
|
||||
int8_t tmp;
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(getPHYSTATUS() & PHYSTATUS_LINK)
|
||||
tmp = PHY_LINK_ON;
|
||||
else
|
||||
tmp = PHY_LINK_OFF;
|
||||
#elif _WIZCHIP_ == 5500
|
||||
if(getPHYCFGR() & PHYCFGR_LNK_ON)
|
||||
tmp = PHY_LINK_ON;
|
||||
else
|
||||
tmp = PHY_LINK_OFF;
|
||||
#else
|
||||
tmp = -1;
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if _WIZCHIP_ > 5100
|
||||
|
||||
int8_t wizphy_getphypmode(void)
|
||||
{
|
||||
int8_t tmp = 0;
|
||||
#if _WIZCHIP_ == 5200
|
||||
if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
|
||||
tmp = PHY_POWER_DOWN;
|
||||
else
|
||||
tmp = PHY_POWER_NORM;
|
||||
#elif _WIZCHIP_ == 5500
|
||||
if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN)
|
||||
tmp = PHY_POWER_DOWN;
|
||||
else
|
||||
tmp = PHY_POWER_NORM;
|
||||
#else
|
||||
tmp = -1;
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
void wizphy_reset(void)
|
||||
{
|
||||
uint8_t tmp = getPHYCFGR();
|
||||
tmp &= PHYCFGR_RST;
|
||||
setPHYCFGR(tmp);
|
||||
tmp = getPHYCFGR();
|
||||
tmp |= ~PHYCFGR_RST;
|
||||
setPHYCFGR(tmp);
|
||||
}
|
||||
|
||||
void wizphy_setphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
if(phyconf->by == PHY_CONFBY_SW)
|
||||
tmp |= PHYCFGR_OPMD;
|
||||
else
|
||||
tmp &= ~PHYCFGR_OPMD;
|
||||
if(phyconf->mode == PHY_MODE_AUTONEGO)
|
||||
tmp |= PHYCFGR_OPMDC_ALLA;
|
||||
else
|
||||
{
|
||||
if(phyconf->duplex == PHY_DUPLEX_FULL)
|
||||
{
|
||||
if(phyconf->speed == PHY_SPEED_100)
|
||||
tmp |= PHYCFGR_OPMDC_100F;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_10F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(phyconf->speed == PHY_SPEED_100)
|
||||
tmp |= PHYCFGR_OPMDC_100H;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_10H;
|
||||
}
|
||||
}
|
||||
setPHYCFGR(tmp);
|
||||
wizphy_reset();
|
||||
}
|
||||
|
||||
void wizphy_getphyconf(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = getPHYCFGR();
|
||||
phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_ALLA:
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
phyconf->mode = PHY_MODE_AUTONEGO;
|
||||
break;
|
||||
default:
|
||||
phyconf->mode = PHY_MODE_MANUAL;
|
||||
break;
|
||||
}
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
case PHYCFGR_OPMDC_100F:
|
||||
case PHYCFGR_OPMDC_100H:
|
||||
phyconf->speed = PHY_SPEED_100;
|
||||
break;
|
||||
default:
|
||||
phyconf->speed = PHY_SPEED_10;
|
||||
break;
|
||||
}
|
||||
switch(tmp & PHYCFGR_OPMDC_ALLA)
|
||||
{
|
||||
case PHYCFGR_OPMDC_100FA:
|
||||
case PHYCFGR_OPMDC_100F:
|
||||
case PHYCFGR_OPMDC_10F:
|
||||
phyconf->duplex = PHY_DUPLEX_FULL;
|
||||
break;
|
||||
default:
|
||||
phyconf->duplex = PHY_DUPLEX_HALF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wizphy_getphystat(wiz_PhyConf* phyconf)
|
||||
{
|
||||
uint8_t tmp = getPHYCFGR();
|
||||
phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
|
||||
phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
|
||||
}
|
||||
|
||||
int8_t wizphy_setphypmode(uint8_t pmode)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = getPHYCFGR();
|
||||
if((tmp & PHYCFGR_OPMD)== 0) return -1;
|
||||
tmp &= ~PHYCFGR_OPMDC_ALLA;
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
tmp |= PHYCFGR_OPMDC_PDOWN;
|
||||
else
|
||||
tmp |= PHYCFGR_OPMDC_ALLA;
|
||||
setPHYCFGR(tmp);
|
||||
wizphy_reset();
|
||||
tmp = getPHYCFGR();
|
||||
if( pmode == PHY_POWER_DOWN)
|
||||
{
|
||||
if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
|
||||
{
|
||||
setSHAR(pnetinfo->mac);
|
||||
setGAR(pnetinfo->gw);
|
||||
setSUBR(pnetinfo->sn);
|
||||
setSIPR(pnetinfo->ip);
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
_SUBN_[0] = pnetinfo->sn[0];
|
||||
_SUBN_[1] = pnetinfo->sn[1];
|
||||
_SUBN_[2] = pnetinfo->sn[2];
|
||||
_SUBN_[3] = pnetinfo->sn[3];
|
||||
#endif
|
||||
_DNS_[0] = pnetinfo->dns[0];
|
||||
_DNS_[1] = pnetinfo->dns[1];
|
||||
_DNS_[2] = pnetinfo->dns[2];
|
||||
_DNS_[3] = pnetinfo->dns[3];
|
||||
_DHCP_ = pnetinfo->dhcp;
|
||||
}
|
||||
|
||||
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
|
||||
{
|
||||
getSHAR(pnetinfo->mac);
|
||||
getGAR(pnetinfo->gw);
|
||||
getSUBR(pnetinfo->sn);
|
||||
getSIPR(pnetinfo->ip);
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
pnetinfo->sn[0] = _SUBN_[0];
|
||||
pnetinfo->sn[1] = _SUBN_[1];
|
||||
pnetinfo->sn[2] = _SUBN_[2];
|
||||
pnetinfo->sn[3] = _SUBN_[3];
|
||||
#endif
|
||||
pnetinfo->dns[0]= _DNS_[0];
|
||||
pnetinfo->dns[1]= _DNS_[1];
|
||||
pnetinfo->dns[2]= _DNS_[2];
|
||||
pnetinfo->dns[3]= _DNS_[3];
|
||||
pnetinfo->dhcp = _DHCP_;
|
||||
}
|
||||
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
uint8_t *wizchip_getsubn(void) {
|
||||
return _SUBN_;
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t wizchip_setnetmode(netmode_type netmode)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
#if _WIZCHIP_ != 5500
|
||||
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
|
||||
#else
|
||||
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
|
||||
#endif
|
||||
tmp = getMR();
|
||||
tmp |= (uint8_t)netmode;
|
||||
setMR(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
netmode_type wizchip_getnetmode(void)
|
||||
{
|
||||
return (netmode_type) getMR();
|
||||
}
|
||||
|
||||
void wizchip_settimeout(wiz_NetTimeout* nettime)
|
||||
{
|
||||
setRCR(nettime->retry_cnt);
|
||||
setRTR(nettime->time_100us);
|
||||
}
|
||||
|
||||
void wizchip_gettimeout(wiz_NetTimeout* nettime)
|
||||
{
|
||||
nettime->retry_cnt = getRCR();
|
||||
nettime->time_100us = getRTR();
|
||||
}
|
|
@ -1,554 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file wizchip_conf.h
|
||||
//! \brief WIZCHIP Config Header File.
|
||||
//! \version 1.0.0
|
||||
//! \date 2013/10/21
|
||||
//! \par Revision history
|
||||
//! <2013/10/21> 1st Release
|
||||
//! \author MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* @defgroup extra_functions 2. WIZnet Extra Functions
|
||||
*
|
||||
* @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.
|
||||
* @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WIZCHIP_CONF_H_
|
||||
#define _WIZCHIP_CONF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* @brief Select WIZCHIP.
|
||||
* @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n
|
||||
* ex> <code> #define \_WIZCHIP_ 5500 </code>
|
||||
*/
|
||||
#ifndef _WIZCHIP_
|
||||
#define _WIZCHIP_ 5200 // 5100, 5200, 5500
|
||||
#endif
|
||||
|
||||
#define _WIZCHIP_IO_MODE_NONE_ 0x0000
|
||||
#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
|
||||
#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */
|
||||
//#define _WIZCHIP_IO_MODE_IIC_ 0x0400
|
||||
//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800
|
||||
// Add to
|
||||
//
|
||||
|
||||
#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */
|
||||
#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
|
||||
|
||||
#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
|
||||
#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
|
||||
|
||||
|
||||
#if (_WIZCHIP_ == 5100)
|
||||
#define _WIZCHIP_ID_ "W5100\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
|
||||
|
||||
#elif (_WIZCHIP_ == 5200)
|
||||
#define _WIZCHIP_ID_ "W5200\0"
|
||||
/**
|
||||
* @brief Define interface mode.
|
||||
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
*/
|
||||
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
|
||||
#include "w5200/w5200.h"
|
||||
#elif (_WIZCHIP_ == 5500)
|
||||
#define _WIZCHIP_ID_ "W5500\0"
|
||||
|
||||
/**
|
||||
* @brief Define interface mode. \n
|
||||
* @todo Should select interface mode as chip.
|
||||
* - @ref \_WIZCHIP_IO_MODE_SPI_ \n
|
||||
* -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
|
||||
* -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_ \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
|
||||
* - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
|
||||
* - Others will be defined in future. \n\n
|
||||
* ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code>
|
||||
*
|
||||
*/
|
||||
//#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_
|
||||
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
|
||||
#include "w5500/w5500.h"
|
||||
#else
|
||||
#error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
|
||||
#endif
|
||||
|
||||
#ifndef _WIZCHIP_IO_MODE_
|
||||
#error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define I/O base address when BUS IF mode.
|
||||
* @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
|
||||
* @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
|
||||
* ex> <code> #define \_WIZCHIP_IO_BASE_ 0x00008000 </code>
|
||||
*/
|
||||
#define _WIZCHIP_IO_BASE_ 0x00000000 //
|
||||
|
||||
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
|
||||
#ifndef _WIZCHIP_IO_BASE_
|
||||
#error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ > 5100
|
||||
#define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP
|
||||
#else
|
||||
#define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************
|
||||
* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
|
||||
*********************************************************/
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
|
||||
*/
|
||||
typedef struct __WIZCHIP
|
||||
{
|
||||
uint16_t if_mode; ///< host interface mode
|
||||
uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on.
|
||||
/**
|
||||
* The set of critical section callback func.
|
||||
*/
|
||||
struct _CRIS
|
||||
{
|
||||
void (*_enter) (void); ///< crtical section enter
|
||||
void (*_exit) (void); ///< critial section exit
|
||||
}CRIS;
|
||||
/**
|
||||
* The set of @ref\_WIZCHIP_ select control callback func.
|
||||
*/
|
||||
struct _CS
|
||||
{
|
||||
void (*_select) (void); ///< @ref \_WIZCHIP_ selected
|
||||
void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected
|
||||
}CS;
|
||||
/**
|
||||
* The set of interface IO callback func.
|
||||
*/
|
||||
union _IF
|
||||
{
|
||||
/**
|
||||
* For BUS interface IO
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint8_t (*_read_byte) (uint32_t AddrSel);
|
||||
void (*_write_byte) (uint32_t AddrSel, uint8_t wb);
|
||||
}BUS;
|
||||
/**
|
||||
* For SPI interface IO
|
||||
*/
|
||||
struct
|
||||
{
|
||||
void (*_read_bytes) (uint8_t *buf, uint32_t len);
|
||||
void (*_write_bytes) (const uint8_t *buf, uint32_t len);
|
||||
}SPI;
|
||||
// To be added
|
||||
//
|
||||
}IF;
|
||||
}_WIZCHIP;
|
||||
|
||||
extern _WIZCHIP WIZCHIP;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* WIZCHIP control type enumration used in @ref ctlwizchip().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly
|
||||
CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
|
||||
CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP
|
||||
CW_CLR_INTERRUPT, ///< Clears interrupt
|
||||
CW_SET_INTRMASK, ///< Masks interrupt
|
||||
CW_GET_INTRMASK, ///< Get interrupt mask
|
||||
CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt.
|
||||
CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt.
|
||||
CW_GET_ID, ///< Gets WIZCHIP name.
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000
|
||||
CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
|
||||
CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000
|
||||
CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000
|
||||
CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000
|
||||
#endif
|
||||
CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal
|
||||
CW_GET_PHYLINK ///< Get PHY Link status
|
||||
}ctlwizchip_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network control type enumration used in @ref ctlnetwork().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo
|
||||
CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo
|
||||
CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
|
||||
CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
|
||||
CN_SET_TIMEOUT, ///< Set network timeout as retry count and time.
|
||||
CN_GET_TIMEOUT, ///< Get network timeout as retry count and time.
|
||||
}ctlnetwork_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
|
||||
* and CW_GET_INTRMASK is used in @ref ctlnetwork().
|
||||
* It can be used with OR operation.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
#if _WIZCHIP_ > 5200
|
||||
IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500.
|
||||
#endif
|
||||
|
||||
IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected
|
||||
|
||||
#if _WIZCHIP_ != 5200
|
||||
IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200
|
||||
#endif
|
||||
|
||||
IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred
|
||||
|
||||
IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt
|
||||
IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt
|
||||
IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt
|
||||
IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt
|
||||
#if _WIZCHIP_ > 5100
|
||||
IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100
|
||||
IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100
|
||||
IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100
|
||||
IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ > 5100
|
||||
IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt
|
||||
#else
|
||||
IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt
|
||||
#endif
|
||||
}intr_kind;
|
||||
|
||||
#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin
|
||||
#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register
|
||||
#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting.
|
||||
#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation
|
||||
#define PHY_SPEED_10 0 ///< Link Speed 10
|
||||
#define PHY_SPEED_100 1 ///< Link Speed 100
|
||||
#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex
|
||||
#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex
|
||||
#define PHY_LINK_OFF 0 ///< Link Off
|
||||
#define PHY_LINK_ON 1 ///< Link On
|
||||
#define PHY_POWER_NORM 0 ///< PHY power normal mode
|
||||
#define PHY_POWER_DOWN 1 ///< PHY power down mode
|
||||
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,
|
||||
* and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
|
||||
* Valid only in W5500.
|
||||
*/
|
||||
typedef struct wiz_PhyConf_t
|
||||
{
|
||||
uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
|
||||
uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
|
||||
uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
|
||||
uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL
|
||||
//uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
|
||||
//uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF
|
||||
}wiz_PhyConf;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* It used in setting dhcp_mode of @ref wiz_NetInfo.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NETINFO_STATIC = 1, ///< Static IP configuration by manually.
|
||||
NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever
|
||||
}dhcp_mode;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network Information for WIZCHIP
|
||||
*/
|
||||
typedef struct wiz_NetInfo_t
|
||||
{
|
||||
uint8_t mac[6]; ///< Source Mac Address
|
||||
uint8_t ip[4]; ///< Source IP Address
|
||||
uint8_t sn[4]; ///< Subnet Mask
|
||||
uint8_t gw[4]; ///< Gateway IP Address
|
||||
uint8_t dns[4]; ///< DNS server IP Address
|
||||
dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP
|
||||
}wiz_NetInfo;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Network mode
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
#if _WIZCHIP_ == 5500
|
||||
NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500
|
||||
#endif
|
||||
NM_WAKEONLAN = (1<<5), ///< Wake On Lan
|
||||
NM_PINGBLOCK = (1<<4), ///< Block ping-request
|
||||
NM_PPPOE = (1<<3), ///< PPPoE mode
|
||||
}netmode_type;
|
||||
|
||||
/**
|
||||
* @ingroup DATA_TYPE
|
||||
* Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
|
||||
*/
|
||||
typedef struct wiz_NetTimeout_t
|
||||
{
|
||||
uint8_t retry_cnt; ///< retry count
|
||||
uint16_t time_100us; ///< time unit 100us
|
||||
}wiz_NetTimeout;
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for critical section of I/O functions such as
|
||||
*\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
|
||||
*@param cris_en : callback function for critical section enter.
|
||||
*@param cris_ex : callback function for critical section exit.
|
||||
*@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
|
||||
*@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
|
||||
*/
|
||||
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
|
||||
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for WIZCHIP select & deselect.
|
||||
*@param cs_sel : callback function for WIZCHIP select
|
||||
*@param cs_desel : callback fucntion for WIZCHIP deselect
|
||||
*@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for bus interface.
|
||||
*@param bus_rb : callback function to read byte data using system bus
|
||||
*@param bus_wb : callback function to write byte data using system bus
|
||||
*@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
|
||||
*or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
|
||||
|
||||
/**
|
||||
*@brief Registers call back function for SPI interface.
|
||||
*@param spi_rb : callback function to read byte usig SPI
|
||||
*@param spi_wb : callback function to write byte usig SPI
|
||||
*@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
|
||||
*or register your functions.
|
||||
*@note If you do not describe or register, null function is called.
|
||||
*/
|
||||
void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t));
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Controls to the WIZCHIP.
|
||||
* @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
|
||||
* controls interrupt & mask and so on.
|
||||
* @param cwtype : Decides to the control type
|
||||
* @param arg : arg type is dependent on cwtype.
|
||||
* @return 0 : Success \n
|
||||
* -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP
|
||||
*/
|
||||
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Controls to network.
|
||||
* @details Controls to network environment, mode, timeout and so on.
|
||||
* @param cntype : Input. Decides to the control type
|
||||
* @param arg : Inout. arg type is dependent on cntype.
|
||||
* @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
|
||||
* 0 : Success
|
||||
*/
|
||||
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are implemented for internal use.
|
||||
* but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Reset WIZCHIP by softly.
|
||||
*/
|
||||
void wizchip_sw_reset(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Initializes WIZCHIP with socket buffer size
|
||||
* @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
|
||||
* @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
|
||||
* @return 0 : succcess \n
|
||||
* -1 : fail. Invalid buffer size
|
||||
*/
|
||||
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Clear Interrupt of WIZCHIP.
|
||||
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
void wizchip_clrinterrupt(intr_kind intr);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get Interrupt of WIZCHIP.
|
||||
* @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
intr_kind wizchip_getinterrupt(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Mask or Unmask Interrupt of WIZCHIP.
|
||||
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
|
||||
*/
|
||||
void wizchip_setinterruptmask(intr_kind intr);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get Interrupt mask of WIZCHIP.
|
||||
* @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
|
||||
*/
|
||||
intr_kind wizchip_getinterruptmask(void);
|
||||
|
||||
#if _WIZCHIP_ > 5100
|
||||
int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100
|
||||
int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100
|
||||
#endif
|
||||
|
||||
#if _WIZCHIP_ == 5500
|
||||
void wizphy_reset(void); ///< Reset phy. Vailid only in W5500
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the phy information for WIZCHIP without power mode
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_setphyconf(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get phy configuration information.
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_getphyconf(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get phy status.
|
||||
* @param phyconf : @ref wiz_PhyConf
|
||||
*/
|
||||
void wizphy_getphystat(wiz_PhyConf* phyconf);
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
|
||||
* @param pmode Settig value of power down mode.
|
||||
*/
|
||||
int8_t wizphy_setphypmode(uint8_t pmode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the network information for WIZCHIP
|
||||
* @param pnetinfo : @ref wizNetInfo
|
||||
*/
|
||||
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get the network information for WIZCHIP
|
||||
* @param pnetinfo : @ref wizNetInfo
|
||||
*/
|
||||
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
|
||||
|
||||
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
|
||||
uint8_t *wizchip_getsubn(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set the network mode such WOL, PPPoE, Ping Block, and etc.
|
||||
* @param pnetinfo Value of network mode. Refer to @ref netmode_type.
|
||||
*/
|
||||
int8_t wizchip_setnetmode(netmode_type netmode);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get the network mode such WOL, PPPoE, Ping Block, and etc.
|
||||
* @return Value of network mode. Refer to @ref netmode_type.
|
||||
*/
|
||||
netmode_type wizchip_getnetmode(void);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Set retry time value(@ref RTR) and retry count(@ref RCR).
|
||||
* @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
|
||||
* @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
|
||||
*/
|
||||
void wizchip_settimeout(wiz_NetTimeout* nettime);
|
||||
|
||||
/**
|
||||
* @ingroup extra_functions
|
||||
* @brief Get retry time value(@ref RTR) and retry count(@ref RCR).
|
||||
* @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
|
||||
* @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
|
||||
*/
|
||||
void wizchip_gettimeout(wiz_NetTimeout* nettime);
|
||||
|
||||
#endif // _WIZCHIP_CONF_H_
|
|
@ -1,975 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file dhcp.c
|
||||
//! \brief DHCP APIs implement file.
|
||||
//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
|
||||
//! \version 1.1.0
|
||||
//! \date 2013/11/18
|
||||
//! \par Revision history
|
||||
//! <2018/10/09> Modified by Nick Moore for CircuitPython
|
||||
//! <2013/11/18> 1st Release
|
||||
//! <2012/12/20> V1.1.0
|
||||
//! 1. Optimize code
|
||||
//! 2. Add reg_dhcp_cbfunc()
|
||||
//! 3. Add DHCP_stop()
|
||||
//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
|
||||
//! 5. Don't care system endian
|
||||
//! 6. Add comments
|
||||
//! <2012/12/26> V1.1.1
|
||||
//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
|
||||
//! \author Eric Jung & MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//#include "Ethernet/socket.h"
|
||||
//#include "Internet/DHCP/dhcp.h"
|
||||
#include "../../ethernet/socket.h"
|
||||
#include "dhcp.h"
|
||||
|
||||
/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* DHCP state machine. */
|
||||
#define STATE_DHCP_INIT 0 ///< Initialize
|
||||
#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
|
||||
#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
|
||||
#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
|
||||
#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
|
||||
#define STATE_DHCP_RELEASE 5 ///< No use
|
||||
#define STATE_DHCP_STOP 6 ///< Stop processing DHCP
|
||||
|
||||
#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
|
||||
#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG
|
||||
|
||||
/* DHCP message OP code */
|
||||
#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
|
||||
#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
|
||||
|
||||
/* DHCP message type */
|
||||
#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
|
||||
#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
|
||||
#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
|
||||
#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
|
||||
#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
|
||||
#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
|
||||
#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
|
||||
#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
|
||||
|
||||
#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
|
||||
#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
|
||||
|
||||
#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
|
||||
#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
|
||||
#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
|
||||
|
||||
#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
|
||||
|
||||
#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
|
||||
#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG
|
||||
|
||||
/*
|
||||
* @brief DHCP option and value (cf. RFC1533)
|
||||
*/
|
||||
enum
|
||||
{
|
||||
padOption = 0,
|
||||
subnetMask = 1,
|
||||
timerOffset = 2,
|
||||
routersOnSubnet = 3,
|
||||
timeServer = 4,
|
||||
nameServer = 5,
|
||||
dns = 6,
|
||||
logServer = 7,
|
||||
cookieServer = 8,
|
||||
lprServer = 9,
|
||||
impressServer = 10,
|
||||
resourceLocationServer = 11,
|
||||
hostName = 12,
|
||||
bootFileSize = 13,
|
||||
meritDumpFile = 14,
|
||||
domainName = 15,
|
||||
swapServer = 16,
|
||||
rootPath = 17,
|
||||
extentionsPath = 18,
|
||||
IPforwarding = 19,
|
||||
nonLocalSourceRouting = 20,
|
||||
policyFilter = 21,
|
||||
maxDgramReasmSize = 22,
|
||||
defaultIPTTL = 23,
|
||||
pathMTUagingTimeout = 24,
|
||||
pathMTUplateauTable = 25,
|
||||
ifMTU = 26,
|
||||
allSubnetsLocal = 27,
|
||||
broadcastAddr = 28,
|
||||
performMaskDiscovery = 29,
|
||||
maskSupplier = 30,
|
||||
performRouterDiscovery = 31,
|
||||
routerSolicitationAddr = 32,
|
||||
staticRoute = 33,
|
||||
trailerEncapsulation = 34,
|
||||
arpCacheTimeout = 35,
|
||||
ethernetEncapsulation = 36,
|
||||
tcpDefaultTTL = 37,
|
||||
tcpKeepaliveInterval = 38,
|
||||
tcpKeepaliveGarbage = 39,
|
||||
nisDomainName = 40,
|
||||
nisServers = 41,
|
||||
ntpServers = 42,
|
||||
vendorSpecificInfo = 43,
|
||||
netBIOSnameServer = 44,
|
||||
netBIOSdgramDistServer = 45,
|
||||
netBIOSnodeType = 46,
|
||||
netBIOSscope = 47,
|
||||
xFontServer = 48,
|
||||
xDisplayManager = 49,
|
||||
dhcpRequestedIPaddr = 50,
|
||||
dhcpIPaddrLeaseTime = 51,
|
||||
dhcpOptionOverload = 52,
|
||||
dhcpMessageType = 53,
|
||||
dhcpServerIdentifier = 54,
|
||||
dhcpParamRequest = 55,
|
||||
dhcpMsg = 56,
|
||||
dhcpMaxMsgSize = 57,
|
||||
dhcpT1value = 58,
|
||||
dhcpT2value = 59,
|
||||
dhcpClassIdentifier = 60,
|
||||
dhcpClientIdentifier = 61,
|
||||
endOption = 255
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief DHCP message format
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
|
||||
uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
|
||||
uint8_t hlen; ///< @ref DHCP_HLENETHERNET
|
||||
uint8_t hops; ///< @ref DHCP_HOPS
|
||||
uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
|
||||
uint16_t secs; ///< @ref DHCP_SECS
|
||||
uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
|
||||
uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
|
||||
uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
|
||||
uint8_t siaddr[4]; ///< No use
|
||||
uint8_t giaddr[4]; ///< No use
|
||||
uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
|
||||
uint8_t sname[64]; ///< No use
|
||||
uint8_t file[128]; ///< No use
|
||||
uint8_t OPT[OPT_SIZE]; ///< Option
|
||||
} RIP_MSG;
|
||||
|
||||
|
||||
|
||||
uint8_t DHCP_SOCKET; // Socket number for DHCP
|
||||
|
||||
uint8_t DHCP_SIP[4]; // DHCP Server IP address
|
||||
|
||||
// Network information from DHCP Server
|
||||
uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address
|
||||
uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP
|
||||
uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP
|
||||
uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP
|
||||
uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP
|
||||
|
||||
|
||||
int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
|
||||
int8_t dhcp_retry_count = 0;
|
||||
|
||||
uint32_t dhcp_lease_time = INFINITE_LEASETIME;
|
||||
volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
|
||||
uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
|
||||
|
||||
uint32_t DHCP_XID; // Any number
|
||||
|
||||
RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
|
||||
|
||||
uint8_t HOST_NAME[] = DCHP_HOST_NAME;
|
||||
|
||||
uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
|
||||
|
||||
/* The default callback function */
|
||||
void default_ip_assign(void);
|
||||
void default_ip_update(void);
|
||||
void default_ip_conflict(void);
|
||||
|
||||
/* Callback handler */
|
||||
void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
|
||||
void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
|
||||
void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
|
||||
|
||||
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
|
||||
|
||||
|
||||
/* send DISCOVER message to DHCP server */
|
||||
void send_DHCP_DISCOVER(void);
|
||||
|
||||
/* send REQEUST message to DHCP server */
|
||||
void send_DHCP_REQUEST(void);
|
||||
|
||||
/* send DECLINE message to DHCP server */
|
||||
void send_DHCP_DECLINE(void);
|
||||
|
||||
/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
|
||||
int8_t check_DHCP_leasedIP(void);
|
||||
|
||||
/* check the timeout in DHCP process */
|
||||
uint8_t check_DHCP_timeout(void);
|
||||
|
||||
/* Intialize to timeout process. */
|
||||
void reset_DHCP_timeout(void);
|
||||
|
||||
/* Parse message as OFFER and ACK and NACK from DHCP server.*/
|
||||
int8_t parseDHCPCMSG(void);
|
||||
|
||||
/* The default handler of ip assign first */
|
||||
void default_ip_assign(void)
|
||||
{
|
||||
setSIPR(DHCP_allocated_ip);
|
||||
setSUBR(DHCP_allocated_sn);
|
||||
setGAR (DHCP_allocated_gw);
|
||||
}
|
||||
|
||||
/* The default handler of ip changed */
|
||||
void default_ip_update(void)
|
||||
{
|
||||
/* WIZchip Software Reset */
|
||||
setMR(MR_RST);
|
||||
getMR(); // for delay
|
||||
default_ip_assign();
|
||||
setSHAR(DHCP_CHADDR);
|
||||
}
|
||||
|
||||
/* The default handler of ip changed */
|
||||
void default_ip_conflict(void)
|
||||
{
|
||||
// WIZchip Software Reset
|
||||
setMR(MR_RST);
|
||||
getMR(); // for delay
|
||||
setSHAR(DHCP_CHADDR);
|
||||
}
|
||||
|
||||
/* register the call back func. */
|
||||
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
|
||||
{
|
||||
dhcp_ip_assign = default_ip_assign;
|
||||
dhcp_ip_update = default_ip_update;
|
||||
dhcp_ip_conflict = default_ip_conflict;
|
||||
if(ip_assign) dhcp_ip_assign = ip_assign;
|
||||
if(ip_update) dhcp_ip_update = ip_update;
|
||||
if(ip_conflict) dhcp_ip_conflict = ip_conflict;
|
||||
}
|
||||
|
||||
/* make the common DHCP message */
|
||||
void makeDHCPMSG(void)
|
||||
{
|
||||
uint8_t bk_mac[6];
|
||||
uint8_t* ptmp;
|
||||
uint8_t i;
|
||||
getSHAR(bk_mac);
|
||||
pDHCPMSG->op = DHCP_BOOTREQUEST;
|
||||
pDHCPMSG->htype = DHCP_HTYPE10MB;
|
||||
pDHCPMSG->hlen = DHCP_HLENETHERNET;
|
||||
pDHCPMSG->hops = DHCP_HOPS;
|
||||
ptmp = (uint8_t*)(&pDHCPMSG->xid);
|
||||
*(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
|
||||
*(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
|
||||
*(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
|
||||
*(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
|
||||
pDHCPMSG->secs = DHCP_SECS;
|
||||
ptmp = (uint8_t*)(&pDHCPMSG->flags);
|
||||
*(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
|
||||
*(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
|
||||
|
||||
pDHCPMSG->ciaddr[0] = 0;
|
||||
pDHCPMSG->ciaddr[1] = 0;
|
||||
pDHCPMSG->ciaddr[2] = 0;
|
||||
pDHCPMSG->ciaddr[3] = 0;
|
||||
|
||||
pDHCPMSG->yiaddr[0] = 0;
|
||||
pDHCPMSG->yiaddr[1] = 0;
|
||||
pDHCPMSG->yiaddr[2] = 0;
|
||||
pDHCPMSG->yiaddr[3] = 0;
|
||||
|
||||
pDHCPMSG->siaddr[0] = 0;
|
||||
pDHCPMSG->siaddr[1] = 0;
|
||||
pDHCPMSG->siaddr[2] = 0;
|
||||
pDHCPMSG->siaddr[3] = 0;
|
||||
|
||||
pDHCPMSG->giaddr[0] = 0;
|
||||
pDHCPMSG->giaddr[1] = 0;
|
||||
pDHCPMSG->giaddr[2] = 0;
|
||||
pDHCPMSG->giaddr[3] = 0;
|
||||
|
||||
pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
|
||||
pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
|
||||
pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
|
||||
pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
|
||||
|
||||
for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
|
||||
for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
|
||||
for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
|
||||
|
||||
// MAGIC_COOKIE
|
||||
pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
|
||||
pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
|
||||
pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
|
||||
pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
|
||||
}
|
||||
|
||||
/* SEND DHCP DISCOVER */
|
||||
void send_DHCP_DISCOVER(void)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t ip[4];
|
||||
uint16_t k = 0;
|
||||
|
||||
makeDHCPMSG();
|
||||
|
||||
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
|
||||
|
||||
// Option Request Param
|
||||
pDHCPMSG->OPT[k++] = dhcpMessageType;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
|
||||
|
||||
// Client identifier
|
||||
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
|
||||
pDHCPMSG->OPT[k++] = 0x07;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
|
||||
|
||||
// host name
|
||||
pDHCPMSG->OPT[k++] = hostName;
|
||||
pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
|
||||
for(i = 0 ; HOST_NAME[i] != 0; i++)
|
||||
pDHCPMSG->OPT[k++] = HOST_NAME[i];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
|
||||
pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpParamRequest;
|
||||
pDHCPMSG->OPT[k++] = 0x06; // length of request
|
||||
pDHCPMSG->OPT[k++] = subnetMask;
|
||||
pDHCPMSG->OPT[k++] = routersOnSubnet;
|
||||
pDHCPMSG->OPT[k++] = dns;
|
||||
pDHCPMSG->OPT[k++] = domainName;
|
||||
pDHCPMSG->OPT[k++] = dhcpT1value;
|
||||
pDHCPMSG->OPT[k++] = dhcpT2value;
|
||||
pDHCPMSG->OPT[k++] = endOption;
|
||||
|
||||
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
|
||||
|
||||
// send broadcasting packet
|
||||
ip[0] = 255;
|
||||
ip[1] = 255;
|
||||
ip[2] = 255;
|
||||
ip[3] = 255;
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Send DHCP_DISCOVER\r\n");
|
||||
#endif
|
||||
|
||||
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
|
||||
}
|
||||
|
||||
/* SEND DHCP REQUEST */
|
||||
void send_DHCP_REQUEST(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t ip[4];
|
||||
uint16_t k = 0;
|
||||
|
||||
makeDHCPMSG();
|
||||
|
||||
if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
|
||||
{
|
||||
*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
|
||||
*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
|
||||
pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
|
||||
pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
|
||||
pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
|
||||
pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
|
||||
ip[0] = DHCP_SIP[0];
|
||||
ip[1] = DHCP_SIP[1];
|
||||
ip[2] = DHCP_SIP[2];
|
||||
ip[3] = DHCP_SIP[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
ip[0] = 255;
|
||||
ip[1] = 255;
|
||||
ip[2] = 255;
|
||||
ip[3] = 255;
|
||||
}
|
||||
|
||||
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
|
||||
|
||||
// Option Request Param.
|
||||
pDHCPMSG->OPT[k++] = dhcpMessageType;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_REQUEST;
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
|
||||
pDHCPMSG->OPT[k++] = 0x07;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
|
||||
|
||||
if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
|
||||
{
|
||||
pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
|
||||
pDHCPMSG->OPT[k++] = 0x04;
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
|
||||
pDHCPMSG->OPT[k++] = 0x04;
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[3];
|
||||
}
|
||||
|
||||
// host name
|
||||
pDHCPMSG->OPT[k++] = hostName;
|
||||
pDHCPMSG->OPT[k++] = 0; // length of hostname
|
||||
for(i = 0 ; HOST_NAME[i] != 0; i++)
|
||||
pDHCPMSG->OPT[k++] = HOST_NAME[i];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
|
||||
pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpParamRequest;
|
||||
pDHCPMSG->OPT[k++] = 0x08;
|
||||
pDHCPMSG->OPT[k++] = subnetMask;
|
||||
pDHCPMSG->OPT[k++] = routersOnSubnet;
|
||||
pDHCPMSG->OPT[k++] = dns;
|
||||
pDHCPMSG->OPT[k++] = domainName;
|
||||
pDHCPMSG->OPT[k++] = dhcpT1value;
|
||||
pDHCPMSG->OPT[k++] = dhcpT2value;
|
||||
pDHCPMSG->OPT[k++] = performRouterDiscovery;
|
||||
pDHCPMSG->OPT[k++] = staticRoute;
|
||||
pDHCPMSG->OPT[k++] = endOption;
|
||||
|
||||
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Send DHCP_REQUEST\r\n");
|
||||
#endif
|
||||
|
||||
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
|
||||
|
||||
}
|
||||
|
||||
/* SEND DHCP DHCPDECLINE */
|
||||
void send_DHCP_DECLINE(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t ip[4];
|
||||
uint16_t k = 0;
|
||||
|
||||
makeDHCPMSG();
|
||||
|
||||
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
|
||||
|
||||
*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
|
||||
*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
|
||||
|
||||
// Option Request Param.
|
||||
pDHCPMSG->OPT[k++] = dhcpMessageType;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_DECLINE;
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
|
||||
pDHCPMSG->OPT[k++] = 0x07;
|
||||
pDHCPMSG->OPT[k++] = 0x01;
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
|
||||
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
|
||||
pDHCPMSG->OPT[k++] = 0x04;
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
|
||||
|
||||
pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
|
||||
pDHCPMSG->OPT[k++] = 0x04;
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[0];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[1];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[2];
|
||||
pDHCPMSG->OPT[k++] = DHCP_SIP[3];
|
||||
|
||||
pDHCPMSG->OPT[k++] = endOption;
|
||||
|
||||
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
|
||||
|
||||
//send broadcasting packet
|
||||
ip[0] = 0xFF;
|
||||
ip[1] = 0xFF;
|
||||
ip[2] = 0xFF;
|
||||
ip[3] = 0xFF;
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("\r\n> Send DHCP_DECLINE\r\n");
|
||||
#endif
|
||||
|
||||
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
|
||||
}
|
||||
|
||||
/* PARSE REPLY pDHCPMSG */
|
||||
int8_t parseDHCPMSG(void)
|
||||
{
|
||||
uint8_t svr_addr[6];
|
||||
uint16_t svr_port;
|
||||
uint16_t len;
|
||||
|
||||
uint8_t * p;
|
||||
uint8_t * e;
|
||||
uint8_t type = 0;
|
||||
uint8_t opt_len;
|
||||
|
||||
if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
|
||||
{
|
||||
len = WIZCHIP_EXPORT(recvfrom)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
|
||||
#endif
|
||||
}
|
||||
else return 0;
|
||||
if (svr_port == DHCP_SERVER_PORT) {
|
||||
// compare mac address
|
||||
if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
|
||||
(pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
|
||||
(pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
|
||||
return 0;
|
||||
type = 0;
|
||||
p = (uint8_t *)(&pDHCPMSG->op);
|
||||
p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
|
||||
e = p + (len - 240);
|
||||
|
||||
while ( p < e ) {
|
||||
|
||||
switch ( *p ) {
|
||||
|
||||
case endOption :
|
||||
p = e; // for break while(p < e)
|
||||
break;
|
||||
case padOption :
|
||||
p++;
|
||||
break;
|
||||
case dhcpMessageType :
|
||||
p++;
|
||||
p++;
|
||||
type = *p++;
|
||||
break;
|
||||
case subnetMask :
|
||||
p++;
|
||||
p++;
|
||||
DHCP_allocated_sn[0] = *p++;
|
||||
DHCP_allocated_sn[1] = *p++;
|
||||
DHCP_allocated_sn[2] = *p++;
|
||||
DHCP_allocated_sn[3] = *p++;
|
||||
break;
|
||||
case routersOnSubnet :
|
||||
p++;
|
||||
opt_len = *p++;
|
||||
DHCP_allocated_gw[0] = *p++;
|
||||
DHCP_allocated_gw[1] = *p++;
|
||||
DHCP_allocated_gw[2] = *p++;
|
||||
DHCP_allocated_gw[3] = *p++;
|
||||
p = p + (opt_len - 4);
|
||||
break;
|
||||
case dns :
|
||||
p++;
|
||||
opt_len = *p++;
|
||||
DHCP_allocated_dns[0] = *p++;
|
||||
DHCP_allocated_dns[1] = *p++;
|
||||
DHCP_allocated_dns[2] = *p++;
|
||||
DHCP_allocated_dns[3] = *p++;
|
||||
p = p + (opt_len - 4);
|
||||
break;
|
||||
case dhcpIPaddrLeaseTime :
|
||||
p++;
|
||||
opt_len = *p++;
|
||||
dhcp_lease_time = *p++;
|
||||
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
|
||||
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
|
||||
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
|
||||
#ifdef _DHCP_DEBUG_
|
||||
dhcp_lease_time = 10;
|
||||
#endif
|
||||
break;
|
||||
case dhcpServerIdentifier :
|
||||
p++;
|
||||
opt_len = *p++;
|
||||
DHCP_SIP[0] = *p++;
|
||||
DHCP_SIP[1] = *p++;
|
||||
DHCP_SIP[2] = *p++;
|
||||
DHCP_SIP[3] = *p++;
|
||||
break;
|
||||
default :
|
||||
p++;
|
||||
opt_len = *p++;
|
||||
p += opt_len;
|
||||
break;
|
||||
} // switch
|
||||
} // while
|
||||
} // if
|
||||
return type;
|
||||
}
|
||||
|
||||
uint8_t DHCP_run(void)
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t ret;
|
||||
|
||||
if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
|
||||
|
||||
if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
|
||||
WIZCHIP_EXPORT(socket)(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
|
||||
|
||||
ret = DHCP_RUNNING;
|
||||
type = parseDHCPMSG();
|
||||
|
||||
switch ( dhcp_state ) {
|
||||
case STATE_DHCP_INIT :
|
||||
DHCP_allocated_ip[0] = 0;
|
||||
DHCP_allocated_ip[1] = 0;
|
||||
DHCP_allocated_ip[2] = 0;
|
||||
DHCP_allocated_ip[3] = 0;
|
||||
send_DHCP_DISCOVER();
|
||||
dhcp_state = STATE_DHCP_DISCOVER;
|
||||
break;
|
||||
case STATE_DHCP_DISCOVER :
|
||||
if (type == DHCP_OFFER){
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Receive DHCP_OFFER\r\n");
|
||||
#endif
|
||||
DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
|
||||
DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
|
||||
DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
|
||||
DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
|
||||
|
||||
send_DHCP_REQUEST();
|
||||
dhcp_state = STATE_DHCP_REQUEST;
|
||||
} else ret = check_DHCP_timeout();
|
||||
break;
|
||||
|
||||
case STATE_DHCP_REQUEST :
|
||||
if (type == DHCP_ACK) {
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Receive DHCP_ACK\r\n");
|
||||
#endif
|
||||
if (check_DHCP_leasedIP()) {
|
||||
// Network info assignment from DHCP
|
||||
dhcp_ip_assign();
|
||||
reset_DHCP_timeout();
|
||||
|
||||
dhcp_state = STATE_DHCP_LEASED;
|
||||
} else {
|
||||
// IP address conflict occurred
|
||||
reset_DHCP_timeout();
|
||||
dhcp_ip_conflict();
|
||||
dhcp_state = STATE_DHCP_INIT;
|
||||
}
|
||||
} else if (type == DHCP_NAK) {
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Receive DHCP_NACK\r\n");
|
||||
#endif
|
||||
|
||||
reset_DHCP_timeout();
|
||||
|
||||
dhcp_state = STATE_DHCP_DISCOVER;
|
||||
} else ret = check_DHCP_timeout();
|
||||
break;
|
||||
|
||||
case STATE_DHCP_LEASED :
|
||||
ret = DHCP_IP_LEASED;
|
||||
if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Maintains the IP address \r\n");
|
||||
#endif
|
||||
|
||||
type = 0;
|
||||
OLD_allocated_ip[0] = DHCP_allocated_ip[0];
|
||||
OLD_allocated_ip[1] = DHCP_allocated_ip[1];
|
||||
OLD_allocated_ip[2] = DHCP_allocated_ip[2];
|
||||
OLD_allocated_ip[3] = DHCP_allocated_ip[3];
|
||||
|
||||
DHCP_XID++;
|
||||
|
||||
send_DHCP_REQUEST();
|
||||
|
||||
reset_DHCP_timeout();
|
||||
|
||||
dhcp_state = STATE_DHCP_REREQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_DHCP_REREQUEST :
|
||||
ret = DHCP_IP_LEASED;
|
||||
if (type == DHCP_ACK) {
|
||||
dhcp_retry_count = 0;
|
||||
if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
|
||||
OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
|
||||
OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
|
||||
OLD_allocated_ip[3] != DHCP_allocated_ip[3])
|
||||
{
|
||||
ret = DHCP_IP_CHANGED;
|
||||
dhcp_ip_update();
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf(">IP changed.\r\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
#ifdef _DHCP_DEBUG_
|
||||
else printf(">IP is continued.\r\n");
|
||||
#endif
|
||||
reset_DHCP_timeout();
|
||||
dhcp_state = STATE_DHCP_LEASED;
|
||||
} else if (type == DHCP_NAK) {
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
|
||||
#endif
|
||||
|
||||
reset_DHCP_timeout();
|
||||
|
||||
dhcp_state = STATE_DHCP_DISCOVER;
|
||||
} else ret = check_DHCP_timeout();
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DHCP_stop(void)
|
||||
{
|
||||
WIZCHIP_EXPORT(close)(DHCP_SOCKET);
|
||||
dhcp_state = STATE_DHCP_STOP;
|
||||
}
|
||||
|
||||
uint8_t check_DHCP_timeout(void)
|
||||
{
|
||||
uint8_t ret = DHCP_RUNNING;
|
||||
|
||||
if (dhcp_retry_count < MAX_DHCP_RETRY) {
|
||||
if (dhcp_tick_next < dhcp_tick_1s) {
|
||||
|
||||
switch ( dhcp_state ) {
|
||||
case STATE_DHCP_DISCOVER :
|
||||
// printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
|
||||
send_DHCP_DISCOVER();
|
||||
break;
|
||||
|
||||
case STATE_DHCP_REQUEST :
|
||||
// printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
|
||||
|
||||
send_DHCP_REQUEST();
|
||||
break;
|
||||
|
||||
case STATE_DHCP_REREQUEST :
|
||||
// printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
|
||||
|
||||
send_DHCP_REQUEST();
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
dhcp_tick_1s = 0;
|
||||
dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
|
||||
dhcp_retry_count++;
|
||||
}
|
||||
} else { // timeout occurred
|
||||
|
||||
switch(dhcp_state) {
|
||||
case STATE_DHCP_DISCOVER:
|
||||
dhcp_state = STATE_DHCP_INIT;
|
||||
ret = DHCP_FAILED;
|
||||
break;
|
||||
case STATE_DHCP_REQUEST:
|
||||
case STATE_DHCP_REREQUEST:
|
||||
send_DHCP_DISCOVER();
|
||||
dhcp_state = STATE_DHCP_DISCOVER;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
reset_DHCP_timeout();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t check_DHCP_leasedIP(void)
|
||||
{
|
||||
uint8_t tmp;
|
||||
int32_t ret;
|
||||
|
||||
//WIZchip RCR value changed for ARP Timeout count control
|
||||
tmp = getRCR();
|
||||
setRCR(0x03);
|
||||
|
||||
// IP conflict detection : ARP request - ARP reply
|
||||
// Broadcasting ARP Request for check the IP conflict using UDP sendto() function
|
||||
ret = WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
|
||||
|
||||
// RCR value restore
|
||||
setRCR(tmp);
|
||||
|
||||
if(ret == SOCKERR_TIMEOUT) {
|
||||
// UDP send Timeout occurred : allocated IP address is unique, DHCP Success
|
||||
|
||||
#ifdef _DHCP_DEBUG_
|
||||
printf("\r\n> Check leased IP - OK\r\n");
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
// Received ARP reply or etc : IP address conflict occur, DHCP Failed
|
||||
send_DHCP_DECLINE();
|
||||
|
||||
ret = dhcp_tick_1s;
|
||||
while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf)
|
||||
{
|
||||
uint8_t zeroip[4] = {0,0,0,0};
|
||||
getSHAR(DHCP_CHADDR);
|
||||
if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
|
||||
{
|
||||
// assign temporary mac address, you should be set SHAR before call this function.
|
||||
DHCP_CHADDR[0] = 0x00;
|
||||
DHCP_CHADDR[1] = 0x08;
|
||||
DHCP_CHADDR[2] = 0xdc;
|
||||
DHCP_CHADDR[3] = 0x00;
|
||||
DHCP_CHADDR[4] = 0x00;
|
||||
DHCP_CHADDR[5] = 0x00;
|
||||
setSHAR(DHCP_CHADDR);
|
||||
}
|
||||
|
||||
DHCP_SOCKET = s; // SOCK_DHCP
|
||||
pDHCPMSG = (RIP_MSG*)buf;
|
||||
DHCP_XID = 0x12345678;
|
||||
|
||||
// WIZchip Netinfo Clear
|
||||
setSIPR(zeroip);
|
||||
setSIPR(zeroip);
|
||||
setGAR(zeroip);
|
||||
|
||||
reset_DHCP_timeout();
|
||||
dhcp_state = STATE_DHCP_INIT;
|
||||
}
|
||||
|
||||
|
||||
/* Rset the DHCP timeout count and retry count. */
|
||||
void reset_DHCP_timeout(void)
|
||||
{
|
||||
dhcp_tick_1s = 0;
|
||||
dhcp_tick_next = DHCP_WAIT_TIME;
|
||||
dhcp_retry_count = 0;
|
||||
}
|
||||
|
||||
void DHCP_time_handler(void)
|
||||
{
|
||||
dhcp_tick_1s++;
|
||||
}
|
||||
|
||||
void getIPfromDHCP(uint8_t* ip)
|
||||
{
|
||||
ip[0] = DHCP_allocated_ip[0];
|
||||
ip[1] = DHCP_allocated_ip[1];
|
||||
ip[2] = DHCP_allocated_ip[2];
|
||||
ip[3] = DHCP_allocated_ip[3];
|
||||
}
|
||||
|
||||
void getGWfromDHCP(uint8_t* ip)
|
||||
{
|
||||
ip[0] =DHCP_allocated_gw[0];
|
||||
ip[1] =DHCP_allocated_gw[1];
|
||||
ip[2] =DHCP_allocated_gw[2];
|
||||
ip[3] =DHCP_allocated_gw[3];
|
||||
}
|
||||
|
||||
void getSNfromDHCP(uint8_t* ip)
|
||||
{
|
||||
ip[0] = DHCP_allocated_sn[0];
|
||||
ip[1] = DHCP_allocated_sn[1];
|
||||
ip[2] = DHCP_allocated_sn[2];
|
||||
ip[3] = DHCP_allocated_sn[3];
|
||||
}
|
||||
|
||||
void getDNSfromDHCP(uint8_t* ip)
|
||||
{
|
||||
ip[0] = DHCP_allocated_dns[0];
|
||||
ip[1] = DHCP_allocated_dns[1];
|
||||
ip[2] = DHCP_allocated_dns[2];
|
||||
ip[3] = DHCP_allocated_dns[3];
|
||||
}
|
||||
|
||||
uint32_t getDHCPLeasetime(void)
|
||||
{
|
||||
return dhcp_lease_time;
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file dhcp.h
|
||||
//! \brief DHCP APIs Header file.
|
||||
//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
|
||||
//! \version 1.1.0
|
||||
//! \date 2013/11/18
|
||||
//! \par Revision history
|
||||
//! <2013/11/18> 1st Release
|
||||
//! <2012/12/20> V1.1.0
|
||||
//! 1. Move unreferenced DEFINE to dhcp.c
|
||||
//! <2012/12/26> V1.1.1
|
||||
//! \author Eric Jung & MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef _DHCP_H_
|
||||
#define _DHCP_H_
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* @details If you want to display debug & processing message, Define _DHCP_DEBUG_
|
||||
* @note If defined, it depends on <stdio.h>
|
||||
*/
|
||||
|
||||
//#define _DHCP_DEBUG_
|
||||
|
||||
/* Retry to processing DHCP */
|
||||
#define MAX_DHCP_RETRY 2 ///< Maximum retry count
|
||||
#define DHCP_WAIT_TIME 3 ///< Wait Time 3s (was 10s)
|
||||
|
||||
/* UDP port numbers for DHCP */
|
||||
#define DHCP_SERVER_PORT 67 ///< DHCP server port number
|
||||
#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
|
||||
|
||||
#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number
|
||||
|
||||
#define DCHP_HOST_NAME "WIZnet\0"
|
||||
|
||||
/*
|
||||
* @brief return value of @ref DHCP_run()
|
||||
*/
|
||||
enum
|
||||
{
|
||||
DHCP_FAILED = 0, ///< Processing Fail
|
||||
DHCP_RUNNING, ///< Processing DHCP protocol
|
||||
DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign)
|
||||
DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update)
|
||||
DHCP_IP_LEASED, ///< Stand by
|
||||
DHCP_STOPPED ///< Stop processing DHCP protocol
|
||||
};
|
||||
|
||||
#define DHCP_INIT_BUFFER_TYPE uint32_t
|
||||
#define DHCP_INIT_BUFFER_SIZE (137)
|
||||
/*
|
||||
* @brief DHCP client initialization (outside of the main loop)
|
||||
* @param s - socket number
|
||||
* @param buf - buffer for processing DHCP message
|
||||
*/
|
||||
void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf);
|
||||
|
||||
/*
|
||||
* @brief DHCP 1s Tick Timer handler
|
||||
* @note SHOULD BE register to your system 1s Tick timer handler
|
||||
*/
|
||||
void DHCP_time_handler(void);
|
||||
|
||||
/*
|
||||
* @brief Register call back function
|
||||
* @param ip_assign - callback func when IP is assigned from DHCP server first
|
||||
* @param ip_update - callback func when IP is changed
|
||||
* @prarm ip_conflict - callback func when the assigned IP is conflict with others.
|
||||
*/
|
||||
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
|
||||
|
||||
/*
|
||||
* @brief DHCP client in the main loop
|
||||
* @return The value is as the follow \n
|
||||
* @ref DHCP_FAILED \n
|
||||
* @ref DHCP_RUNNING \n
|
||||
* @ref DHCP_IP_ASSIGN \n
|
||||
* @ref DHCP_IP_CHANGED \n
|
||||
* @ref DHCP_IP_LEASED \n
|
||||
* @ref DHCP_STOPPED \n
|
||||
*
|
||||
* @note This function is always called by you main task.
|
||||
*/
|
||||
uint8_t DHCP_run(void);
|
||||
|
||||
/*
|
||||
* @brief Stop DHCP processing
|
||||
* @note If you want to restart. call DHCP_init() and DHCP_run()
|
||||
*/
|
||||
void DHCP_stop(void);
|
||||
|
||||
/* Get Network information assigned from DHCP server */
|
||||
/*
|
||||
* @brief Get IP address
|
||||
* @param ip - IP address to be returned
|
||||
*/
|
||||
void getIPfromDHCP(uint8_t* ip);
|
||||
/*
|
||||
* @brief Get Gateway address
|
||||
* @param ip - Gateway address to be returned
|
||||
*/
|
||||
void getGWfromDHCP(uint8_t* ip);
|
||||
/*
|
||||
* @brief Get Subnet mask value
|
||||
* @param ip - Subnet mask to be returned
|
||||
*/
|
||||
void getSNfromDHCP(uint8_t* ip);
|
||||
/*
|
||||
* @brief Get DNS address
|
||||
* @param ip - DNS address to be returned
|
||||
*/
|
||||
void getDNSfromDHCP(uint8_t* ip);
|
||||
|
||||
/*
|
||||
* @brief Get the leased time by DHCP sever
|
||||
* @return unit 1s
|
||||
*/
|
||||
uint32_t getDHCPLeasetime(void);
|
||||
|
||||
#endif /* _DHCP_H_ */
|
|
@ -1,572 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file dns.c
|
||||
//! \brief DNS APIs Implement file.
|
||||
//! \details Send DNS query & Receive DNS reponse. \n
|
||||
//! It depends on stdlib.h & string.h in ansi-c library
|
||||
//! \version 1.1.0
|
||||
//! \date 2013/11/18
|
||||
//! \par Revision history
|
||||
//! <2013/10/21> 1st Release
|
||||
//! <2013/12/20> V1.1.0
|
||||
//! 1. Remove secondary DNS server in DNS_run
|
||||
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
|
||||
//! 2. DNS_timerHandler -> DNS_time_handler
|
||||
//! 3. Remove the unused define
|
||||
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
|
||||
//! <2013/12/20> V1.1.0
|
||||
//! <2018/10/04> Modified HAL_GetTick for use with CircuitPython by Nick Moore
|
||||
//!
|
||||
//! \author Eric Jung & MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
//#include "Ethernet/socket.h"
|
||||
//#include "Internet/DNS/dns.h"
|
||||
#include "../../ethernet/socket.h"
|
||||
#include "dns.h"
|
||||
|
||||
#ifdef _DNS_DEBUG_
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define INITRTT 2000L /* Initial smoothed response time */
|
||||
#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */
|
||||
|
||||
#define TYPE_A 1 /* Host address */
|
||||
#define TYPE_NS 2 /* Name server */
|
||||
#define TYPE_MD 3 /* Mail destination (obsolete) */
|
||||
#define TYPE_MF 4 /* Mail forwarder (obsolete) */
|
||||
#define TYPE_CNAME 5 /* Canonical name */
|
||||
#define TYPE_SOA 6 /* Start of Authority */
|
||||
#define TYPE_MB 7 /* Mailbox name (experimental) */
|
||||
#define TYPE_MG 8 /* Mail group member (experimental) */
|
||||
#define TYPE_MR 9 /* Mail rename name (experimental) */
|
||||
#define TYPE_NULL 10 /* Null (experimental) */
|
||||
#define TYPE_WKS 11 /* Well-known sockets */
|
||||
#define TYPE_PTR 12 /* Pointer record */
|
||||
#define TYPE_HINFO 13 /* Host information */
|
||||
#define TYPE_MINFO 14 /* Mailbox information (experimental)*/
|
||||
#define TYPE_MX 15 /* Mail exchanger */
|
||||
#define TYPE_TXT 16 /* Text strings */
|
||||
#define TYPE_ANY 255 /* Matches any type */
|
||||
|
||||
#define CLASS_IN 1 /* The ARPA Internet */
|
||||
|
||||
/* Round trip timing parameters */
|
||||
#define AGAIN 8 /* Average RTT gain = 1/8 */
|
||||
#define LAGAIN 3 /* Log2(AGAIN) */
|
||||
#define DGAIN 4 /* Mean deviation gain = 1/4 */
|
||||
#define LDGAIN 2 /* log2(DGAIN) */
|
||||
|
||||
/* Header for all domain messages */
|
||||
struct dhdr
|
||||
{
|
||||
uint16_t id; /* Identification */
|
||||
uint8_t qr; /* Query/Response */
|
||||
#define QUERY 0
|
||||
#define RESPONSE 1
|
||||
uint8_t opcode;
|
||||
#define IQUERY 1
|
||||
uint8_t aa; /* Authoratative answer */
|
||||
uint8_t tc; /* Truncation */
|
||||
uint8_t rd; /* Recursion desired */
|
||||
uint8_t ra; /* Recursion available */
|
||||
uint8_t rcode; /* Response code */
|
||||
#define NO_ERROR 0
|
||||
#define FORMAT_ERROR 1
|
||||
#define SERVER_FAIL 2
|
||||
#define NAME_ERROR 3
|
||||
#define NOT_IMPL 4
|
||||
#define REFUSED 5
|
||||
uint16_t qdcount; /* Question count */
|
||||
uint16_t ancount; /* Answer count */
|
||||
uint16_t nscount; /* Authority (name server) count */
|
||||
uint16_t arcount; /* Additional record count */
|
||||
};
|
||||
|
||||
|
||||
uint8_t* pDNSMSG; // DNS message buffer
|
||||
uint8_t DNS_SOCKET; // SOCKET number for DNS
|
||||
uint16_t DNS_MSGID; // DNS message ID
|
||||
|
||||
|
||||
uint32_t HAL_GetTick(void) {
|
||||
return supervisor_ticks_ms32();
|
||||
}
|
||||
|
||||
uint32_t hal_sys_tick;
|
||||
|
||||
/* converts uint16_t from network buffer to a host byte order integer. */
|
||||
uint16_t get16(uint8_t * s)
|
||||
{
|
||||
uint16_t i;
|
||||
i = *s++ << 8;
|
||||
i = i + *s;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* copies uint16_t to the network buffer with network byte order. */
|
||||
uint8_t * put16(uint8_t * s, uint16_t i)
|
||||
{
|
||||
*s++ = i >> 8;
|
||||
*s++ = i;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
|
||||
*
|
||||
* Description : This function converts a compressed domain name to the human-readable form
|
||||
* Arguments : msg - is a pointer to the reply message
|
||||
* compressed - is a pointer to the domain name in reply message.
|
||||
* buf - is a pointer to the buffer for the human-readable form name.
|
||||
* len - is the MAX. size of buffer.
|
||||
* Returns : the length of compressed message
|
||||
*/
|
||||
int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len)
|
||||
{
|
||||
uint16_t slen; /* Length of current segment */
|
||||
uint8_t * cp;
|
||||
int clen = 0; /* Total length of compressed name */
|
||||
int indirect = 0; /* Set if indirection encountered */
|
||||
int nseg = 0; /* Total number of segments in name */
|
||||
|
||||
cp = compressed;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
slen = *cp++; /* Length of this segment */
|
||||
|
||||
if (!indirect) clen++;
|
||||
|
||||
if ((slen & 0xc0) == 0xc0)
|
||||
{
|
||||
if (!indirect)
|
||||
clen++;
|
||||
indirect = 1;
|
||||
/* Follow indirection */
|
||||
cp = &msg[((slen & 0x3f)<<8) + *cp];
|
||||
slen = *cp++;
|
||||
}
|
||||
|
||||
if (slen == 0) /* zero length == all done */
|
||||
break;
|
||||
|
||||
len -= slen + 1;
|
||||
|
||||
if (len < 0) return -1;
|
||||
|
||||
if (!indirect) clen += slen;
|
||||
|
||||
while (slen-- != 0) *buf++ = (char)*cp++;
|
||||
*buf++ = '.';
|
||||
nseg++;
|
||||
}
|
||||
|
||||
if (nseg == 0)
|
||||
{
|
||||
/* Root name; represent as single dot */
|
||||
*buf++ = '.';
|
||||
len--;
|
||||
}
|
||||
|
||||
*buf++ = '\0';
|
||||
len--;
|
||||
|
||||
return clen; /* Length of compressed message */
|
||||
}
|
||||
|
||||
/*
|
||||
* PARSE QUESTION SECTION
|
||||
*
|
||||
* Description : This function parses the question record of the reply message.
|
||||
* Arguments : msg - is a pointer to the reply message
|
||||
* cp - is a pointer to the question record.
|
||||
* Returns : a pointer the to next record.
|
||||
*/
|
||||
uint8_t * dns_question(uint8_t * msg, uint8_t * cp)
|
||||
{
|
||||
int len;
|
||||
char name[MAXCNAME];
|
||||
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
|
||||
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
cp += 2; /* type */
|
||||
cp += 2; /* class */
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PARSE ANSER SECTION
|
||||
*
|
||||
* Description : This function parses the answer record of the reply message.
|
||||
* Arguments : msg - is a pointer to the reply message
|
||||
* cp - is a pointer to the answer record.
|
||||
* Returns : a pointer the to next record.
|
||||
*/
|
||||
uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns)
|
||||
{
|
||||
int len, type;
|
||||
char name[MAXCNAME];
|
||||
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
type = get16(cp);
|
||||
cp += 2; /* type */
|
||||
cp += 2; /* class */
|
||||
cp += 4; /* ttl */
|
||||
cp += 2; /* len */
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_A:
|
||||
/* Just read the address directly into the structure */
|
||||
ip_from_dns[0] = *cp++;
|
||||
ip_from_dns[1] = *cp++;
|
||||
ip_from_dns[2] = *cp++;
|
||||
ip_from_dns[3] = *cp++;
|
||||
break;
|
||||
case TYPE_CNAME:
|
||||
case TYPE_MB:
|
||||
case TYPE_MG:
|
||||
case TYPE_MR:
|
||||
case TYPE_NS:
|
||||
case TYPE_PTR:
|
||||
/* These types all consist of a single domain name */
|
||||
/* convert it to ASCII format */
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
break;
|
||||
case TYPE_HINFO:
|
||||
len = *cp++;
|
||||
cp += len;
|
||||
|
||||
len = *cp++;
|
||||
cp += len;
|
||||
break;
|
||||
case TYPE_MX:
|
||||
cp += 2;
|
||||
/* Get domain name of exchanger */
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
break;
|
||||
case TYPE_SOA:
|
||||
/* Get domain name of name server */
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
|
||||
/* Get domain name of responsible person */
|
||||
len = parse_name(msg, cp, name, MAXCNAME);
|
||||
if (len == -1) return 0;
|
||||
|
||||
cp += len;
|
||||
|
||||
cp += 4;
|
||||
cp += 4;
|
||||
cp += 4;
|
||||
cp += 4;
|
||||
cp += 4;
|
||||
break;
|
||||
case TYPE_TXT:
|
||||
/* Just stash */
|
||||
break;
|
||||
default:
|
||||
/* Ignore */
|
||||
break;
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* PARSE THE DNS REPLY
|
||||
*
|
||||
* Description : This function parses the reply message from DNS server.
|
||||
* Arguments : dhdr - is a pointer to the header for DNS message
|
||||
* buf - is a pointer to the reply message.
|
||||
* len - is the size of reply message.
|
||||
* Returns : -1 - Domain name length is too big
|
||||
* 0 - Fail (Timeout or parse error)
|
||||
* 1 - Success,
|
||||
*/
|
||||
int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns)
|
||||
{
|
||||
uint16_t tmp;
|
||||
uint16_t i;
|
||||
uint8_t * msg;
|
||||
uint8_t * cp;
|
||||
|
||||
msg = pbuf;
|
||||
memset(pdhdr, 0, sizeof(*pdhdr));
|
||||
|
||||
pdhdr->id = get16(&msg[0]);
|
||||
tmp = get16(&msg[2]);
|
||||
if (tmp & 0x8000) pdhdr->qr = 1;
|
||||
|
||||
pdhdr->opcode = (tmp >> 11) & 0xf;
|
||||
|
||||
if (tmp & 0x0400) pdhdr->aa = 1;
|
||||
if (tmp & 0x0200) pdhdr->tc = 1;
|
||||
if (tmp & 0x0100) pdhdr->rd = 1;
|
||||
if (tmp & 0x0080) pdhdr->ra = 1;
|
||||
|
||||
pdhdr->rcode = tmp & 0xf;
|
||||
pdhdr->qdcount = get16(&msg[4]);
|
||||
pdhdr->ancount = get16(&msg[6]);
|
||||
pdhdr->nscount = get16(&msg[8]);
|
||||
pdhdr->arcount = get16(&msg[10]);
|
||||
|
||||
|
||||
/* Now parse the variable length sections */
|
||||
cp = &msg[12];
|
||||
|
||||
/* Question section */
|
||||
for (i = 0; i < pdhdr->qdcount; i++)
|
||||
{
|
||||
cp = dns_question(msg, cp);
|
||||
if(!cp)
|
||||
{
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Answer section */
|
||||
for (i = 0; i < pdhdr->ancount; i++)
|
||||
{
|
||||
cp = dns_answer(msg, cp, ip_from_dns);
|
||||
if(!cp)
|
||||
{
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Name server (authority) section */
|
||||
for (i = 0; i < pdhdr->nscount; i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/* Additional section */
|
||||
for (i = 0; i < pdhdr->arcount; i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if(pdhdr->rcode == 0) return 1; // No error
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MAKE DNS QUERY MESSAGE
|
||||
*
|
||||
* Description : This function makes DNS query message.
|
||||
* Arguments : op - Recursion desired
|
||||
* name - is a pointer to the domain name.
|
||||
* buf - is a pointer to the buffer for DNS message.
|
||||
* len - is the MAX. size of buffer.
|
||||
* Returns : the pointer to the DNS message.
|
||||
*/
|
||||
int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len)
|
||||
{
|
||||
uint8_t *cp;
|
||||
char *cp1;
|
||||
char sname[MAXCNAME];
|
||||
char *dname;
|
||||
uint16_t p;
|
||||
uint16_t dlen;
|
||||
|
||||
cp = buf;
|
||||
|
||||
DNS_MSGID++;
|
||||
cp = put16(cp, DNS_MSGID);
|
||||
p = (op << 11) | 0x0100; /* Recursion desired */
|
||||
cp = put16(cp, p);
|
||||
cp = put16(cp, 1);
|
||||
cp = put16(cp, 0);
|
||||
cp = put16(cp, 0);
|
||||
cp = put16(cp, 0);
|
||||
|
||||
strcpy(sname, name);
|
||||
dname = sname;
|
||||
dlen = strlen(dname);
|
||||
for (;;)
|
||||
{
|
||||
/* Look for next dot */
|
||||
cp1 = strchr(dname, '.');
|
||||
|
||||
if (cp1 != NULL) len = cp1 - dname; /* More to come */
|
||||
else len = dlen; /* Last component */
|
||||
|
||||
*cp++ = len; /* Write length of component */
|
||||
if (len == 0) break;
|
||||
|
||||
/* Copy component up to (but not including) dot */
|
||||
memcpy(cp, dname, len);
|
||||
cp += len;
|
||||
if (cp1 == NULL)
|
||||
{
|
||||
*cp++ = 0; /* Last one; write null and finish */
|
||||
break;
|
||||
}
|
||||
dname += len+1;
|
||||
dlen -= len+1;
|
||||
}
|
||||
|
||||
cp = put16(cp, 0x0001); /* type */
|
||||
cp = put16(cp, 0x0001); /* class */
|
||||
|
||||
return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
|
||||
}
|
||||
|
||||
/*
|
||||
* CHECK DNS TIMEOUT
|
||||
*
|
||||
* Description : This function check the DNS timeout
|
||||
* Arguments : None.
|
||||
* Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
|
||||
* Note : timeout : retry count and timer both over.
|
||||
*/
|
||||
|
||||
int8_t check_DNS_timeout(void)
|
||||
{
|
||||
static uint8_t retry_count;
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000)
|
||||
{
|
||||
hal_sys_tick = tick;
|
||||
if(retry_count >= MAX_DNS_RETRY) {
|
||||
retry_count = 0;
|
||||
return -1; // timeout occurred
|
||||
}
|
||||
retry_count++;
|
||||
return 0; // timer over, but no timeout
|
||||
}
|
||||
|
||||
return 1; // no timer over, no timeout occur
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DNS CLIENT INIT */
|
||||
void DNS_init(uint8_t s, uint8_t * buf)
|
||||
{
|
||||
DNS_SOCKET = s; // SOCK_DNS
|
||||
pDNSMSG = buf; // User's shared buffer
|
||||
DNS_MSGID = DNS_MSG_ID;
|
||||
}
|
||||
|
||||
/* DNS CLIENT RUN */
|
||||
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
|
||||
{
|
||||
int8_t ret;
|
||||
struct dhdr dhp;
|
||||
uint8_t ip[4];
|
||||
uint16_t len, port;
|
||||
int8_t ret_check_timeout;
|
||||
|
||||
hal_sys_tick = HAL_GetTick();
|
||||
|
||||
// Socket open
|
||||
WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0);
|
||||
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
|
||||
#endif
|
||||
|
||||
len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
|
||||
WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
|
||||
{
|
||||
if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
|
||||
len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port);
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len);
|
||||
#endif
|
||||
ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
|
||||
break;
|
||||
}
|
||||
// Check Timeout
|
||||
ret_check_timeout = check_DNS_timeout();
|
||||
if (ret_check_timeout < 0) {
|
||||
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
|
||||
#endif
|
||||
return 0; // timeout occurred
|
||||
}
|
||||
else if (ret_check_timeout == 0) {
|
||||
|
||||
#ifdef _DNS_DEBUG_
|
||||
printf("> DNS Timeout\r\n");
|
||||
#endif
|
||||
WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
|
||||
}
|
||||
}
|
||||
WIZCHIP_EXPORT(close)(DNS_SOCKET);
|
||||
// Return value
|
||||
// 0 > : failed / 1 - success
|
||||
return ret;
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
//! \file dns.h
|
||||
//! \brief DNS APIs Header file.
|
||||
//! \details Send DNS query & Receive DNS reponse.
|
||||
//! \version 1.1.0
|
||||
//! \date 2013/11/18
|
||||
//! \par Revision history
|
||||
//! <2013/10/21> 1st Release
|
||||
//! <2013/12/20> V1.1.0
|
||||
//! 1. Remove secondary DNS server in DNS_run
|
||||
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
|
||||
//! 2. DNS_timerHandler -> DNS_time_handler
|
||||
//! 3. Move the no reference define to dns.c
|
||||
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
|
||||
//! <2013/12/20> V1.1.0
|
||||
//!
|
||||
//! \author Eric Jung & MidnightCow
|
||||
//! \copyright
|
||||
//!
|
||||
//! Copyright (c) 2013, WIZnet Co., LTD.
|
||||
//! All rights reserved.
|
||||
//!
|
||||
//! Redistribution and use in source and binary forms, with or without
|
||||
//! modification, are permitted provided that the following conditions
|
||||
//! are met:
|
||||
//!
|
||||
//! * Redistributions of source code must retain the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer.
|
||||
//! * Redistributions in binary form must reproduce the above copyright
|
||||
//! notice, this list of conditions and the following disclaimer in the
|
||||
//! documentation and/or other materials provided with the distribution.
|
||||
//! * Neither the name of the <ORGANIZATION> nor the names of its
|
||||
//! contributors may be used to endorse or promote products derived
|
||||
//! from this software without specific prior written permission.
|
||||
//!
|
||||
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
//! THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef _DNS_H_
|
||||
#define _DNS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
/*
|
||||
* @brief Define it for Debug & Monitor DNS processing.
|
||||
* @note If defined, it depends on <stdio.h>
|
||||
*/
|
||||
|
||||
//#define _DNS_DEBUG_
|
||||
|
||||
#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */
|
||||
/*
|
||||
* @brief Maximum length of your queried Domain name
|
||||
* @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1)
|
||||
* @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
|
||||
*/
|
||||
#define MAX_DOMAIN_NAME 32 // for example "www.google.com"
|
||||
|
||||
#define MAX_DNS_RETRY 2 ///< Requery Count
|
||||
#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s.
|
||||
|
||||
#define IPPORT_DOMAIN 53 ///< DNS server port number
|
||||
|
||||
#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number
|
||||
/*
|
||||
* @brief DNS process initialize
|
||||
* @param s : Socket number for DNS
|
||||
* @param buf : Buffer for DNS message
|
||||
*/
|
||||
void DNS_init(uint8_t s, uint8_t * buf);
|
||||
|
||||
/*
|
||||
* @brief DNS process
|
||||
* @details Send DNS query and receive DNS response
|
||||
* @param dns_ip : DNS server ip address
|
||||
* @param name : Domain name to be queried
|
||||
* @param ip_from_dns : IP address from DNS server
|
||||
* @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
|
||||
* 0 : failed (Timeout or Parse error)\n
|
||||
* 1 : success
|
||||
* @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
|
||||
*/
|
||||
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
|
||||
|
||||
#endif /* _DNS_H_ */
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Automatically generated header file: don't edit
|
||||
*/
|
||||
|
||||
#define HAVE_DOT_CONFIG 1
|
||||
#define CONFIG_PLATFORM_LINUX 1
|
||||
#undef CONFIG_PLATFORM_CYGWIN
|
||||
#undef CONFIG_PLATFORM_WIN32
|
||||
|
||||
/*
|
||||
* General Configuration
|
||||
*/
|
||||
#define PREFIX "/usr/local"
|
||||
#undef CONFIG_DEBUG
|
||||
#undef CONFIG_STRIP_UNWANTED_SECTIONS
|
||||
#undef CONFIG_VISUAL_STUDIO_7_0
|
||||
#undef CONFIG_VISUAL_STUDIO_8_0
|
||||
#undef CONFIG_VISUAL_STUDIO_10_0
|
||||
#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
|
||||
#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
|
||||
#define CONFIG_VISUAL_STUDIO_10_0_BASE ""
|
||||
#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
|
||||
#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
|
||||
|
||||
/*
|
||||
* SSL Library
|
||||
*/
|
||||
#undef CONFIG_SSL_SERVER_ONLY
|
||||
#undef CONFIG_SSL_CERT_VERIFICATION
|
||||
#undef CONFIG_SSL_FULL_MODE
|
||||
#define CONFIG_SSL_SKELETON_MODE 1
|
||||
#define CONFIG_SSL_ENABLE_SERVER 1
|
||||
#define CONFIG_SSL_ENABLE_CLIENT 1
|
||||
#undef CONFIG_SSL_DIAGNOSTICS
|
||||
#define CONFIG_SSL_PROT_LOW 1
|
||||
#undef CONFIG_SSL_PROT_MEDIUM
|
||||
#undef CONFIG_SSL_PROT_HIGH
|
||||
#define CONFIG_SSL_AES 1
|
||||
#define CONFIG_SSL_USE_DEFAULT_KEY 1
|
||||
#define CONFIG_SSL_PRIVATE_KEY_LOCATION ""
|
||||
#define CONFIG_SSL_PRIVATE_KEY_PASSWORD ""
|
||||
#define CONFIG_SSL_X509_CERT_LOCATION ""
|
||||
#undef CONFIG_SSL_GENERATE_X509_CERT
|
||||
#define CONFIG_SSL_X509_COMMON_NAME ""
|
||||
#define CONFIG_SSL_X509_ORGANIZATION_NAME ""
|
||||
#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME ""
|
||||
#undef CONFIG_SSL_HAS_PEM
|
||||
#undef CONFIG_SSL_USE_PKCS12
|
||||
#define CONFIG_SSL_EXPIRY_TIME
|
||||
#define CONFIG_X509_MAX_CA_CERTS 0
|
||||
#define CONFIG_SSL_MAX_CERTS 3
|
||||
#undef CONFIG_SSL_CTX_MUTEXING
|
||||
#undef CONFIG_USE_DEV_URANDOM
|
||||
#undef CONFIG_WIN32_USE_CRYPTO_LIB
|
||||
#undef CONFIG_OPENSSL_COMPATIBLE
|
||||
#undef CONFIG_PERFORMANCE_TESTING
|
||||
#undef CONFIG_SSL_TEST
|
||||
#undef CONFIG_AXTLSWRAP
|
||||
#undef CONFIG_AXHTTPD
|
||||
#undef CONFIG_HTTP_STATIC_BUILD
|
||||
#define CONFIG_HTTP_PORT
|
||||
#define CONFIG_HTTP_HTTPS_PORT
|
||||
#define CONFIG_HTTP_SESSION_CACHE_SIZE
|
||||
#define CONFIG_HTTP_WEBROOT ""
|
||||
#define CONFIG_HTTP_TIMEOUT
|
||||
#undef CONFIG_HTTP_HAS_CGI
|
||||
#define CONFIG_HTTP_CGI_EXTENSIONS ""
|
||||
#undef CONFIG_HTTP_ENABLE_LUA
|
||||
#define CONFIG_HTTP_LUA_PREFIX ""
|
||||
#undef CONFIG_HTTP_BUILD_LUA
|
||||
#define CONFIG_HTTP_CGI_LAUNCHER ""
|
||||
#undef CONFIG_HTTP_DIRECTORIES
|
||||
#undef CONFIG_HTTP_HAS_AUTHORIZATION
|
||||
#undef CONFIG_HTTP_HAS_IPV6
|
||||
#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER
|
||||
#define CONFIG_HTTP_USER ""
|
||||
#undef CONFIG_HTTP_VERBOSE
|
||||
#undef CONFIG_HTTP_IS_DAEMON
|
||||
|
||||
/*
|
||||
* Language Bindings
|
||||
*/
|
||||
#undef CONFIG_BINDINGS
|
||||
#undef CONFIG_CSHARP_BINDINGS
|
||||
#undef CONFIG_VBNET_BINDINGS
|
||||
#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
|
||||
#undef CONFIG_JAVA_BINDINGS
|
||||
#define CONFIG_JAVA_HOME ""
|
||||
#undef CONFIG_PERL_BINDINGS
|
||||
#define CONFIG_PERL_CORE ""
|
||||
#define CONFIG_PERL_LIB ""
|
||||
#undef CONFIG_LUA_BINDINGS
|
||||
#define CONFIG_LUA_CORE ""
|
||||
|
||||
/*
|
||||
* Samples
|
||||
*/
|
||||
#undef CONFIG_SAMPLES
|
||||
#undef CONFIG_C_SAMPLES
|
||||
#undef CONFIG_CSHARP_SAMPLES
|
||||
#undef CONFIG_VBNET_SAMPLES
|
||||
#undef CONFIG_JAVA_SAMPLES
|
||||
#undef CONFIG_PERL_SAMPLES
|
||||
#undef CONFIG_LUA_SAMPLES
|
||||
#undef CONFIG_BIGINT_CLASSICAL
|
||||
#undef CONFIG_BIGINT_MONTGOMERY
|
||||
#undef CONFIG_BIGINT_BARRETT
|
||||
#undef CONFIG_BIGINT_CRT
|
||||
#undef CONFIG_BIGINT_KARATSUBA
|
||||
#define MUL_KARATSUBA_THRESH
|
||||
#define SQU_KARATSUBA_THRESH
|
||||
#undef CONFIG_BIGINT_SLIDING_WINDOW
|
||||
#undef CONFIG_BIGINT_SQUARE
|
||||
#undef CONFIG_BIGINT_CHECK_ON
|
||||
#undef CONFIG_INTEGER_32BIT
|
||||
#undef CONFIG_INTEGER_16BIT
|
||||
#undef CONFIG_INTEGER_8BIT
|
|
@ -0,0 +1 @@
|
|||
#define AXTLS_VERSION "(no version)"
|
|
@ -1,94 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
// If you wish to override the functions for mapping the machine_mem read/write
|
||||
// address, then add a #define for MICROPY_MACHINE_MEM_GET_READ_ADDR and/or
|
||||
// MICROPY_MACHINE_MEM_GET_WRITE_ADDR in your mpconfigport.h. Since the
|
||||
// prototypes are identical, it is allowable for both of the macros to evaluate
|
||||
// the to same function.
|
||||
//
|
||||
// It is expected that the modmachine.c file for a given port will provide the
|
||||
// implementations, if the default implementation isn't used.
|
||||
|
||||
#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) || !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
|
||||
STATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) {
|
||||
uintptr_t addr = mp_obj_int_get_truncated(addr_o);
|
||||
if ((addr & (align - 1)) != 0) {
|
||||
mp_raise_ValueError_varg(translate("address %08x is not aligned to %d bytes"), addr, align);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
|
||||
#define MICROPY_MACHINE_MEM_GET_READ_ADDR machine_mem_get_addr
|
||||
#endif
|
||||
#if !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
|
||||
#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR machine_mem_get_addr
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
// TODO support slice index to read/write multiple values at once
|
||||
machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (value == MP_OBJ_NULL) {
|
||||
// delete
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
} else if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size);
|
||||
uint32_t val;
|
||||
switch (self->elem_size) {
|
||||
case 1:
|
||||
val = (*(uint8_t *)addr);
|
||||
break;
|
||||
case 2:
|
||||
val = (*(uint16_t *)addr);
|
||||
break;
|
||||
default:
|
||||
val = (*(uint32_t *)addr);
|
||||
break;
|
||||
}
|
||||
return mp_obj_new_int(val);
|
||||
} else {
|
||||
// store
|
||||
uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size);
|
||||
uint32_t val = mp_obj_get_int_truncated(value);
|
||||
switch (self->elem_size) {
|
||||
case 1:
|
||||
(*(uint8_t *)addr) = val;
|
||||
break;
|
||||
case 2:
|
||||
(*(uint16_t *)addr) = val;
|
||||
break;
|
||||
default:
|
||||
(*(uint32_t *)addr) = val;
|
||||
break;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
const mp_obj_type_t machine_mem_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_mem,
|
||||
.print = machine_mem_print,
|
||||
.subscr = machine_mem_subscr,
|
||||
};
|
||||
|
||||
const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
|
||||
const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
|
||||
const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
|
@ -1,29 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2015 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct _machine_mem_obj_t {
|
||||
mp_obj_base_t base;
|
||||
unsigned elem_size; // in bytes
|
||||
} machine_mem_obj_t;
|
||||
|
||||
extern const mp_obj_type_t machine_mem_type;
|
||||
|
||||
extern const machine_mem_obj_t machine_mem8_obj;
|
||||
extern const machine_mem_obj_t machine_mem16_obj;
|
||||
extern const machine_mem_obj_t machine_mem32_obj;
|
||||
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/virtpin.h"
|
||||
#include "extmod/machine_pinbase.h"
|
||||
|
||||
// PinBase class
|
||||
|
||||
// As this is abstract class, its instance is null.
|
||||
// But there should be an instance, as the rest of instance code
|
||||
// expects that there will be concrete object for inheritance.
|
||||
typedef struct _mp_pinbase_t {
|
||||
mp_obj_base_t base;
|
||||
} mp_pinbase_t;
|
||||
|
||||
STATIC const mp_pinbase_t pinbase_singleton = {
|
||||
.base = { &machine_pinbase_type },
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pinbase_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
(void)type;
|
||||
(void)n_args;
|
||||
(void)args;
|
||||
(void)kw_args;
|
||||
return MP_OBJ_FROM_PTR(&pinbase_singleton);
|
||||
}
|
||||
|
||||
mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
(void)errcode;
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(obj, MP_QSTR_value, dest);
|
||||
return mp_obj_get_int(mp_call_method_n_kw(0, 0, dest));
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
mp_obj_t dest[3];
|
||||
mp_load_method(obj, MP_QSTR_value, dest);
|
||||
dest[2] = (arg == 0 ? mp_const_false : mp_const_true);
|
||||
mp_call_method_n_kw(1, 0, dest);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC const mp_pin_p_t pinbase_pin_p = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
|
||||
.ioctl = pinbase_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_pinbase_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PinBase,
|
||||
.make_new = pinbase_make_new,
|
||||
.protocol = &pinbase_pin_p,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
extern const mp_obj_type_t machine_pinbase_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
|
@ -1,44 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_PULSE
|
||||
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
|
||||
mp_uint_t start = mp_hal_ticks_us();
|
||||
while (mp_hal_pin_read(pin) != pulse_level) {
|
||||
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
|
||||
return (mp_uint_t)-2;
|
||||
}
|
||||
}
|
||||
start = mp_hal_ticks_us();
|
||||
while (mp_hal_pin_read(pin) == pulse_level) {
|
||||
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
|
||||
return (mp_uint_t)-1;
|
||||
}
|
||||
}
|
||||
return mp_hal_ticks_us() - start;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
|
||||
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);
|
||||
int level = 0;
|
||||
if (mp_obj_is_true(args[1])) {
|
||||
level = 1;
|
||||
}
|
||||
mp_uint_t timeout_us = 1000000;
|
||||
if (n_args > 2) {
|
||||
timeout_us = mp_obj_get_int(args[2]);
|
||||
}
|
||||
mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);
|
||||
// May return -1 or -2 in case of timeout
|
||||
return mp_obj_new_int(us);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);
|
||||
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
|
|
@ -1,159 +0,0 @@
|
|||
// Copyright (c) 2017 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/virtpin.h"
|
||||
#include "extmod/machine_signal.h"
|
||||
|
||||
// Signal class
|
||||
|
||||
typedef struct _machine_signal_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t pin;
|
||||
bool invert;
|
||||
} machine_signal_t;
|
||||
|
||||
STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_obj_t pin = args[0];
|
||||
bool invert = false;
|
||||
|
||||
#if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
|
||||
mp_pin_p_t *pin_p = (mp_pin_t *)mp_proto_get(QSTR_pin_protocol, pin);
|
||||
|
||||
if (pin_p == NULL) {
|
||||
// If first argument isn't a Pin-like object, we filter out "invert"
|
||||
// from keyword arguments and pass them all to the exported Pin
|
||||
// constructor to create one.
|
||||
mp_obj_t *pin_args = mp_local_alloc((n_args + n_kw * 2) * sizeof(mp_obj_t));
|
||||
memcpy(pin_args, args, n_args * sizeof(mp_obj_t));
|
||||
const mp_obj_t *src = args + n_args;
|
||||
mp_obj_t *dst = pin_args + n_args;
|
||||
mp_obj_t *sig_value = NULL;
|
||||
for (size_t cnt = n_kw; cnt; cnt--) {
|
||||
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
|
||||
invert = mp_obj_is_true(src[1]);
|
||||
n_kw--;
|
||||
} else {
|
||||
*dst++ = *src;
|
||||
*dst++ = src[1];
|
||||
}
|
||||
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) {
|
||||
// Value is pertained to Signal, so we should invert
|
||||
// it for Pin if needed, and we should do it only when
|
||||
// inversion status is guaranteedly known.
|
||||
sig_value = dst - 1;
|
||||
}
|
||||
src += 2;
|
||||
}
|
||||
|
||||
if (invert && sig_value != NULL) {
|
||||
*sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1);
|
||||
}
|
||||
|
||||
// Here we pass NULL as a type, hoping that mp_pin_make_new()
|
||||
// will just ignore it as set a concrete type. If not, we'd need
|
||||
// to expose port's "default" pin type too.
|
||||
pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
|
||||
|
||||
mp_local_free(pin_args);
|
||||
} else
|
||||
#endif
|
||||
// Otherwise there should be 1 or 2 args
|
||||
{
|
||||
if (n_args == 1) {
|
||||
if (kw_args == NULL || kw_args->used == 0) {
|
||||
} else if (kw_args->used == 1 && kw_args->table[0].key == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
|
||||
invert = mp_obj_is_true(kw_args->table[0].value);
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
error:
|
||||
mp_raise_TypeError(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
machine_signal_t *o = m_new_obj(machine_signal_t);
|
||||
o->base.type = type;
|
||||
o->pin = pin;
|
||||
o->invert = invert;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t signal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
(void)errcode;
|
||||
machine_signal_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
return mp_virtual_pin_read(self->pin) ^ self->invert;
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
mp_virtual_pin_write(self->pin, arg ^ self->invert);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fast method for getting/setting signal value
|
||||
STATIC mp_obj_t signal_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num_kw_array(n_args, n_kw, 0, 1, false);
|
||||
if (n_args == 0) {
|
||||
// get pin
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_virtual_pin_read(self_in));
|
||||
} else {
|
||||
// set pin
|
||||
mp_virtual_pin_write(self_in, mp_obj_is_true(args[0]));
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t signal_value(size_t n_args, const mp_obj_t *args) {
|
||||
return signal_call(args[0], n_args - 1, 0, args + 1);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(signal_value_obj, 1, 2, signal_value);
|
||||
|
||||
STATIC mp_obj_t signal_on(mp_obj_t self_in) {
|
||||
mp_virtual_pin_write(self_in, 1);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_on_obj, signal_on);
|
||||
|
||||
STATIC mp_obj_t signal_off(mp_obj_t self_in) {
|
||||
mp_virtual_pin_write(self_in, 0);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_off_obj, signal_off);
|
||||
|
||||
STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&signal_value_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&signal_on_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&signal_off_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table);
|
||||
|
||||
STATIC const mp_pin_p_t signal_pin_p = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
|
||||
.ioctl = signal_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_signal_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Signal,
|
||||
.make_new = signal_make_new,
|
||||
.call = signal_call,
|
||||
.protocol = &signal_pin_p,
|
||||
.locals_dict = (void *)&signal_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) 2017 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
extern const mp_obj_type_t machine_signal_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
|
|
@ -331,7 +331,7 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
|
|||
openinfo.psize = args.pagesize.u_int;
|
||||
openinfo.minkeypage = args.minkeypage.u_int;
|
||||
|
||||
DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
|
||||
DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
|
||||
if (db == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
|
|
1449
extmod/modlwip.c
1449
extmod/modlwip.c
File diff suppressed because it is too large
Load Diff
|
@ -13,8 +13,8 @@
|
|||
// Low-level 1-Wire routines
|
||||
|
||||
#define TIMING_RESET1 (480)
|
||||
#define TIMING_RESET2 (40)
|
||||
#define TIMING_RESET3 (420)
|
||||
#define TIMING_RESET2 (70)
|
||||
#define TIMING_RESET3 (410)
|
||||
#define TIMING_READ1 (5)
|
||||
#define TIMING_READ2 (5)
|
||||
#define TIMING_READ3 (40)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014 Paul Sokolovsky
|
||||
// Copyright (c) 2014-2018 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
@ -73,7 +73,7 @@ enum {
|
|||
#define AGG_TYPE_BITS 2
|
||||
|
||||
enum {
|
||||
STRUCT, PTR, ARRAY, BITFIELD,
|
||||
STRUCT, PTR, ARRAY,
|
||||
};
|
||||
|
||||
// Here we need to set sign bit right
|
||||
|
@ -118,7 +118,11 @@ STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_p
|
|||
(void)kind;
|
||||
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const char *typen = "unk";
|
||||
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
|
||||
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)
|
||||
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
|
||||
|| MP_OBJ_IS_TYPE(self->desc, &mp_type_ordereddict)
|
||||
#endif
|
||||
) {
|
||||
typen = "STRUCT";
|
||||
} else if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
|
||||
|
@ -191,7 +195,11 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
|
|||
}
|
||||
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size) {
|
||||
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
|
||||
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)
|
||||
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
|
||||
&& !MP_OBJ_IS_TYPE(desc_in, &mp_type_ordereddict)
|
||||
#endif
|
||||
) {
|
||||
if (MP_OBJ_IS_TYPE(desc_in, &mp_type_tuple)) {
|
||||
return uctypes_struct_agg_size((mp_obj_tuple_t *)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size);
|
||||
} else if (MP_OBJ_IS_SMALL_INT(desc_in)) {
|
||||
|
@ -246,7 +254,8 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
|
|||
return total_size;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
|
||||
STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_t obj_in = args[0];
|
||||
mp_uint_t max_field_size = 0;
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &mp_type_bytearray)) {
|
||||
return mp_obj_len(obj_in);
|
||||
|
@ -255,15 +264,22 @@ STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
|
|||
// We can apply sizeof either to structure definition (a dict)
|
||||
// or to instantiated structure
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
|
||||
if (n_args != 1) {
|
||||
mp_raise_TypeError(NULL);
|
||||
}
|
||||
// Extract structure definition
|
||||
mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in);
|
||||
obj_in = obj->desc;
|
||||
layout_type = obj->flags;
|
||||
} else {
|
||||
if (n_args == 2) {
|
||||
layout_type = mp_obj_get_int(args[1]);
|
||||
}
|
||||
}
|
||||
mp_uint_t size = uctypes_struct_size(obj_in, layout_type, &max_field_size);
|
||||
return MP_OBJ_NEW_SMALL_INT(size);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_sizeof_obj, uctypes_struct_sizeof);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof);
|
||||
|
||||
static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
|
||||
char struct_type = big_endian ? '>' : '<';
|
||||
|
@ -325,7 +341,7 @@ STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
|
|||
return mp_obj_new_int_from_ll(((int64_t *)p)[index]);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
case FLOAT32:
|
||||
return mp_obj_new_float((mp_float_t)((float *)p)[index]);
|
||||
return mp_obj_new_float(((float *)p)[index]);
|
||||
case FLOAT64:
|
||||
return mp_obj_new_float(((double *)p)[index]);
|
||||
#endif
|
||||
|
@ -384,8 +400,11 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
|
|||
STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
|
||||
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// TODO: Support at least OrderedDict in addition
|
||||
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
|
||||
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)
|
||||
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
|
||||
&& !MP_OBJ_IS_TYPE(self->desc, &mp_type_ordereddict)
|
||||
#endif
|
||||
) {
|
||||
mp_raise_TypeError(translate("struct: no fields"));
|
||||
}
|
||||
|
||||
|
@ -589,6 +608,26 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
|
|||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_INT:
|
||||
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
if (agg_type == PTR) {
|
||||
byte *p = *(void **)self->addr;
|
||||
return mp_obj_new_int((mp_int_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
default:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
(void)flags;
|
||||
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
@ -637,6 +676,7 @@ STATIC const mp_obj_type_t uctypes_struct_type = {
|
|||
.make_new = uctypes_struct_make_new,
|
||||
.attr = uctypes_struct_attr,
|
||||
.subscr = uctypes_struct_subscr,
|
||||
.unary_op = uctypes_struct_unary_op,
|
||||
.buffer_p = { .get_buffer = uctypes_get_buffer },
|
||||
};
|
||||
|
||||
|
@ -695,6 +735,30 @@ STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, 4)) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UCTYPES_NATIVE_C_TYPES
|
||||
// C native type aliases. These depend on GCC-compatible predefined
|
||||
// preprocessor macros.
|
||||
#if __SIZEOF_SHORT__ == 2
|
||||
{ MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) },
|
||||
#endif
|
||||
#if __SIZEOF_INT__ == 4
|
||||
{ MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
|
||||
#endif
|
||||
#if __SIZEOF_LONG__ == 4
|
||||
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
|
||||
#elif __SIZEOF_LONG__ == 8
|
||||
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
|
||||
#endif
|
||||
#if __SIZEOF_LONG_LONG__ == 8
|
||||
{ MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
|
||||
#endif
|
||||
#endif // MICROPY_PY_UCTYPES_NATIVE_C_TYPES
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_PTR), MP_ROM_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ARRAY), MP_ROM_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) },
|
||||
};
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
|
||||
#if MICROPY_PY_UHASHLIB
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
#include "mbedtls/version.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA256
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
@ -22,13 +26,14 @@
|
|||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA1
|
||||
#if MICROPY_PY_UHASHLIB_SHA1 || MICROPY_PY_UHASHLIB_MD5
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
#include "lib/axtls/crypto/crypto.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
#include "mbedtls/md5.h"
|
||||
#include "mbedtls/sha1.h"
|
||||
#endif
|
||||
|
||||
|
@ -45,12 +50,18 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
|
|||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_arg_check_num(n_args, kw_args, 0, 1, false);
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
|
||||
#define mbedtls_sha256_update_ret mbedtls_sha256_update
|
||||
#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context));
|
||||
o->base.type = type;
|
||||
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
|
||||
mbedtls_sha256_starts((mbedtls_sha256_context *)&o->state, 0);
|
||||
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
|
@ -61,7 +72,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
|
|||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_sha256_update((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
|
||||
mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
@ -69,7 +80,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
|
|||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 32);
|
||||
mbedtls_sha256_finish((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
|
||||
mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
|
||||
|
@ -164,12 +175,19 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
|||
#endif
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
|
||||
#define mbedtls_sha1_update_ret mbedtls_sha1_update
|
||||
#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
|
||||
o->base.type = type;
|
||||
mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
|
||||
mbedtls_sha1_starts((mbedtls_sha1_context *)o->state);
|
||||
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
|
@ -180,7 +198,7 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
|||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_sha1_update((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
|
||||
mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
@ -188,7 +206,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
|||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 20);
|
||||
mbedtls_sha1_finish((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
|
||||
mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
|
||||
mbedtls_sha1_free((mbedtls_sha1_context *)self->state);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
|
@ -211,6 +229,93 @@ STATIC const mp_obj_type_t uhashlib_sha1_type = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_MD5
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX));
|
||||
o->base.type = type;
|
||||
MD5_Init((MD5_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, MD5_SIZE);
|
||||
MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
#endif // MICROPY_SSL_AXTLS
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#define mbedtls_md5_starts_ret mbedtls_md5_starts
|
||||
#define mbedtls_md5_update_ret mbedtls_md5_update
|
||||
#define mbedtls_md5_finish_ret mbedtls_md5_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context));
|
||||
o->base.type = type;
|
||||
mbedtls_md5_init((mbedtls_md5_context *)o->state);
|
||||
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 16);
|
||||
mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);
|
||||
mbedtls_md5_free((mbedtls_md5_context *)self->state);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
#endif // MICROPY_SSL_MBEDTLS
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_md5_update_obj, uhashlib_md5_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_md5_digest_obj, uhashlib_md5_digest);
|
||||
|
||||
STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_md5_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_md5_digest_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t uhashlib_md5_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_md5,
|
||||
.make_new = uhashlib_md5_make_new,
|
||||
.locals_dict = (void *)&uhashlib_md5_locals_dict,
|
||||
};
|
||||
#endif // MICROPY_PY_UHASHLIB_MD5
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
|
||||
#if MICROPY_PY_UHASHLIB_SHA256
|
||||
|
@ -219,6 +324,9 @@ STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
|
|||
#if MICROPY_PY_UHASHLIB_SHA1
|
||||
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_UHASHLIB_MD5
|
||||
{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globals_table);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
typedef struct _poll_obj_t {
|
||||
mp_obj_t obj;
|
||||
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, mp_uint_t arg, int *errcode);
|
||||
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
mp_uint_t flags;
|
||||
mp_uint_t flags_ret;
|
||||
} poll_obj_t;
|
||||
|
@ -33,7 +33,7 @@ typedef struct _poll_obj_t {
|
|||
STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) {
|
||||
for (mp_uint_t i = 0; i < obj_len; i++) {
|
||||
mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
if (elem->value == NULL) {
|
||||
if (elem->value == MP_OBJ_NULL) {
|
||||
// object not found; get its ioctl and add it to the poll list
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
|
||||
poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
|
||||
|
@ -41,27 +41,27 @@ STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_
|
|||
poll_obj->ioctl = stream_p->ioctl;
|
||||
poll_obj->flags = flags;
|
||||
poll_obj->flags_ret = 0;
|
||||
elem->value = poll_obj;
|
||||
elem->value = MP_OBJ_FROM_PTR(poll_obj);
|
||||
} else {
|
||||
// object exists; update its flags
|
||||
if (or_flags) {
|
||||
((poll_obj_t *)elem->value)->flags |= flags;
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
|
||||
} else {
|
||||
((poll_obj_t *)elem->value)->flags = flags;
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// poll each object in the map
|
||||
STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) {
|
||||
STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
|
||||
mp_uint_t n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < poll_map->alloc; ++i) {
|
||||
if (!MP_MAP_SLOT_IS_FILLED(poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)poll_map->table[i].value;
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value);
|
||||
int errcode;
|
||||
mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode);
|
||||
poll_obj->flags_ret = ret;
|
||||
|
@ -138,15 +138,15 @@ STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) {
|
|||
if (!MP_MAP_SLOT_IS_FILLED(&poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)poll_map.table[i].value;
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
|
||||
((mp_obj_list_t *)list_array[0])->items[rwx_len[0]++] = poll_obj->obj;
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
|
||||
}
|
||||
if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
|
||||
((mp_obj_list_t *)list_array[1])->items[rwx_len[1]++] = poll_obj->obj;
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
|
||||
}
|
||||
if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
|
||||
((mp_obj_list_t *)list_array[2])->items[rwx_len[2]++] = poll_obj->obj;
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
|
||||
}
|
||||
}
|
||||
mp_map_deinit(&poll_map);
|
||||
|
@ -171,7 +171,7 @@ typedef struct _mp_obj_poll_t {
|
|||
|
||||
/// \method register(obj[, eventmask])
|
||||
STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = args[0];
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t flags;
|
||||
if (n_args == 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
|
@ -185,7 +185,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
|
|||
|
||||
/// \method unregister(obj)
|
||||
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
|
||||
mp_obj_poll_t *self = self_in;
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
|
||||
// TODO raise KeyError if obj didn't exist in map
|
||||
return mp_const_none;
|
||||
|
@ -194,18 +194,18 @@ MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
|
|||
|
||||
/// \method modify(obj, eventmask)
|
||||
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
|
||||
mp_obj_poll_t *self = self_in;
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
((poll_obj_t *)elem->value)->flags = mp_obj_get_int(eventmask_in);
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
|
||||
|
||||
STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = args[0];
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
// work out timeout (its given already in ms)
|
||||
mp_uint_t timeout = -1;
|
||||
|
@ -238,18 +238,18 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
|
|||
return n_ready;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = args[0];
|
||||
STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t n_ready = poll_poll_internal(n_args, args);
|
||||
|
||||
// one or more objects are ready, or we had a timeout
|
||||
mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL);
|
||||
mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
|
||||
n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
|
||||
if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)self->poll_map.table[i].value;
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret != 0) {
|
||||
mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
|
||||
ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
|
||||
|
@ -259,7 +259,7 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return ret_list;
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
|
||||
|
||||
|
@ -292,7 +292,7 @@ STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
|
|||
if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)self->poll_map.table[i].value;
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret != 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
|
||||
t->items[0] = poll_obj->obj;
|
||||
|
@ -334,7 +334,7 @@ STATIC mp_obj_t select_poll(void) {
|
|||
mp_map_init(&poll->poll_map, 0);
|
||||
poll->iter_cnt = 0;
|
||||
poll->ret_tuple = MP_OBJ_NULL;
|
||||
return poll;
|
||||
return MP_OBJ_FROM_PTR(poll);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
|
||||
|
||||
|
|
|
@ -158,21 +158,13 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
|
|||
|
||||
STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
|
||||
(void)arg;
|
||||
switch (request) {
|
||||
case MP_STREAM_CLOSE:
|
||||
if (self->ssl_sock != NULL) {
|
||||
ssl_free(self->ssl_sock);
|
||||
ssl_ctx_free(self->ssl_ctx);
|
||||
self->ssl_sock = NULL;
|
||||
mp_stream_close(self->sock);
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) {
|
||||
ssl_free(self->ssl_sock);
|
||||
ssl_ctx_free(self->ssl_ctx);
|
||||
self->ssl_sock = NULL;
|
||||
}
|
||||
// Pass all requests down to the underlying socket
|
||||
return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
|
||||
|
@ -220,10 +212,10 @@ STATIC const mp_obj_type_t ussl_socket_type = {
|
|||
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
// TODO: Implement more args
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
|
||||
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
|
||||
};
|
||||
|
||||
// TODO: Check that sock implements stream protocol
|
||||
|
|
|
@ -249,23 +249,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
|
|||
|
||||
STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
|
||||
(void)arg;
|
||||
switch (request) {
|
||||
case MP_STREAM_CLOSE:
|
||||
mbedtls_pk_free(&self->pkey);
|
||||
mbedtls_x509_crt_free(&self->cert);
|
||||
mbedtls_x509_crt_free(&self->cacert);
|
||||
mbedtls_ssl_free(&self->ssl);
|
||||
mbedtls_ssl_config_free(&self->conf);
|
||||
mbedtls_ctr_drbg_free(&self->ctr_drbg);
|
||||
mbedtls_entropy_free(&self->entropy);
|
||||
mp_stream_close(self->sock);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
if (request == MP_STREAM_CLOSE) {
|
||||
mbedtls_pk_free(&self->pkey);
|
||||
mbedtls_x509_crt_free(&self->cert);
|
||||
mbedtls_x509_crt_free(&self->cacert);
|
||||
mbedtls_ssl_free(&self->ssl);
|
||||
mbedtls_ssl_config_free(&self->conf);
|
||||
mbedtls_ctr_drbg_free(&self->ctr_drbg);
|
||||
mbedtls_entropy_free(&self->entropy);
|
||||
}
|
||||
// Pass all requests down to the underlying socket
|
||||
return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "py/mphal.h"
|
||||
#endif
|
||||
#include "extmod/modwebsocket.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if MICROPY_PY_WEBREPL
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ int mp_uos_dupterm_rx_chr(void) {
|
|||
return buf[0];
|
||||
}
|
||||
} else {
|
||||
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
|
||||
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
|
|||
mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
|
||||
nlr_pop();
|
||||
} else {
|
||||
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
|
||||
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
extmod/vfs.c
11
extmod/vfs.c
|
@ -17,6 +17,10 @@
|
|||
#include "extmod/vfs_fat.h"
|
||||
#endif
|
||||
|
||||
#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX
|
||||
#include "extmod/vfs_posix.h"
|
||||
#endif
|
||||
|
||||
// For mp_vfs_proxy_call, the maximum number of additional args that can be passed.
|
||||
// A fixed maximum size is used to avoid the need for a costly variable array.
|
||||
#define PROXY_MAX_ARGS (2)
|
||||
|
@ -244,6 +248,13 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
|||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX
|
||||
// If the file is an integer then delegate straight to the POSIX handler
|
||||
if (MP_OBJ_IS_SMALL_INT(args[ARG_file].u_obj)) {
|
||||
return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj);
|
||||
return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t *)&args);
|
||||
}
|
||||
|
|
|
@ -172,6 +172,9 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
|
|||
}
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
#ifdef DTTOIF
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type));
|
||||
#else
|
||||
if (dirent->d_type == DT_DIR) {
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
|
||||
} else if (dirent->d_type == DT_REG) {
|
||||
|
@ -179,10 +182,12 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
|
|||
} else {
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// DT_UNKNOWN should have 0 value on any reasonable system
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
#endif
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_INO
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino);
|
||||
#else
|
||||
|
@ -200,6 +205,9 @@ STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
|
|||
iter->iternext = vfs_posix_ilistdir_it_iternext;
|
||||
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
|
||||
const char *path = vfs_posix_get_path_str(self, path_in);
|
||||
if (path[0] == '\0') {
|
||||
path = ".";
|
||||
}
|
||||
iter->dir = opendir(path);
|
||||
if (iter->dir == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
|
|
@ -30,12 +30,17 @@ typedef float float_t;
|
|||
typedef union {
|
||||
float f;
|
||||
struct {
|
||||
uint64_t m : 23;
|
||||
uint64_t e : 8;
|
||||
uint64_t s : 1;
|
||||
uint32_t m : 23;
|
||||
uint32_t e : 8;
|
||||
uint32_t s : 1;
|
||||
};
|
||||
} float_s_t;
|
||||
|
||||
int __signbitf(float f) {
|
||||
float_s_t u = {.f = f};
|
||||
return u.s;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
float copysignf(float x, float y) {
|
||||
float_s_t fx={.f = x};
|
||||
|
@ -55,10 +60,14 @@ static const float _M_LN2 = 0.6931472;
|
|||
float log2f(float x) { return logf(x) / (float)_M_LN2; }
|
||||
|
||||
float tanhf(float x) {
|
||||
if (isinf(x)) {
|
||||
return copysignf(1, x);
|
||||
int sign = 0;
|
||||
if (x < 0) {
|
||||
sign = 1;
|
||||
x = -x;
|
||||
}
|
||||
return sinhf(x) / coshf(x);
|
||||
x = expm1f(-2 * x);
|
||||
x = x / (x + 2);
|
||||
return sign ? x : -x;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
{
|
||||
float y;
|
||||
int local_signgam;
|
||||
if (!isfinite(x)) {
|
||||
/* special cases: tgammaf(nan)=nan, tgammaf(inf)=inf, tgammaf(-inf)=nan */
|
||||
return x + INFINITY;
|
||||
}
|
||||
y = expf(__ieee754_lgammaf_r(x,&local_signgam));
|
||||
if (local_signgam < 0) y = -y;
|
||||
#ifdef _IEEE_LIBM
|
||||
|
|
|
@ -4,6 +4,10 @@ functions.
|
|||
The files lgamma.c, log10.c and tanh.c are too small to have a meaningful
|
||||
copyright or license.
|
||||
|
||||
The file copysign.c contains a double version of the float copysignf provided
|
||||
in libm/math.c for use in DEBUG builds where the standard library copy is
|
||||
not available.
|
||||
|
||||
The rest of the files in this directory are copied from the musl library,
|
||||
v1.1.16, and, unless otherwise stated in the individual file, have the
|
||||
following copyright and MIT license:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016-2018 Damien P. George
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,33 +23,26 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_DRIVERS_BUS_SPI_H
|
||||
#define MICROPY_INCLUDED_DRIVERS_BUS_SPI_H
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "libm.h"
|
||||
|
||||
enum {
|
||||
MP_SPI_IOCTL_INIT,
|
||||
MP_SPI_IOCTL_DEINIT,
|
||||
};
|
||||
#ifndef NDEBUG
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
uint64_t m : 52;
|
||||
uint64_t e : 11;
|
||||
uint64_t s : 1;
|
||||
};
|
||||
} double_s_t;
|
||||
|
||||
typedef struct _mp_spi_proto_t {
|
||||
int (*ioctl)(void *self, uint32_t cmd);
|
||||
void (*transfer)(void *self, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
} mp_spi_proto_t;
|
||||
double copysign(double x, double y) {
|
||||
double_s_t dx={.d = x};
|
||||
double_s_t dy={.d = y};
|
||||
|
||||
typedef struct _mp_soft_spi_obj_t {
|
||||
uint32_t delay_half; // microsecond delay for half SCK period
|
||||
uint8_t polarity;
|
||||
uint8_t phase;
|
||||
mp_hal_pin_obj_t sck;
|
||||
mp_hal_pin_obj_t mosi;
|
||||
mp_hal_pin_obj_t miso;
|
||||
} mp_soft_spi_obj_t;
|
||||
// copy sign bit;
|
||||
dx.s = dy.s;
|
||||
|
||||
extern const mp_spi_proto_t mp_soft_spi_proto;
|
||||
|
||||
int mp_soft_spi_ioctl(void *self, uint32_t cmd);
|
||||
void mp_soft_spi_transfer(void *self, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
|
||||
#endif // MICROPY_INCLUDED_DRIVERS_BUS_SPI_H
|
||||
return dx.d;
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,12 @@
|
|||
#include <math.h>
|
||||
|
||||
double tanh(double x) {
|
||||
return sinh(x) / cosh(x);
|
||||
int sign = 0;
|
||||
if (x < 0) {
|
||||
sign = 1;
|
||||
x = -x;
|
||||
}
|
||||
x = expm1(-2 * x);
|
||||
x = x / (x + 2);
|
||||
return sign ? x : -x;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Daniel Campora
|
||||
* 2018 Tobias Badertscher
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "lib/utils/mpirq.h"
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PUBLIC DATA
|
||||
******************************************************************************/
|
||||
|
||||
const mp_arg_t mp_irq_init_args[] = {
|
||||
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
|
||||
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE DATA
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE PUBLIC FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent) {
|
||||
mp_irq_obj_t *self = m_new0(mp_irq_obj_t, 1);
|
||||
self->base.type = &mp_irq_type;
|
||||
self->methods = (mp_irq_methods_t *)methods;
|
||||
self->parent = parent;
|
||||
self->handler = mp_const_none;
|
||||
self->ishard = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
void mp_irq_handler(mp_irq_obj_t *self) {
|
||||
if (self->handler != mp_const_none) {
|
||||
if (self->ishard) {
|
||||
// When executing code within a handler we must lock the GC to prevent
|
||||
// any memory allocations.
|
||||
gc_lock();
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_call_function_1(self->handler, self->parent);
|
||||
nlr_pop();
|
||||
} else {
|
||||
// Uncaught exception; disable the callback so that it doesn't run again
|
||||
self->methods->trigger(self->parent, 0);
|
||||
self->handler = mp_const_none;
|
||||
printf("Uncaught exception in IRQ callback handler\n");
|
||||
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
}
|
||||
gc_unlock();
|
||||
} else {
|
||||
// Schedule call to user function
|
||||
mp_sched_schedule(self->handler, self->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings
|
||||
|
||||
STATIC mp_obj_t mp_irq_flags(mp_obj_t self_in) {
|
||||
mp_irq_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_FLAGS));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
|
||||
|
||||
STATIC mp_obj_t mp_irq_trigger(size_t n_args, const mp_obj_t *args) {
|
||||
mp_irq_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_obj_t ret_obj = mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_TRIGGERS));
|
||||
if (n_args == 2) {
|
||||
// Set trigger
|
||||
self->methods->trigger(self->parent, mp_obj_get_int(args[1]));
|
||||
}
|
||||
return ret_obj;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_irq_trigger_obj, 1, 2, mp_irq_trigger);
|
||||
|
||||
STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
mp_irq_handler(MP_OBJ_TO_PTR(self_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&mp_irq_trigger_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t mp_irq_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_irq,
|
||||
.call = mp_irq_call,
|
||||
.locals_dict = (mp_obj_dict_t *)&mp_irq_locals_dict,
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Daniel Campora
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H
|
||||
#define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE CONSTANTS
|
||||
******************************************************************************/
|
||||
|
||||
enum {
|
||||
MP_IRQ_ARG_INIT_handler = 0,
|
||||
MP_IRQ_ARG_INIT_trigger,
|
||||
MP_IRQ_ARG_INIT_hard,
|
||||
MP_IRQ_ARG_INIT_NUM_ARGS,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE TYPES
|
||||
******************************************************************************/
|
||||
|
||||
typedef mp_obj_t (*mp_irq_init_t)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
typedef mp_uint_t (*mp_irq_uint_method_one_uint_para_t)(mp_obj_t self, mp_uint_t trigger);
|
||||
typedef mp_uint_t (*mp_irq_int_method_one_para_t)(mp_obj_t self, mp_uint_t info_type);
|
||||
|
||||
enum {
|
||||
MP_IRQ_INFO_FLAGS,
|
||||
MP_IRQ_INFO_TRIGGERS,
|
||||
MP_IRQ_INFO_CNT
|
||||
};
|
||||
|
||||
typedef struct _mp_irq_methods_t {
|
||||
mp_irq_init_t init;
|
||||
mp_irq_uint_method_one_uint_para_t trigger;
|
||||
mp_irq_int_method_one_para_t info;
|
||||
} mp_irq_methods_t;
|
||||
|
||||
typedef struct _mp_irq_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_irq_methods_t *methods;
|
||||
mp_obj_t parent;
|
||||
mp_obj_t handler;
|
||||
bool ishard;
|
||||
} mp_irq_obj_t;
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE EXPORTED DATA
|
||||
******************************************************************************/
|
||||
|
||||
extern const mp_arg_t mp_irq_init_args[];
|
||||
extern const mp_obj_type_t mp_irq_type;
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PUBLIC FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent);
|
||||
void mp_irq_handler(mp_irq_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_USE_INTERNAL_PRINTF
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -39,6 +37,18 @@
|
|||
#include "py/formatfloat.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
int DEBUG_printf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = mp_vprintf(MICROPY_DEBUG_PRINTER, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_USE_INTERNAL_PRINTF
|
||||
|
||||
#undef putchar // Some stdlibs have a #define for putchar
|
||||
int printf(const char *fmt, ...);
|
||||
int vprintf(const char *fmt, va_list ap);
|
||||
|
@ -59,20 +69,6 @@ int vprintf(const char *fmt, va_list ap) {
|
|||
return mp_vprintf(&mp_plat_print, fmt, ap);
|
||||
}
|
||||
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
extern const mp_print_t MICROPY_DEBUG_PRINTER_DEST;
|
||||
int DEBUG_printf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
#ifndef MICROPY_DEBUG_PRINTER_DEST
|
||||
#define MICROPY_DEBUG_PRINTER_DEST mp_plat_print
|
||||
#endif
|
||||
int ret = mp_vprintf(&MICROPY_DEBUG_PRINTER_DEST, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
|
||||
int putchar(int c) {
|
||||
char chr = c;
|
||||
|
|
|
@ -129,7 +129,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
|
|||
mp_hal_stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
// check for SystemExit
|
||||
if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {
|
||||
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
|
||||
// at the moment, the value of SystemExit is unused
|
||||
ret = pyexec_system_exit;
|
||||
#if CIRCUITPY_ALARM
|
||||
|
@ -138,7 +138,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
|
|||
#endif
|
||||
} else {
|
||||
if ((mp_obj_t)nlr.ret_val != MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
|
||||
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
|
||||
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
}
|
||||
ret = PYEXEC_EXCEPTION;
|
||||
}
|
||||
|
@ -455,6 +455,12 @@ friendly_repl_reset:
|
|||
}
|
||||
#endif
|
||||
|
||||
// If the GC is locked at this point there is no way out except a reset,
|
||||
// so force the GC to be unlocked to help the user debug what went wrong.
|
||||
if (MP_STATE_MEM(gc_lock_depth) != 0) {
|
||||
MP_STATE_MEM(gc_lock_depth) = 0;
|
||||
}
|
||||
|
||||
vstr_reset(&line);
|
||||
int ret = readline(&line, ">>> ");
|
||||
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
|
||||
|
|
|
@ -172,7 +172,7 @@ STATIC const mp_obj_type_t stdio_buffer_obj_type = {
|
|||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &stdio_buffer_obj_stream_p,
|
||||
.locals_dict = (mp_obj_t)&stdio_locals_dict,
|
||||
.locals_dict = (mp_obj_dict_t *)&stdio_locals_dict,
|
||||
};
|
||||
|
||||
STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused
|
||||
|
|
|
@ -2304,10 +2304,6 @@ msgstr ""
|
|||
msgid "Version was invalid"
|
||||
msgstr ""
|
||||
|
||||
#: py/emitnative.c
|
||||
msgid "Viper functions don't currently support more than 4 arguments"
|
||||
msgstr ""
|
||||
|
||||
#: ports/stm/common-hal/microcontroller/Processor.c
|
||||
msgid "Voltage read timed out"
|
||||
msgstr ""
|
||||
|
@ -2387,11 +2383,6 @@ msgstr ""
|
|||
msgid "abort() called"
|
||||
msgstr ""
|
||||
|
||||
#: extmod/machine_mem.c
|
||||
#, c-format
|
||||
msgid "address %08x is not aligned to %d bytes"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/i2cperipheral/I2CPeripheral.c
|
||||
msgid "address out of bounds"
|
||||
msgstr ""
|
||||
|
@ -2400,6 +2391,10 @@ msgstr ""
|
|||
msgid "addresses is empty"
|
||||
msgstr ""
|
||||
|
||||
#: py/compile.c
|
||||
msgid "annotation must be an identifier"
|
||||
msgstr ""
|
||||
|
||||
#: py/modbuiltins.c
|
||||
msgid "arg is an empty sequence"
|
||||
msgstr ""
|
||||
|
@ -2582,6 +2577,10 @@ msgstr ""
|
|||
msgid "can't convert %q to %q"
|
||||
msgstr ""
|
||||
|
||||
#: py/runtime.c
|
||||
msgid "can't convert %q to int"
|
||||
msgstr ""
|
||||
|
||||
#: py/objstr.c
|
||||
msgid "can't convert '%q' object to %q implicitly"
|
||||
msgstr ""
|
||||
|
@ -2590,6 +2589,10 @@ msgstr ""
|
|||
msgid "can't convert to %q"
|
||||
msgstr ""
|
||||
|
||||
#: py/runtime.c
|
||||
msgid "can't convert to int"
|
||||
msgstr ""
|
||||
|
||||
#: py/objstr.c
|
||||
msgid "can't convert to str implicitly"
|
||||
msgstr ""
|
||||
|
@ -2993,7 +2996,7 @@ msgid "full"
|
|||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "function does not take keyword arguments"
|
||||
msgid "function doesn't take keyword arguments"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
|
@ -3048,6 +3051,10 @@ msgstr ""
|
|||
msgid "generator ignored GeneratorExit"
|
||||
msgstr ""
|
||||
|
||||
#: py/objgenerator.c
|
||||
msgid "generator raised StopIteration"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/_stage/Layer.c
|
||||
msgid "graphic must be 2048 bytes long"
|
||||
msgstr ""
|
||||
|
@ -3427,6 +3434,10 @@ msgstr ""
|
|||
msgid "need more than %d values to unpack"
|
||||
msgstr ""
|
||||
|
||||
#: py/modmath.c
|
||||
msgid "negative factorial"
|
||||
msgstr ""
|
||||
|
||||
#: py/objint_longlong.c py/objint_mpz.c py/runtime.c
|
||||
msgid "negative power with no float support"
|
||||
msgstr ""
|
||||
|
@ -3656,10 +3667,6 @@ msgstr ""
|
|||
msgid "palette_index should be an int"
|
||||
msgstr ""
|
||||
|
||||
#: py/compile.c
|
||||
msgid "parameter annotation must be an identifier"
|
||||
msgstr ""
|
||||
|
||||
#: py/emitinlinextensa.c
|
||||
msgid "parameters must be registers in sequence a2 to a5"
|
||||
msgstr ""
|
||||
|
@ -3715,6 +3722,7 @@ msgstr ""
|
|||
#: ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/adafruit_metro_esp32s2/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/artisense_rd00/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/atmegazero_esp32s2/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h
|
||||
#: ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h
|
||||
|
@ -4098,7 +4106,7 @@ msgstr ""
|
|||
msgid "unknown type"
|
||||
msgstr ""
|
||||
|
||||
#: py/emitnative.c
|
||||
#: py/compile.c
|
||||
msgid "unknown type '%q'"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ ifneq ($(findstring undefine,$(.FEATURES)),)
|
|||
override undefine COPT
|
||||
override undefine CFLAGS_EXTRA
|
||||
override undefine LDFLAGS_EXTRA
|
||||
override undefine MICROPY_FORCE_32BIT
|
||||
override undefine CROSS_COMPILE
|
||||
override undefine FROZEN_DIR
|
||||
override undefine FROZEN_MPY_DIR
|
||||
override undefine BUILD
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// empty file
|
||||
// prevent including extmod/virtpin.h
|
||||
#define mp_hal_pin_obj_t
|
||||
|
|
|
@ -22,8 +22,8 @@ UNAME_S := $(shell uname -s)
|
|||
# include py core make definitions
|
||||
include $(TOP)/py/py.mk
|
||||
|
||||
INC += -I.
|
||||
INC += -I$(TOP)
|
||||
INC += -I.
|
||||
INC += -I$(TOP)
|
||||
INC += -I$(BUILD)
|
||||
|
||||
# compiler settings
|
||||
|
@ -79,7 +79,7 @@ ifneq (,$(findstring mingw,$(COMPILER_TARGET)))
|
|||
SRC_C += fmode.c
|
||||
endif
|
||||
|
||||
OBJ = $(PY_O)
|
||||
OBJ = $(PY_CORE_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
|
||||
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
|
||||
|
|
|
@ -76,6 +76,9 @@ LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
|
|||
endif
|
||||
LDFLAGS = -Lbuild $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
|
||||
|
||||
# Flags to link with pthread library
|
||||
LIBPTHREAD = -lpthread
|
||||
|
||||
ifeq ($(MICROPY_FORCE_32BIT),1)
|
||||
# Note: you may need to install i386 versions of dependency packages,
|
||||
# starting with linux-libc-dev:i386
|
||||
|
@ -101,17 +104,17 @@ SRC_MOD += modusocket.c
|
|||
endif
|
||||
ifeq ($(MICROPY_PY_THREAD),1)
|
||||
CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0
|
||||
LDFLAGS_MOD += -lpthread
|
||||
LDFLAGS_MOD += $(LIBPTHREAD)
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_PY_FFI),1)
|
||||
|
||||
ifeq ($(MICROPY_STANDALONE),1)
|
||||
LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(TOP)/lib/libffi/build_dir/out/lib/libffi-*/include)
|
||||
LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include)
|
||||
ifeq ($(MICROPY_FORCE_32BIT),1)
|
||||
LIBFFI_LDFLAGS_MOD = $(TOP)/lib/libffi/build_dir/out/lib32/libffi.a
|
||||
LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a
|
||||
else
|
||||
LIBFFI_LDFLAGS_MOD = $(TOP)/lib/libffi/build_dir/out/lib/libffi.a
|
||||
LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a
|
||||
endif
|
||||
else
|
||||
LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi)
|
||||
|
@ -141,7 +144,6 @@ SRC_C += \
|
|||
mpthreadport.c \
|
||||
input.c \
|
||||
file.c \
|
||||
modmachine.c \
|
||||
modos.c \
|
||||
moduos_vfs.c \
|
||||
modtime.c \
|
||||
|
@ -156,12 +158,6 @@ SRC_C += \
|
|||
supervisor/shared/translate.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
PY_EXTMOD_O_BASENAME += \
|
||||
extmod/machine_mem.o \
|
||||
extmod/machine_pinbase.o \
|
||||
extmod/machine_signal.o \
|
||||
extmod/machine_pulse.o \
|
||||
|
||||
LIB_SRC_C = $(addprefix lib/,\
|
||||
$(LIB_SRC_C_EXTRA) \
|
||||
timeutils/timeutils.c \
|
||||
|
@ -232,8 +228,7 @@ nanbox:
|
|||
CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_nanbox.h>"' \
|
||||
BUILD=build-nanbox \
|
||||
PROG=micropython_nanbox \
|
||||
MICROPY_FORCE_32BIT=1 \
|
||||
MICROPY_PY_USSL=0
|
||||
MICROPY_FORCE_32BIT=1
|
||||
|
||||
freedos:
|
||||
$(MAKE) \
|
||||
|
@ -264,9 +259,9 @@ coverage:
|
|||
|
||||
coverage_test: coverage
|
||||
$(eval DIRNAME=ports/$(notdir $(CURDIR)))
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs -d thread
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --auto-jobs --emit native
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -j1
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -j1 -d thread
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -j1 --emit native
|
||||
cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -j1 --via-mpy -d basics float
|
||||
cat $(TOP)/tests/basics/0prelim.py | ./micropython_coverage | grep -q 'abc'
|
||||
gcov -o build-coverage/py $(TOP)/py/*.c
|
||||
|
@ -297,23 +292,19 @@ endif
|
|||
|
||||
deplibs: libffi axtls
|
||||
|
||||
libffi: $(BUILD)/lib/libffi/include/ffi.h
|
||||
|
||||
$(TOP)/lib/libffi/configure: $(TOP)/lib/libffi/autogen.sh
|
||||
cd $(TOP)/lib/libffi; ./autogen.sh
|
||||
|
||||
# install-exec-recursive & install-data-am targets are used to avoid building
|
||||
# docs and depending on makeinfo
|
||||
libffi:
|
||||
cd $(TOP)/lib/libffi; git clean -d -x -f
|
||||
cd $(TOP)/lib/libffi; ./autogen.sh
|
||||
mkdir -p $(TOP)/lib/libffi/build_dir; cd $(TOP)/lib/libffi/build_dir; \
|
||||
../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \
|
||||
$(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure
|
||||
mkdir -p $(BUILD)/lib/libffi; cd $(BUILD)/lib/libffi; \
|
||||
$(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \
|
||||
$(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am
|
||||
|
||||
axtls: $(BUILD)/libaxtls.a
|
||||
|
||||
$(BUILD)/libaxtls.a: $(TOP)/lib/axtls/README | $(OBJ_DIRS)
|
||||
cd $(TOP)/lib/axtls; cp config/upyconfig config/.config
|
||||
cd $(TOP)/lib/axtls; $(MAKE) oldconfig -B
|
||||
cd $(TOP)/lib/axtls; $(MAKE) clean
|
||||
cd $(TOP)/lib/axtls; $(MAKE) all CC="$(CC)" LD="$(LD)"
|
||||
cp $(TOP)/lib/axtls/_stage/libaxtls.a $@
|
||||
axtls: $(TOP)/lib/axtls/README
|
||||
|
||||
$(TOP)/lib/axtls/README:
|
||||
@echo "You cloned without --recursive, fetching submodules for you."
|
||||
|
|
|
@ -125,6 +125,8 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
|
|||
o->fd = -1;
|
||||
#endif
|
||||
return 0;
|
||||
case MP_STREAM_GET_FILENO:
|
||||
return o->fd;
|
||||
default:
|
||||
*errcode = EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
|
|
|
@ -511,9 +511,6 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
|
||||
|
||||
#if defined(MICROPY_UNIX_COVERAGE)
|
||||
|
|
|
@ -117,6 +117,10 @@ STATIC ffi_type *char2ffi_type(char c) {
|
|||
return &ffi_type_slong;
|
||||
case 'L':
|
||||
return &ffi_type_ulong;
|
||||
case 'q':
|
||||
return &ffi_type_sint64;
|
||||
case 'Q':
|
||||
return &ffi_type_uint64;
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
case 'f':
|
||||
return &ffi_type_float;
|
||||
|
|
|
@ -118,7 +118,7 @@ STATIC void print_jobject(const mp_print_t *print, jobject obj) {
|
|||
// jclass
|
||||
|
||||
STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_jclass_t *self = self_in;
|
||||
mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (kind == PRINT_REPR) {
|
||||
mp_printf(print, "<jclass @%p \"", self->cls);
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
|
|||
STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) {
|
||||
if (dest[0] == MP_OBJ_NULL) {
|
||||
// load attribute
|
||||
mp_obj_jclass_t *self = self_in;
|
||||
mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const char *attr = qstr_str(attr_in);
|
||||
|
||||
jstring field_name = JJ(NewStringUTF, attr);
|
||||
|
@ -151,7 +151,7 @@ STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) {
|
|||
o->meth = NULL;
|
||||
o->obj = self->cls;
|
||||
o->is_static = true;
|
||||
dest[0] = o;
|
||||
dest[0] = MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
|||
if (n_kw != 0) {
|
||||
mp_raise_TypeError("kwargs not supported");
|
||||
}
|
||||
mp_obj_jclass_t *self = self_in;
|
||||
mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
jarray methods = JJ(CallObjectMethod, self->cls, Class_getConstructors_mid);
|
||||
|
||||
|
@ -186,13 +186,13 @@ STATIC mp_obj_t new_jclass(jclass jc) {
|
|||
mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t);
|
||||
o->base.type = &jclass_type;
|
||||
o->cls = jc;
|
||||
return o;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
// jobject
|
||||
|
||||
STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_jobject_t *self = self_in;
|
||||
mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (kind == PRINT_REPR) {
|
||||
mp_printf(print, "<jobject @%p \"", self->obj);
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
|||
STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) {
|
||||
if (dest[0] == MP_OBJ_NULL) {
|
||||
// load attribute
|
||||
mp_obj_jobject_t *self = self_in;
|
||||
mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
const char *attr = qstr_str(attr_in);
|
||||
jclass obj_class = JJ(GetObjectClass, self->obj);
|
||||
|
@ -229,7 +229,7 @@ STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) {
|
|||
o->meth = NULL;
|
||||
o->obj = self->obj;
|
||||
o->is_static = false;
|
||||
dest[0] = o;
|
||||
dest[0] = MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ STATIC void get_jclass_name(jobject obj, char *buf) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_jobject_t *self = self_in;
|
||||
mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_uint_t idx = mp_obj_get_int(index);
|
||||
char class_name[64];
|
||||
get_jclass_name(self->obj, class_name);
|
||||
|
@ -292,7 +292,7 @@ STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
|
|||
}
|
||||
|
||||
STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
mp_obj_jobject_t *self = self_in;
|
||||
mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL:
|
||||
case MP_UNARY_OP_LEN: {
|
||||
|
@ -316,9 +316,9 @@ MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor);
|
|||
|
||||
// .getiter special method which returns iterator which works in terms
|
||||
// of object subscription.
|
||||
STATIC mp_obj_t subscr_getiter(mp_obj_t self_in) {
|
||||
mp_obj_t dest[2] = {(mp_obj_t)&subscr_load_adaptor_obj, self_in};
|
||||
return mp_obj_new_getitem_iter(dest);
|
||||
STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
mp_obj_t dest[2] = {MP_OBJ_FROM_PTR(&subscr_load_adaptor_obj), self_in};
|
||||
return mp_obj_new_getitem_iter(dest, iter_buf);
|
||||
}
|
||||
|
||||
STATIC const mp_obj_type_t jobject_type = {
|
||||
|
@ -346,7 +346,7 @@ STATIC mp_obj_t new_jobject(jobject jo) {
|
|||
mp_obj_jobject_t *o = m_new_obj(mp_obj_jobject_t);
|
||||
o->base.type = &jobject_type;
|
||||
o->obj = jo;
|
||||
return o;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ STATIC mp_obj_t new_jobject(jobject jo) {
|
|||
|
||||
STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_jmethod_t *self = self_in;
|
||||
mp_obj_jmethod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// Variable value printed as cast to int
|
||||
mp_printf(print, "<jmethod '%s'>", qstr_str(self->name));
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) {
|
|||
if (!is_object) {
|
||||
return false;
|
||||
}
|
||||
mp_obj_jobject_t *jo = arg;
|
||||
mp_obj_jobject_t *jo = MP_OBJ_TO_PTR(arg);
|
||||
if (!MATCH(expected_type, "java.lang.Object")) {
|
||||
char class_name[64];
|
||||
get_jclass_name(jo->obj, class_name);
|
||||
|
@ -490,8 +490,8 @@ STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool
|
|||
// printf("name=%p meth_name=%s\n", name, meth_name);
|
||||
|
||||
bool found = true;
|
||||
for (int i = 0; i < n_args && *arg_types != ')'; i++) {
|
||||
if (!py2jvalue(&arg_types, args[i], &jargs[i])) {
|
||||
for (size_t j = 0; j < n_args && *arg_types != ')'; j++) {
|
||||
if (!py2jvalue(&arg_types, args[j], &jargs[j])) {
|
||||
goto next_method;
|
||||
}
|
||||
|
||||
|
@ -507,13 +507,12 @@ STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool
|
|||
if (found) {
|
||||
// printf("found!\n");
|
||||
jmethodID method_id = JJ(FromReflectedMethod, meth);
|
||||
jobject res;
|
||||
mp_obj_t ret;
|
||||
if (is_constr) {
|
||||
JJ(ReleaseStringUTFChars, name_o, decl);
|
||||
res = JJ(NewObjectA, obj, method_id, jargs);
|
||||
jobject res = JJ(NewObjectA, obj, method_id, jargs);
|
||||
return new_jobject(res);
|
||||
} else {
|
||||
mp_obj_t ret;
|
||||
if (MATCH(ret_type, "void")) {
|
||||
JJ(CallVoidMethodA, obj, method_id, jargs);
|
||||
check_exception();
|
||||
|
@ -527,7 +526,7 @@ STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool
|
|||
check_exception();
|
||||
ret = mp_obj_new_bool(res);
|
||||
} else if (is_object_type(ret_type)) {
|
||||
res = JJ(CallObjectMethodA, obj, method_id, jargs);
|
||||
jobject res = JJ(CallObjectMethodA, obj, method_id, jargs);
|
||||
check_exception();
|
||||
ret = new_jobject(res);
|
||||
} else {
|
||||
|
@ -556,7 +555,7 @@ STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
|||
if (n_kw != 0) {
|
||||
mp_raise_TypeError("kwargs not supported");
|
||||
}
|
||||
mp_obj_jmethod_t *self = self_in;
|
||||
mp_obj_jmethod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
const char *name = qstr_str(self->name);
|
||||
// jstring meth_name = JJ(NewStringUTF, name);
|
||||
|
@ -585,7 +584,7 @@ STATIC const mp_obj_type_t jmethod_type = {
|
|||
#define LIBJVM_SO "libjvm.so"
|
||||
#endif
|
||||
|
||||
STATIC void create_jvm() {
|
||||
STATIC void create_jvm(void) {
|
||||
JavaVMInitArgs args;
|
||||
JavaVMOption options;
|
||||
options.optionString = "-Djava.class.path=.";
|
||||
|
@ -648,7 +647,7 @@ STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) {
|
|||
mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t);
|
||||
o->base.type = &jclass_type;
|
||||
o->cls = cls;
|
||||
return o;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls);
|
||||
|
||||
|
@ -661,7 +660,7 @@ STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) {
|
|||
|
||||
if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) {
|
||||
|
||||
mp_obj_jclass_t *jcls = type_in;
|
||||
mp_obj_jclass_t *jcls = MP_OBJ_TO_PTR(type_in);
|
||||
res = JJ(NewObjectArray, size, jcls->cls, NULL);
|
||||
|
||||
} else if (MP_OBJ_IS_STR(type_in)) {
|
||||
|
@ -700,8 +699,8 @@ STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) {
|
|||
MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array);
|
||||
|
||||
|
||||
STATIC mp_obj_t mod_jni_env() {
|
||||
return mp_obj_new_int((mp_int_t)env);
|
||||
STATIC mp_obj_t mod_jni_env(void) {
|
||||
return mp_obj_new_int((mp_int_t)(uintptr_t)env);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env);
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/vfs.h"
|
||||
#include "extmod/misc.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
@ -106,16 +107,21 @@ STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mod_os_unlink(mp_obj_t path_in) {
|
||||
STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) {
|
||||
const char *path = mp_obj_str_get_str(path_in);
|
||||
|
||||
// Note that POSIX requires remove() to be able to delete a directory
|
||||
// too (act as rmdir()). This is POSIX extenstion to ANSI C semantics
|
||||
// of that function. But Python remove() follows ANSI C, and explicitly
|
||||
// required to raise exception on attempt to remove a directory. Thus,
|
||||
// call POSIX unlink() here.
|
||||
int r = unlink(path);
|
||||
|
||||
RAISE_ERRNO(r, errno);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_unlink_obj, mod_os_unlink);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_remove_obj, mod_os_remove);
|
||||
|
||||
STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) {
|
||||
const char *cmd = mp_obj_str_get_str(cmd_in);
|
||||
|
@ -172,12 +178,24 @@ STATIC mp_obj_t listdir_next(mp_obj_t self_in) {
|
|||
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
|
||||
t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name));
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type);
|
||||
#ifdef DTTOIF
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type));
|
||||
#else
|
||||
if (dirent->d_type == DT_DIR) {
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
|
||||
} else if (dirent->d_type == DT_REG) {
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG);
|
||||
} else {
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// DT_UNKNOWN should have 0 value on any reasonable system
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
#endif
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_INO
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino);
|
||||
#else
|
||||
|
@ -217,7 +235,7 @@ STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mod_os_statvfs_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mod_os_unlink_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mod_os_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) },
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <poll.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/objtuple.h"
|
||||
|
@ -65,19 +66,15 @@ typedef struct _mp_obj_poll_t {
|
|||
} mp_obj_poll_t;
|
||||
|
||||
STATIC int get_fd(mp_obj_t fdlike) {
|
||||
int fd;
|
||||
// Shortcut for fdfile compatible types
|
||||
if (MP_OBJ_IS_TYPE(fdlike, &mp_type_fileio)
|
||||
#if MICROPY_PY_SOCKET
|
||||
|| MP_OBJ_IS_TYPE(fdlike, &mp_type_socket)
|
||||
#endif
|
||||
) {
|
||||
mp_obj_fdfile_t *fdfile = MP_OBJ_TO_PTR(fdlike);
|
||||
fd = fdfile->fd;
|
||||
} else {
|
||||
fd = mp_obj_get_int(fdlike);
|
||||
if (MP_OBJ_IS_OBJ(fdlike)) {
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(fdlike, MP_STREAM_OP_IOCTL);
|
||||
int err;
|
||||
mp_uint_t res = stream_p->ioctl(fdlike, MP_STREAM_GET_FILENO, 0, &err);
|
||||
if (res != MP_STREAM_ERROR) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
return mp_obj_get_int(fdlike);
|
||||
}
|
||||
|
||||
/// \method register(obj[, eventmask])
|
||||
|
@ -161,13 +158,13 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas
|
|||
for (int i = self->len - 1; i >= 0; i--) {
|
||||
if (entries->fd == fd) {
|
||||
entries->events = mp_obj_get_int(eventmask_in);
|
||||
break;
|
||||
return mp_const_none;
|
||||
}
|
||||
entries++;
|
||||
}
|
||||
|
||||
// TODO raise KeyError if obj didn't exist in map
|
||||
return mp_const_none;
|
||||
// obj doesn't exist in poller
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
|
@ -67,6 +68,7 @@
|
|||
typedef struct _mp_obj_socket_t {
|
||||
mp_obj_base_t base;
|
||||
int fd;
|
||||
bool blocking;
|
||||
} mp_obj_socket_t;
|
||||
|
||||
const mp_obj_type_t mp_type_socket;
|
||||
|
@ -80,6 +82,7 @@ STATIC mp_obj_socket_t *socket_new(int fd) {
|
|||
mp_obj_socket_t *o = m_new_obj(mp_obj_socket_t);
|
||||
o->base.type = &mp_type_socket;
|
||||
o->fd = fd;
|
||||
o->blocking = true;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -94,7 +97,14 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
|
|||
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
mp_int_t r = read(o->fd, buf, size);
|
||||
if (r == -1) {
|
||||
*errcode = errno;
|
||||
int err = errno;
|
||||
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
||||
// timed out, and need to convert that to ETIMEDOUT.
|
||||
if (err == EAGAIN && o->blocking) {
|
||||
err = MP_ETIMEDOUT;
|
||||
}
|
||||
|
||||
*errcode = err;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return r;
|
||||
|
@ -104,7 +114,14 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
|
|||
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
mp_int_t r = write(o->fd, buf, size);
|
||||
if (r == -1) {
|
||||
*errcode = errno;
|
||||
int err = errno;
|
||||
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
||||
// timed out, and need to convert that to ETIMEDOUT.
|
||||
if (err == EAGAIN && o->blocking) {
|
||||
err = MP_ETIMEDOUT;
|
||||
}
|
||||
|
||||
*errcode = err;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return r;
|
||||
|
@ -125,6 +142,9 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
|
|||
close(self->fd);
|
||||
return 0;
|
||||
|
||||
case MP_STREAM_GET_FILENO:
|
||||
return self->fd;
|
||||
|
||||
default:
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
|
@ -309,10 +329,49 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
|
|||
}
|
||||
flags = fcntl(self->fd, F_SETFL, flags);
|
||||
RAISE_ERRNO(flags, errno);
|
||||
self->blocking = val;
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
|
||||
|
||||
STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
||||
mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
struct timeval tv = {0,};
|
||||
bool new_blocking = true;
|
||||
|
||||
if (timeout_in == mp_const_none) {
|
||||
setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, NULL, 0);
|
||||
setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, NULL, 0);
|
||||
} else {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t val = mp_obj_get_float(timeout_in);
|
||||
double ipart;
|
||||
tv.tv_usec = round(modf(val, &ipart) * 1000000);
|
||||
tv.tv_sec = ipart;
|
||||
#else
|
||||
tv.tv_sec = mp_obj_get_int(timeout_in);
|
||||
#endif
|
||||
|
||||
// For SO_RCVTIMEO/SO_SNDTIMEO, zero timeout means infinity, but
|
||||
// for Python API it means non-blocking.
|
||||
if (tv.tv_sec == 0 && tv.tv_usec == 0) {
|
||||
new_blocking = false;
|
||||
} else {
|
||||
setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&tv, sizeof(struct timeval));
|
||||
setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO,
|
||||
&tv, sizeof(struct timeval));
|
||||
}
|
||||
}
|
||||
|
||||
if (self->blocking != new_blocking) {
|
||||
socket_setblocking(self_in, mp_obj_new_bool(new_blocking));
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
|
||||
|
||||
STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
|
||||
// TODO: CPython explicitly says that closing returned object doesn't close
|
||||
// the original socket (Python2 at all says that fd is dup()ed). But we
|
||||
|
@ -368,6 +427,7 @@ STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define MICROPY_DEBUG_PRINTERS (1)
|
||||
// Printing debug to stderr may give tests which
|
||||
// check stdout a chance to pass, etc.
|
||||
#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print
|
||||
#define MICROPY_DEBUG_PRINTER (&mp_stderr_print)
|
||||
#define MICROPY_READER_POSIX (1)
|
||||
#define MICROPY_USE_READLINE_HISTORY (1)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
|
@ -125,7 +125,9 @@
|
|||
#define MICROPY_PY_UTIMEQ (1)
|
||||
#define MICROPY_PY_UHASHLIB (1)
|
||||
#if MICROPY_PY_USSL
|
||||
#define MICROPY_PY_UHASHLIB_MD5 (1)
|
||||
#define MICROPY_PY_UHASHLIB_SHA1 (1)
|
||||
#define MICROPY_PY_UCRYPTOLIB (1)
|
||||
#endif
|
||||
#define MICROPY_PY_UBINASCII (1)
|
||||
#define MICROPY_PY_UBINASCII_CRC32 (1)
|
||||
|
@ -133,9 +135,9 @@
|
|||
#ifndef MICROPY_PY_USELECT_POSIX
|
||||
#define MICROPY_PY_USELECT_POSIX (1)
|
||||
#endif
|
||||
#define MICROPY_PY_WEBSOCKET (1)
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
#define MICROPY_PY_MACHINE_PULSE (1)
|
||||
#define MICROPY_PY_WEBSOCKET (0)
|
||||
#define MICROPY_PY_MACHINE (0)
|
||||
#define MICROPY_PY_MACHINE_PULSE (0)
|
||||
#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr
|
||||
#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr
|
||||
|
||||
|
@ -189,6 +191,11 @@ extern const struct _mp_obj_module_t mp_module_jni;
|
|||
#else
|
||||
#define MICROPY_PY_FFI_DEF
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE
|
||||
#define MICROPY_PY_MACHINE_DEF { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) },
|
||||
#else
|
||||
#define MICROPY_PY_MACHINE_DEF
|
||||
#endif
|
||||
#if MICROPY_PY_JNI
|
||||
#define MICROPY_PY_JNI_DEF { MP_ROM_QSTR(MP_QSTR_jni), MP_ROM_PTR(&mp_module_jni) },
|
||||
#else
|
||||
|
@ -220,7 +227,7 @@ extern const struct _mp_obj_module_t mp_module_jni;
|
|||
MICROPY_PY_JNI_DEF \
|
||||
MICROPY_PY_UTIME_DEF \
|
||||
MICROPY_PY_SOCKET_DEF \
|
||||
{ MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
|
||||
MICROPY_PY_MACHINE_DEF \
|
||||
MICROPY_PY_UOS_DEF \
|
||||
MICROPY_PY_USELECT_DEF \
|
||||
MICROPY_PY_TERMIOS_DEF \
|
||||
|
|
|
@ -24,11 +24,11 @@ MICROPY_PY_SOCKET = 1
|
|||
MICROPY_PY_FFI = 1
|
||||
|
||||
# ussl module requires one of the TLS libraries below
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_PY_USSL = 0
|
||||
# axTLS has minimal size and fully integrated with MicroPython, but
|
||||
# implements only a subset of modern TLS functionality, so may have
|
||||
# problems with some servers.
|
||||
MICROPY_SSL_AXTLS = 1
|
||||
MICROPY_SSL_AXTLS = 0
|
||||
# mbedTLS is more up to date and complete implementation, but also
|
||||
# more bloated. Configuring and building of mbedTLS should be done
|
||||
# outside of MicroPython, it can just link with mbedTLS library.
|
||||
|
|
|
@ -32,23 +32,32 @@
|
|||
|
||||
#include <mpconfigport.h>
|
||||
|
||||
#define MICROPY_OPT_MATH_FACTORIAL (1)
|
||||
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
|
||||
#define MICROPY_ENABLE_SCHEDULER (1)
|
||||
#define MICROPY_READER_VFS (1)
|
||||
#define MICROPY_MODULE_GETATTR (1)
|
||||
#define MICROPY_PY_DELATTR_SETATTR (1)
|
||||
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
|
||||
#define MICROPY_PY_BUILTINS_RANGE_BINOP (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
|
||||
#define MICROPY_PY_SYS_GETSIZEOF (1)
|
||||
#define MICROPY_PY_MATH_FACTORIAL (1)
|
||||
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
|
||||
#define MICROPY_PY_IO_BUFFEREDWRITER (1)
|
||||
#define MICROPY_PY_IO_RESOURCE_STREAM (1)
|
||||
#define MICROPY_PY_URE_MATCH_GROUPS (1)
|
||||
#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
|
||||
#define MICROPY_PY_URE_SUB (1)
|
||||
#define MICROPY_VFS_POSIX (1)
|
||||
#undef MICROPY_VFS_FAT
|
||||
#define MICROPY_VFS_FAT (1)
|
||||
#define MICROPY_FATFS_USE_LABEL (1)
|
||||
#define MICROPY_PY_FRAMEBUF (1)
|
||||
#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1)
|
||||
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
|
||||
#define MICROPY_PY_UCRYPTOLIB (1)
|
||||
|
||||
// TODO these should be generic, not bound to fatfs
|
||||
#define mp_type_fileio mp_type_vfs_posix_fileio
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#define MICROPY_PY_BUILTINS_REVERSED (0)
|
||||
#define MICROPY_PY_BUILTINS_SET (0)
|
||||
#define MICROPY_PY_BUILTINS_SLICE (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_COUNT (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_OP_MODULO (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (0)
|
||||
#define MICROPY_PY_BUILTINS_MIN_MAX (0)
|
||||
|
|
|
@ -31,27 +31,20 @@
|
|||
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
|
||||
void mp_arg_check_num(size_t n_args, mp_map_t *kw_args, size_t n_args_min, size_t n_args_max, bool takes_kw) {
|
||||
size_t n_kw = 0;
|
||||
if (kw_args != NULL) {
|
||||
n_kw = kw_args->used;
|
||||
}
|
||||
mp_arg_check_num_kw_array(n_args, n_kw, n_args_min, n_args_max, takes_kw);
|
||||
}
|
||||
|
||||
void mp_arg_check_num_kw_array(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {
|
||||
// NOTE(tannewt): This prevents this function from being optimized away.
|
||||
// Without it, functions can crash when reading invalid args.
|
||||
__asm volatile ("");
|
||||
void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig) {
|
||||
// TODO maybe take the function name as an argument so we can print nicer error messages
|
||||
|
||||
if (n_kw > 0 && !takes_kw) {
|
||||
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
|
||||
mp_arg_error_terse_mismatch();
|
||||
#else
|
||||
mp_raise_TypeError(translate("function does not take keyword arguments"));
|
||||
#endif
|
||||
// The reverse of MP_OBJ_FUN_MAKE_SIG
|
||||
bool takes_kw = sig & 1;
|
||||
size_t n_args_min = sig >> 17;
|
||||
size_t n_args_max = (sig >> 1) & 0xffff;
|
||||
|
||||
if (n_kw && !takes_kw) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_arg_error_terse_mismatch();
|
||||
} else {
|
||||
mp_raise_TypeError(translate("function doesn't take keyword arguments"));
|
||||
}
|
||||
}
|
||||
|
||||
if (n_args_min == n_args_max) {
|
||||
|
@ -85,6 +78,18 @@ void mp_arg_check_num_kw_array(size_t n_args, size_t n_kw, size_t n_args_min, si
|
|||
}
|
||||
}
|
||||
|
||||
inline void mp_arg_check_num(size_t n_args, mp_map_t *kw_args, size_t n_args_min, size_t n_args_max, bool takes_kw) {
|
||||
size_t n_kw = 0;
|
||||
if (kw_args != NULL) {
|
||||
n_kw = kw_args->used;
|
||||
}
|
||||
mp_arg_check_num_sig(n_args, n_kw, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw));
|
||||
}
|
||||
|
||||
inline void mp_arg_check_num_kw_array(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {
|
||||
mp_arg_check_num_sig(n_args, n_kw, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw));
|
||||
}
|
||||
|
||||
void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {
|
||||
size_t pos_found = 0, kws_found = 0;
|
||||
for (size_t i = 0; i < n_allowed; i++) {
|
||||
|
|
35
py/asmarm.c
35
py/asmarm.c
|
@ -273,6 +273,21 @@ void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) {
|
|||
emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2));
|
||||
}
|
||||
|
||||
void asm_arm_mov_reg_pcrel(asm_arm_t *as, uint reg_dest, uint label) {
|
||||
assert(label < as->base.max_num_labels);
|
||||
mp_uint_t dest = as->base.label_offsets[label];
|
||||
mp_int_t rel = dest - as->base.code_offset;
|
||||
rel -= 12 + 8; // adjust for load of rel, and then PC+8 prefetch of add_reg_reg_reg
|
||||
|
||||
// To load rel int reg_dest, insert immediate into code and jump over it
|
||||
emit_al(as, 0x59f0000 | (reg_dest << 12)); // ldr rd, [pc]
|
||||
emit_al(as, 0xa000000); // b pc
|
||||
emit(as, rel);
|
||||
|
||||
// Do reg_dest += PC
|
||||
asm_arm_add_reg_reg_reg(as, reg_dest, reg_dest, ASM_ARM_REG_PC);
|
||||
}
|
||||
|
||||
void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs) {
|
||||
// mov rd, rd, lsl rs
|
||||
emit_al(as, 0x1a00010 | (rd << 12) | (rs << 8) | rd);
|
||||
|
@ -347,19 +362,15 @@ void asm_arm_b_label(asm_arm_t *as, uint label) {
|
|||
asm_arm_bcc_label(as, ASM_ARM_CC_AL, label);
|
||||
}
|
||||
|
||||
void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {
|
||||
// If the table offset fits into the ldr instruction
|
||||
if (fun_id < (0x1000 / 4)) {
|
||||
emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_LR, ASM_ARM_REG_PC)); // mov lr, pc
|
||||
emit_al(as, 0x597f000 | (fun_id << 2)); // ldr pc, [r7, #fun_id*4]
|
||||
return;
|
||||
}
|
||||
void asm_arm_bl_ind(asm_arm_t *as, uint fun_id, uint reg_temp) {
|
||||
// The table offset should fit into the ldr instruction
|
||||
assert(fun_id < (0x1000 / 4));
|
||||
emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_LR, ASM_ARM_REG_PC)); // mov lr, pc
|
||||
emit_al(as, 0x597f000 | (fun_id << 2)); // ldr pc, [r7, #fun_id*4]
|
||||
}
|
||||
|
||||
emit_al(as, 0x59f0004 | (reg_temp << 12)); // ldr rd, [pc, #4]
|
||||
// Set lr after fun_ptr
|
||||
emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_LR, ASM_ARM_REG_PC, 4)); // add lr, pc, #4
|
||||
emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_PC, reg_temp)); // mov pc, reg_temp
|
||||
emit(as, (uint)fun_ptr);
|
||||
void asm_arm_bx_reg(asm_arm_t *as, uint reg_src) {
|
||||
emit_al(as, 0x012fff10 | reg_src);
|
||||
}
|
||||
|
||||
#endif // MICROPY_EMIT_ARM
|
||||
|
|
19
py/asmarm.h
19
py/asmarm.h
|
@ -98,6 +98,7 @@ void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
|
|||
void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
|
||||
void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
|
||||
void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num);
|
||||
void asm_arm_mov_reg_pcrel(asm_arm_t *as, uint reg_dest, uint label);
|
||||
void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs);
|
||||
void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs);
|
||||
|
||||
|
@ -120,7 +121,11 @@ void asm_arm_pop(asm_arm_t *as, uint reglist);
|
|||
// control flow
|
||||
void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label);
|
||||
void asm_arm_b_label(asm_arm_t *as, uint label);
|
||||
void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp);
|
||||
void asm_arm_bl_ind(asm_arm_t *as, uint fun_id, uint reg_temp);
|
||||
void asm_arm_bx_reg(asm_arm_t *as, uint reg_src);
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define ASM_ARM_REG_FUN_TABLE ASM_ARM_REG_R7
|
||||
|
||||
#if defined(GENERIC_ASM_API) && GENERIC_ASM_API
|
||||
|
||||
|
@ -144,18 +149,21 @@ void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp);
|
|||
#define REG_LOCAL_3 ASM_ARM_REG_R6
|
||||
#define REG_LOCAL_NUM (3)
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define REG_FUN_TABLE ASM_ARM_REG_FUN_TABLE
|
||||
|
||||
#define ASM_T asm_arm_t
|
||||
#define ASM_END_PASS asm_arm_end_pass
|
||||
#define ASM_ENTRY asm_arm_entry
|
||||
#define ASM_EXIT asm_arm_exit
|
||||
|
||||
#define ASM_JUMP asm_arm_b_label
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_arm_cmp_reg_i8(as, reg, 0); \
|
||||
asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_arm_cmp_reg_i8(as, reg, 0); \
|
||||
asm_arm_bcc_label(as, ASM_ARM_CC_NE, label); \
|
||||
|
@ -165,14 +173,15 @@ void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp);
|
|||
asm_arm_cmp_reg_reg(as, reg1, reg2); \
|
||||
asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \
|
||||
} while (0)
|
||||
#define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, ASM_ARM_REG_R3)
|
||||
#define ASM_JUMP_REG(as, reg) asm_arm_bx_reg((as), (reg))
|
||||
#define ASM_CALL_IND(as, idx) asm_arm_bl_ind(as, idx, ASM_ARM_REG_R3)
|
||||
|
||||
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_arm_mov_local_reg((as), (local_num), (reg_src))
|
||||
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_arm_mov_reg_local((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src))
|
||||
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_arm_mov_reg_pcrel((as), (reg_dest), (label))
|
||||
|
||||
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift))
|
||||
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift))
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include "py/mphal.h"
|
||||
#include "py/asmthumb.h"
|
||||
|
||||
#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32)
|
||||
#define UNSIGNED_FIT7(x) ((uint32_t)(x) < 128)
|
||||
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
|
||||
#define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)
|
||||
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
|
||||
|
@ -43,6 +45,15 @@
|
|||
#define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
|
||||
#define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000)
|
||||
|
||||
// Note: these actually take an imm12 but the high-bit is not encoded here
|
||||
#define OP_ADD_W_RRI_HI(reg_src) (0xf200 | (reg_src))
|
||||
#define OP_ADD_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff))
|
||||
#define OP_SUB_W_RRI_HI(reg_src) (0xf2a0 | (reg_src))
|
||||
#define OP_SUB_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff))
|
||||
|
||||
#define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base))
|
||||
#define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
|
||||
|
||||
static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
|
||||
return mp_asm_base_get_cur_to_write_bytes(&as->base, n);
|
||||
}
|
||||
|
@ -51,7 +62,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
|
|||
(void)as;
|
||||
// could check labels are resolved...
|
||||
|
||||
#if defined(MCU_SERIES_F7)
|
||||
#if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT == 1
|
||||
if (as->base.pass == MP_ASM_PASS_EMIT) {
|
||||
// flush D-cache, so the code emitted is stored in memory
|
||||
MP_HAL_CLEAN_DCACHE(as->base.code_base, as->base.code_size);
|
||||
|
@ -89,6 +100,7 @@ STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) {
|
|||
#define OP_POP_RLIST(rlolist) (0xbc00 | (rlolist))
|
||||
#define OP_POP_RLIST_PC(rlolist) (0xbc00 | 0x0100 | (rlolist))
|
||||
|
||||
// The number of words must fit in 7 unsigned bits
|
||||
#define OP_ADD_SP(num_words) (0xb000 | (num_words))
|
||||
#define OP_SUB_SP(num_words) (0xb080 | (num_words))
|
||||
|
||||
|
@ -142,7 +154,11 @@ void asm_thumb_entry(asm_thumb_t *as, int num_locals) {
|
|||
}
|
||||
asm_thumb_op16(as, OP_PUSH_RLIST_LR(reglist));
|
||||
if (stack_adjust > 0) {
|
||||
asm_thumb_op16(as, OP_SUB_SP(stack_adjust));
|
||||
if (UNSIGNED_FIT7(stack_adjust)) {
|
||||
asm_thumb_op16(as, OP_SUB_SP(stack_adjust));
|
||||
} else {
|
||||
asm_thumb_op32(as, OP_SUB_W_RRI_HI(ASM_THUMB_REG_SP), OP_SUB_W_RRI_LO(ASM_THUMB_REG_SP, stack_adjust * 4));
|
||||
}
|
||||
}
|
||||
as->push_reglist = reglist;
|
||||
as->stack_adjust = stack_adjust;
|
||||
|
@ -150,7 +166,11 @@ void asm_thumb_entry(asm_thumb_t *as, int num_locals) {
|
|||
|
||||
void asm_thumb_exit(asm_thumb_t *as) {
|
||||
if (as->stack_adjust > 0) {
|
||||
asm_thumb_op16(as, OP_ADD_SP(as->stack_adjust));
|
||||
if (UNSIGNED_FIT7(as->stack_adjust)) {
|
||||
asm_thumb_op16(as, OP_ADD_SP(as->stack_adjust));
|
||||
} else {
|
||||
asm_thumb_op32(as, OP_ADD_W_RRI_HI(ASM_THUMB_REG_SP), OP_ADD_W_RRI_LO(ASM_THUMB_REG_SP, as->stack_adjust * 4));
|
||||
}
|
||||
}
|
||||
asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist));
|
||||
}
|
||||
|
@ -269,21 +289,6 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
|
|||
}
|
||||
}
|
||||
|
||||
// i32 is stored as a full word in the code, and aligned to machine-word boundary
|
||||
// TODO this is very inefficient, improve it!
|
||||
void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
|
||||
// align on machine-word + 2
|
||||
if ((as->base.code_offset & 3) == 0) {
|
||||
asm_thumb_op16(as, ASM_THUMB_OP_NOP);
|
||||
}
|
||||
// jump over the i32 value (instruction prefetch adds 2 to PC)
|
||||
asm_thumb_op16(as, OP_B_N(2));
|
||||
// store i32 on machine-word aligned boundary
|
||||
mp_asm_base_data(&as->base, 4, i32);
|
||||
// do the actual load of the i32 value
|
||||
asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32);
|
||||
}
|
||||
|
||||
#define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
|
||||
#define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
|
||||
|
||||
|
@ -310,6 +315,27 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
|
|||
asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
|
||||
}
|
||||
|
||||
void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label) {
|
||||
mp_uint_t dest = get_label_dest(as, label);
|
||||
mp_int_t rel = dest - as->base.code_offset;
|
||||
rel -= 4 + 4; // adjust for mov_reg_i16 and then PC+4 prefetch of add_reg_reg
|
||||
rel |= 1; // to stay in Thumb state when jumping to this address
|
||||
asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, rlo_dest, rel); // 4 bytes
|
||||
asm_thumb_add_reg_reg(as, rlo_dest, ASM_THUMB_REG_R15); // 2 bytes
|
||||
}
|
||||
|
||||
static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) {
|
||||
asm_thumb_op32(as, OP_LDR_W_HI(reg_base), OP_LDR_W_LO(reg_dest, word_offset * 4));
|
||||
}
|
||||
|
||||
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) {
|
||||
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) {
|
||||
asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset);
|
||||
} else {
|
||||
asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// this could be wrong, because it should have a range of +/- 16MiB...
|
||||
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
|
||||
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
|
||||
|
@ -355,25 +381,10 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {
|
|||
#define OP_BLX(reg) (0x4780 | ((reg) << 3))
|
||||
#define OP_SVC(arg) (0xdf00 | (arg))
|
||||
|
||||
void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {
|
||||
/* TODO make this use less bytes
|
||||
uint rlo_base = ASM_THUMB_REG_R3;
|
||||
uint rlo_dest = ASM_THUMB_REG_R7;
|
||||
uint word_offset = 4;
|
||||
asm_thumb_op16(as, 0x0000);
|
||||
asm_thumb_op16(as, 0x6800 | (word_offset << 6) | (rlo_base << 3) | rlo_dest); // ldr rlo_dest, [rlo_base, #offset]
|
||||
asm_thumb_op16(as, 0x4780 | (ASM_THUMB_REG_R9 << 3)); // blx reg
|
||||
*/
|
||||
|
||||
if (fun_id < 32) {
|
||||
// load ptr to function from table, indexed by fun_id (must be in range 0-31); 4 bytes
|
||||
asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, ASM_THUMB_REG_R7, fun_id));
|
||||
asm_thumb_op16(as, OP_BLX(reg_temp));
|
||||
} else {
|
||||
// load ptr to function into register using immediate; 6 bytes
|
||||
asm_thumb_mov_reg_i32(as, reg_temp, (mp_uint_t)fun_ptr);
|
||||
asm_thumb_op16(as, OP_BLX(reg_temp));
|
||||
}
|
||||
void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp) {
|
||||
// Load ptr to function from table, indexed by fun_id, then call it
|
||||
asm_thumb_ldr_reg_reg_i12_optimised(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id);
|
||||
asm_thumb_op16(as, OP_BLX(reg_temp));
|
||||
}
|
||||
|
||||
#endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#define ASM_THUMB_REG_R13 (13)
|
||||
#define ASM_THUMB_REG_R14 (14)
|
||||
#define ASM_THUMB_REG_R15 (15)
|
||||
#define ASM_THUMB_REG_SP (ASM_THUMB_REG_R13)
|
||||
#define ASM_THUMB_REG_LR (REG_R14)
|
||||
|
||||
#define ASM_THUMB_CC_EQ (0x0)
|
||||
|
@ -195,6 +196,26 @@ static inline void asm_thumb_cmp_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rl
|
|||
asm_thumb_format_4(as, ASM_THUMB_FORMAT_4_CMP, rlo_dest, rlo_src);
|
||||
}
|
||||
|
||||
// FORMAT 5: hi register operations (add, cmp, mov, bx)
|
||||
// For add/cmp/mov, at least one of the args must be a high register
|
||||
|
||||
#define ASM_THUMB_FORMAT_5_ADD (0x4400)
|
||||
#define ASM_THUMB_FORMAT_5_BX (0x4700)
|
||||
|
||||
#define ASM_THUMB_FORMAT_5_ENCODE(op, r_dest, r_src) \
|
||||
((op) | ((r_dest) << 4 & 0x0080) | ((r_src) << 3) | ((r_dest) & 0x0007))
|
||||
|
||||
static inline void asm_thumb_format_5(asm_thumb_t *as, uint op, uint r_dest, uint r_src) {
|
||||
asm_thumb_op16(as, ASM_THUMB_FORMAT_5_ENCODE(op, r_dest, r_src));
|
||||
}
|
||||
|
||||
static inline void asm_thumb_add_reg_reg(asm_thumb_t *as, uint r_dest, uint r_src) {
|
||||
asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_ADD, r_dest, r_src);
|
||||
}
|
||||
static inline void asm_thumb_bx_reg(asm_thumb_t *as, uint r_src) {
|
||||
asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_BX, 0, r_src);
|
||||
}
|
||||
|
||||
// FORMAT 9: load/store with immediate offset
|
||||
// For word transfers the offset must be aligned, and >>2
|
||||
|
||||
|
@ -251,14 +272,19 @@ bool asm_thumb_bl_label(asm_thumb_t *as, uint label);
|
|||
|
||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience
|
||||
void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience
|
||||
void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32); // convenience
|
||||
void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience
|
||||
void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience
|
||||
void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience
|
||||
void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label);
|
||||
|
||||
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint byte_offset); // convenience
|
||||
|
||||
void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch
|
||||
void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch
|
||||
void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp); // convenience
|
||||
void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp); // convenience
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define ASM_THUMB_REG_FUN_TABLE ASM_THUMB_REG_R7
|
||||
|
||||
#if defined(GENERIC_ASM_API) && GENERIC_ASM_API
|
||||
|
||||
|
@ -283,18 +309,20 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
|
|||
#define REG_LOCAL_3 ASM_THUMB_REG_R6
|
||||
#define REG_LOCAL_NUM (3)
|
||||
|
||||
#define REG_FUN_TABLE ASM_THUMB_REG_FUN_TABLE
|
||||
|
||||
#define ASM_T asm_thumb_t
|
||||
#define ASM_END_PASS asm_thumb_end_pass
|
||||
#define ASM_ENTRY asm_thumb_entry
|
||||
#define ASM_EXIT asm_thumb_exit
|
||||
|
||||
#define ASM_JUMP asm_thumb_b_label
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_thumb_cmp_rlo_i8(as, reg, 0); \
|
||||
asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_thumb_cmp_rlo_i8(as, reg, 0); \
|
||||
asm_thumb_bcc_label(as, ASM_THUMB_CC_NE, label); \
|
||||
|
@ -304,14 +332,15 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
|
|||
asm_thumb_cmp_rlo_rlo(as, reg1, reg2); \
|
||||
asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \
|
||||
} while (0)
|
||||
#define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, ASM_THUMB_REG_R3)
|
||||
#define ASM_JUMP_REG(as, reg) asm_thumb_bx_reg((as), (reg))
|
||||
#define ASM_CALL_IND(as, idx) asm_thumb_bl_ind(as, idx, ASM_THUMB_REG_R3)
|
||||
|
||||
#define ASM_MOV_LOCAL_REG(as, local_num, reg) asm_thumb_mov_local_reg((as), (local_num), (reg))
|
||||
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_optimised((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_aligned((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_thumb_mov_reg_local((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src))
|
||||
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_PCREL(as, rlo_dest, label) asm_thumb_mov_reg_pcrel((as), (rlo_dest), (label))
|
||||
|
||||
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift))
|
||||
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift))
|
||||
|
@ -323,7 +352,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
|
|||
#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_MUL, (reg_dest), (reg_src))
|
||||
|
||||
#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
|
||||
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), (word_offset))
|
||||
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (word_offset))
|
||||
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
|
||||
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
|
||||
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
|
||||
|
|
112
py/asmx64.c
112
py/asmx64.c
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -73,8 +73,10 @@
|
|||
#define OPCODE_CMP_R64_WITH_RM64 (0x39) /* /r */
|
||||
// #define OPCODE_CMP_RM32_WITH_R32 (0x3b)
|
||||
#define OPCODE_TEST_R8_WITH_RM8 (0x84) /* /r */
|
||||
#define OPCODE_TEST_R64_WITH_RM64 (0x85) /* /r */
|
||||
#define OPCODE_JMP_REL8 (0xeb)
|
||||
#define OPCODE_JMP_REL32 (0xe9)
|
||||
#define OPCODE_JMP_RM64 (0xff) /* /4 */
|
||||
#define OPCODE_JCC_REL8 (0x70) /* | jcc type */
|
||||
#define OPCODE_JCC_REL32_A (0x0f)
|
||||
#define OPCODE_JCC_REL32_B (0x80) /* | jcc type */
|
||||
|
@ -181,21 +183,22 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
|
|||
*/
|
||||
|
||||
STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) {
|
||||
assert(disp_r64 != ASM_X64_REG_RSP);
|
||||
|
||||
if (disp_r64 == ASM_X64_REG_R12) {
|
||||
// special case for r12; not fully implemented
|
||||
assert(SIGNED_FIT8(disp_offset));
|
||||
asm_x64_write_byte_3(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), 0x24, IMM32_L0(disp_offset));
|
||||
return;
|
||||
}
|
||||
|
||||
if (disp_offset == 0 && disp_r64 != ASM_X64_REG_RBP) {
|
||||
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP0 | MODRM_RM_R64(disp_r64));
|
||||
uint8_t rm_disp;
|
||||
if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) {
|
||||
rm_disp = MODRM_RM_DISP0;
|
||||
} else if (SIGNED_FIT8(disp_offset)) {
|
||||
asm_x64_write_byte_2(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), IMM32_L0(disp_offset));
|
||||
rm_disp = MODRM_RM_DISP8;
|
||||
} else {
|
||||
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP32 | MODRM_RM_R64(disp_r64));
|
||||
rm_disp = MODRM_RM_DISP32;
|
||||
}
|
||||
asm_x64_write_byte_1(as, MODRM_R64(r64) | rm_disp | MODRM_RM_R64(disp_r64));
|
||||
if ((disp_r64 & 7) == ASM_X64_REG_RSP) {
|
||||
// Special case for rsp and r12, they need a SIB byte
|
||||
asm_x64_write_byte_1(as, 0x24);
|
||||
}
|
||||
if (rm_disp == MODRM_RM_DISP8) {
|
||||
asm_x64_write_byte_1(as, IMM32_L0(disp_offset));
|
||||
} else if (rm_disp == MODRM_RM_DISP32) {
|
||||
asm_x64_write_word32(as, disp_offset);
|
||||
}
|
||||
}
|
||||
|
@ -361,15 +364,6 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r
|
|||
}
|
||||
}
|
||||
|
||||
// src_i64 is stored as a full word in the code, and aligned to machine-word boundary
|
||||
void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64) {
|
||||
// mov instruction uses 2 bytes for the instruction, before the i64
|
||||
while (((as->base.code_offset + 2) & (WORD_SIZE - 1)) != 0) {
|
||||
asm_x64_nop(as);
|
||||
}
|
||||
asm_x64_mov_i64_to_r64(as, src_i64, dest_r64);
|
||||
}
|
||||
|
||||
void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {
|
||||
asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64);
|
||||
}
|
||||
|
@ -465,17 +459,25 @@ void asm_x64_cmp_i32_with_r32(asm_x64_t *as, int src_i32, int src_r32) {
|
|||
*/
|
||||
|
||||
void asm_x64_test_r8_with_r8(asm_x64_t *as, int src_r64_a, int src_r64_b) {
|
||||
// TODO implement for other registers
|
||||
assert(src_r64_a == ASM_X64_REG_RAX);
|
||||
assert(src_r64_b == ASM_X64_REG_RAX);
|
||||
assert(src_r64_a < 8);
|
||||
assert(src_r64_b < 8);
|
||||
asm_x64_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R64(src_r64_a) | MODRM_RM_REG | MODRM_RM_R64(src_r64_b));
|
||||
}
|
||||
|
||||
void asm_x64_test_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b) {
|
||||
asm_x64_generic_r64_r64(as, src_r64_b, src_r64_a, OPCODE_TEST_R64_WITH_RM64);
|
||||
}
|
||||
|
||||
void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) {
|
||||
assert(dest_r8 < 8);
|
||||
asm_x64_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r8));
|
||||
}
|
||||
|
||||
void asm_x64_jmp_reg(asm_x64_t *as, int src_r64) {
|
||||
assert(src_r64 < 8);
|
||||
asm_x64_write_byte_2(as, OPCODE_JMP_RM64, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(src_r64));
|
||||
}
|
||||
|
||||
STATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) {
|
||||
assert(label < as->base.max_num_labels);
|
||||
return as->base.label_offsets[label];
|
||||
|
@ -528,63 +530,72 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
|
|||
void asm_x64_entry(asm_x64_t *as, int num_locals) {
|
||||
assert(num_locals >= 0);
|
||||
asm_x64_push_r64(as, ASM_X64_REG_RBP);
|
||||
asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);
|
||||
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
|
||||
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
|
||||
asm_x64_push_r64(as, ASM_X64_REG_RBX);
|
||||
asm_x64_push_r64(as, ASM_X64_REG_R12);
|
||||
asm_x64_push_r64(as, ASM_X64_REG_R13);
|
||||
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
|
||||
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
|
||||
as->num_locals = num_locals;
|
||||
}
|
||||
|
||||
void asm_x64_exit(asm_x64_t *as) {
|
||||
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, -as->num_locals * WORD_SIZE);
|
||||
asm_x64_pop_r64(as, ASM_X64_REG_R13);
|
||||
asm_x64_pop_r64(as, ASM_X64_REG_R12);
|
||||
asm_x64_pop_r64(as, ASM_X64_REG_RBX);
|
||||
asm_x64_write_byte_1(as, OPCODE_LEAVE);
|
||||
asm_x64_pop_r64(as, ASM_X64_REG_RBP);
|
||||
asm_x64_ret(as);
|
||||
}
|
||||
|
||||
// locals:
|
||||
// - stored on the stack in ascending order
|
||||
// - numbered 0 through as->num_locals-1
|
||||
// - RBP points above the last local
|
||||
// - RSP points to the first local
|
||||
//
|
||||
// | RBP
|
||||
// v
|
||||
// | RSP
|
||||
// v
|
||||
// l0 l1 l2 ... l(n-1)
|
||||
// ^ ^
|
||||
// | low address | high address in RAM
|
||||
//
|
||||
STATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {
|
||||
return (-as->num_locals + local_num) * WORD_SIZE;
|
||||
STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) {
|
||||
(void)as;
|
||||
// Stack is full descending, RSP points to local0
|
||||
return local_num * WORD_SIZE;
|
||||
}
|
||||
|
||||
void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) {
|
||||
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, src_local_num), dest_r64);
|
||||
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, src_local_num), dest_r64);
|
||||
}
|
||||
|
||||
void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) {
|
||||
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, dest_local_num));
|
||||
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, dest_local_num));
|
||||
}
|
||||
|
||||
void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) {
|
||||
int offset = asm_x64_local_offset_from_ebp(as, local_num);
|
||||
int offset = asm_x64_local_offset_from_rsp(as, local_num);
|
||||
if (offset == 0) {
|
||||
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RBP);
|
||||
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RSP);
|
||||
} else {
|
||||
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RBP, offset, dest_r64);
|
||||
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RSP, offset, dest_r64);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label) {
|
||||
mp_uint_t dest = get_label_dest(as, label);
|
||||
mp_int_t rel = dest - (as->base.code_offset + 7);
|
||||
asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64), OPCODE_LEA_MEM_TO_R64, MODRM_R64(dest_r64) | MODRM_RM_R64(5));
|
||||
asm_x64_write_word32(as, rel);
|
||||
}
|
||||
|
||||
/*
|
||||
void asm_x64_push_local(asm_x64_t *as, int local_num) {
|
||||
asm_x64_push_disp(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
|
||||
asm_x64_push_disp(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, local_num));
|
||||
}
|
||||
|
||||
void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) {
|
||||
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RBP);
|
||||
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_ebp(as, local_num), temp_r64);
|
||||
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RSP);
|
||||
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_rsp(as, local_num), temp_r64);
|
||||
asm_x64_push_r64(as, temp_r64);
|
||||
}
|
||||
*/
|
||||
|
@ -610,21 +621,10 @@ void asm_x64_call_i1(asm_x64_t *as, void* func, int i1) {
|
|||
}
|
||||
*/
|
||||
|
||||
void asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r64) {
|
||||
void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r64) {
|
||||
assert(temp_r64 < 8);
|
||||
#ifdef __LP64__
|
||||
asm_x64_mov_i64_to_r64_optimised(as, (int64_t)ptr, temp_r64);
|
||||
#else
|
||||
// If we get here, sizeof(int) == sizeof(void*).
|
||||
asm_x64_mov_i64_to_r64_optimised(as, (int64_t)(unsigned int)ptr, temp_r64);
|
||||
#endif
|
||||
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_FUN_TABLE, fun_id * WORD_SIZE, temp_r64);
|
||||
asm_x64_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R64(2) | MODRM_RM_REG | MODRM_RM_R64(temp_r64));
|
||||
// this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all
|
||||
// doesn't work anymore because calls are 64 bits away
|
||||
/*
|
||||
asm_x64_write_byte_1(as, OPCODE_CALL_REL32);
|
||||
asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
|
||||
*/
|
||||
}
|
||||
|
||||
#endif // MICROPY_EMIT_X64
|
||||
|
|
35
py/asmx64.h
35
py/asmx64.h
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -85,7 +85,6 @@ void asm_x64_pop_r64(asm_x64_t *as, int dest_r64);
|
|||
void asm_x64_mov_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
|
||||
void asm_x64_mov_i64_to_r64(asm_x64_t *as, int64_t src_i64, int dest_r64);
|
||||
void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64);
|
||||
void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64);
|
||||
void asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
|
||||
void asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
|
||||
void asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
|
||||
|
@ -104,7 +103,9 @@ void asm_x64_sub_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
|
|||
void asm_x64_mul_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
|
||||
void asm_x64_cmp_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b);
|
||||
void asm_x64_test_r8_with_r8(asm_x64_t *as, int src_r64_a, int src_r64_b);
|
||||
void asm_x64_test_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b);
|
||||
void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8);
|
||||
void asm_x64_jmp_reg(asm_x64_t *as, int src_r64);
|
||||
void asm_x64_jmp_label(asm_x64_t *as, mp_uint_t label);
|
||||
void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label);
|
||||
void asm_x64_entry(asm_x64_t *as, int num_locals);
|
||||
|
@ -112,7 +113,11 @@ void asm_x64_exit(asm_x64_t *as);
|
|||
void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64);
|
||||
void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num);
|
||||
void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64);
|
||||
void asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r32);
|
||||
void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label);
|
||||
void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32);
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define ASM_X64_REG_FUN_TABLE ASM_X64_REG_RBP
|
||||
|
||||
#if defined(GENERIC_ASM_API) && GENERIC_ASM_API
|
||||
|
||||
|
@ -139,20 +144,31 @@ void asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r32);
|
|||
#define REG_LOCAL_3 ASM_X64_REG_R13
|
||||
#define REG_LOCAL_NUM (3)
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define REG_FUN_TABLE ASM_X64_REG_FUN_TABLE
|
||||
|
||||
#define ASM_T asm_x64_t
|
||||
#define ASM_END_PASS asm_x64_end_pass
|
||||
#define ASM_ENTRY asm_x64_entry
|
||||
#define ASM_EXIT asm_x64_exit
|
||||
|
||||
#define ASM_JUMP asm_x64_jmp_label
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_x64_test_r8_with_r8(as, reg, reg); \
|
||||
if (bool_test) { \
|
||||
asm_x64_test_r8_with_r8((as), (reg), (reg)); \
|
||||
} else { \
|
||||
asm_x64_test_r64_with_r64((as), (reg), (reg)); \
|
||||
} \
|
||||
asm_x64_jcc_label(as, ASM_X64_CC_JZ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_x64_test_r8_with_r8(as, reg, reg); \
|
||||
if (bool_test) { \
|
||||
asm_x64_test_r8_with_r8((as), (reg), (reg)); \
|
||||
} else { \
|
||||
asm_x64_test_r64_with_r64((as), (reg), (reg)); \
|
||||
} \
|
||||
asm_x64_jcc_label(as, ASM_X64_CC_JNZ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
|
||||
|
@ -160,14 +176,15 @@ void asm_x64_call_ind(asm_x64_t *as, void *ptr, int temp_r32);
|
|||
asm_x64_cmp_r64_with_r64(as, reg1, reg2); \
|
||||
asm_x64_jcc_label(as, ASM_X64_CC_JE, label); \
|
||||
} while (0)
|
||||
#define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, ASM_X64_REG_RAX)
|
||||
#define ASM_JUMP_REG(as, reg) asm_x64_jmp_reg((as), (reg))
|
||||
#define ASM_CALL_IND(as, idx) asm_x64_call_ind(as, idx, ASM_X64_REG_RAX)
|
||||
|
||||
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x64_mov_r64_to_local((as), (reg_src), (local_num))
|
||||
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_optimised((as), (imm), (reg_dest))
|
||||
#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_aligned((as), (imm), (reg_dest))
|
||||
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x64_mov_local_to_r64((as), (local_num), (reg_dest))
|
||||
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src))
|
||||
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest))
|
||||
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x64_mov_reg_pcrel((as), (reg_dest), (label))
|
||||
|
||||
#define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg))
|
||||
#define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg))
|
||||
|
|
122
py/asmx86.c
122
py/asmx86.c
|
@ -73,8 +73,10 @@
|
|||
#define OPCODE_CMP_R32_WITH_RM32 (0x39)
|
||||
// #define OPCODE_CMP_RM32_WITH_R32 (0x3b)
|
||||
#define OPCODE_TEST_R8_WITH_RM8 (0x84) /* /r */
|
||||
#define OPCODE_TEST_R32_WITH_RM32 (0x85) /* /r */
|
||||
#define OPCODE_JMP_REL8 (0xeb)
|
||||
#define OPCODE_JMP_REL32 (0xe9)
|
||||
#define OPCODE_JMP_RM32 (0xff) /* /4 */
|
||||
#define OPCODE_JCC_REL8 (0x70) /* | jcc type */
|
||||
#define OPCODE_JCC_REL32_A (0x0f)
|
||||
#define OPCODE_JCC_REL32_B (0x80) /* | jcc type */
|
||||
|
@ -135,14 +137,22 @@ STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {
|
|||
}
|
||||
|
||||
STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {
|
||||
assert(disp_r32 != ASM_X86_REG_ESP);
|
||||
|
||||
uint8_t rm_disp;
|
||||
if (disp_offset == 0 && disp_r32 != ASM_X86_REG_EBP) {
|
||||
asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP0 | MODRM_RM_R32(disp_r32));
|
||||
rm_disp = MODRM_RM_DISP0;
|
||||
} else if (SIGNED_FIT8(disp_offset)) {
|
||||
asm_x86_write_byte_2(as, MODRM_R32(r32) | MODRM_RM_DISP8 | MODRM_RM_R32(disp_r32), IMM32_L0(disp_offset));
|
||||
rm_disp = MODRM_RM_DISP8;
|
||||
} else {
|
||||
asm_x86_write_byte_1(as, MODRM_R32(r32) | MODRM_RM_DISP32 | MODRM_RM_R32(disp_r32));
|
||||
rm_disp = MODRM_RM_DISP32;
|
||||
}
|
||||
asm_x86_write_byte_1(as, MODRM_R32(r32) | rm_disp | MODRM_RM_R32(disp_r32));
|
||||
if (disp_r32 == ASM_X86_REG_ESP) {
|
||||
// Special case for esp, it needs a SIB byte
|
||||
asm_x86_write_byte_1(as, 0x24);
|
||||
}
|
||||
if (rm_disp == MODRM_RM_DISP8) {
|
||||
asm_x86_write_byte_1(as, IMM32_L0(disp_offset));
|
||||
} else if (rm_disp == MODRM_RM_DISP32) {
|
||||
asm_x86_write_word32(as, disp_offset);
|
||||
}
|
||||
}
|
||||
|
@ -151,9 +161,11 @@ STATIC void asm_x86_generic_r32_r32(asm_x86_t *as, int dest_r32, int src_r32, in
|
|||
asm_x86_write_byte_2(as, op, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
|
||||
}
|
||||
|
||||
#if 0
|
||||
STATIC void asm_x86_nop(asm_x86_t *as) {
|
||||
asm_x86_write_byte_1(as, OPCODE_NOP);
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void asm_x86_push_r32(asm_x86_t *as, int src_r32) {
|
||||
asm_x86_write_byte_1(as, OPCODE_PUSH_R32 | src_r32);
|
||||
|
@ -229,15 +241,6 @@ void asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32) {
|
|||
asm_x86_write_word32(as, src_i32);
|
||||
}
|
||||
|
||||
// src_i32 is stored as a full word in the code, and aligned to machine-word boundary
|
||||
void asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32) {
|
||||
// mov instruction uses 1 byte for the instruction, before the i32
|
||||
while (((as->base.code_offset + 1) & (WORD_SIZE - 1)) != 0) {
|
||||
asm_x86_nop(as);
|
||||
}
|
||||
asm_x86_mov_i32_to_r32(as, src_i32, dest_r32);
|
||||
}
|
||||
|
||||
void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {
|
||||
asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32);
|
||||
}
|
||||
|
@ -312,7 +315,7 @@ void asm_x86_sar_r32_by_imm(asm_x86_t *as, int r32, int imm) {
|
|||
#endif
|
||||
|
||||
void asm_x86_cmp_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b) {
|
||||
asm_x86_write_byte_2(as, OPCODE_CMP_R32_WITH_RM32, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));
|
||||
asm_x86_generic_r32_r32(as, src_r32_b, src_r32_a, OPCODE_CMP_R32_WITH_RM32);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -328,16 +331,21 @@ void asm_x86_cmp_i32_with_r32(asm_x86_t *as, int src_i32, int src_r32) {
|
|||
#endif
|
||||
|
||||
void asm_x86_test_r8_with_r8(asm_x86_t *as, int src_r32_a, int src_r32_b) {
|
||||
// TODO implement for other registers
|
||||
assert(src_r32_a == ASM_X86_REG_EAX);
|
||||
assert(src_r32_b == ASM_X86_REG_EAX);
|
||||
asm_x86_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b));
|
||||
}
|
||||
|
||||
void asm_x86_test_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b) {
|
||||
asm_x86_generic_r32_r32(as, src_r32_b, src_r32_a, OPCODE_TEST_R32_WITH_RM32);
|
||||
}
|
||||
|
||||
void asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8) {
|
||||
asm_x86_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r8));
|
||||
}
|
||||
|
||||
void asm_x86_jmp_reg(asm_x86_t *as, int src_r32) {
|
||||
asm_x86_write_byte_2(as, OPCODE_JMP_RM32, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(src_r32));
|
||||
}
|
||||
|
||||
STATIC mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) {
|
||||
assert(label < as->base.max_num_labels);
|
||||
return as->base.label_offsets[label];
|
||||
|
@ -390,86 +398,102 @@ void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label) {
|
|||
void asm_x86_entry(asm_x86_t *as, int num_locals) {
|
||||
assert(num_locals >= 0);
|
||||
asm_x86_push_r32(as, ASM_X86_REG_EBP);
|
||||
asm_x86_mov_r32_r32(as, ASM_X86_REG_EBP, ASM_X86_REG_ESP);
|
||||
if (num_locals > 0) {
|
||||
asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE);
|
||||
}
|
||||
asm_x86_push_r32(as, ASM_X86_REG_EBX);
|
||||
asm_x86_push_r32(as, ASM_X86_REG_ESI);
|
||||
asm_x86_push_r32(as, ASM_X86_REG_EDI);
|
||||
// TODO align stack on 16-byte boundary
|
||||
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
|
||||
asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE);
|
||||
as->num_locals = num_locals;
|
||||
}
|
||||
|
||||
void asm_x86_exit(asm_x86_t *as) {
|
||||
asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, -as->num_locals * WORD_SIZE);
|
||||
asm_x86_pop_r32(as, ASM_X86_REG_EDI);
|
||||
asm_x86_pop_r32(as, ASM_X86_REG_ESI);
|
||||
asm_x86_pop_r32(as, ASM_X86_REG_EBX);
|
||||
asm_x86_write_byte_1(as, OPCODE_LEAVE);
|
||||
asm_x86_pop_r32(as, ASM_X86_REG_EBP);
|
||||
asm_x86_ret(as);
|
||||
}
|
||||
|
||||
STATIC int asm_x86_arg_offset_from_esp(asm_x86_t *as, size_t arg_num) {
|
||||
// Above esp are: locals, 4 saved registers, return eip, arguments
|
||||
return (as->num_locals + 4 + 1 + arg_num) * WORD_SIZE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void asm_x86_push_arg(asm_x86_t *as, int src_arg_num) {
|
||||
asm_x86_push_disp(as, ASM_X86_REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE);
|
||||
asm_x86_push_disp(as, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, src_arg_num));
|
||||
}
|
||||
#endif
|
||||
|
||||
void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32) {
|
||||
asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE, dest_r32);
|
||||
asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, src_arg_num), dest_r32);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void asm_x86_mov_r32_to_arg(asm_x86_t *as, int src_r32, int dest_arg_num) {
|
||||
asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_EBP, 2 * WORD_SIZE + dest_arg_num * WORD_SIZE);
|
||||
asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, dest_arg_num));
|
||||
}
|
||||
#endif
|
||||
|
||||
// locals:
|
||||
// - stored on the stack in ascending order
|
||||
// - numbered 0 through as->num_locals-1
|
||||
// - EBP points above the last local
|
||||
// - ESP points to the first local
|
||||
//
|
||||
// | EBP
|
||||
// v
|
||||
// | ESP
|
||||
// v
|
||||
// l0 l1 l2 ... l(n-1)
|
||||
// ^ ^
|
||||
// | low address | high address in RAM
|
||||
//
|
||||
STATIC int asm_x86_local_offset_from_ebp(asm_x86_t *as, int local_num) {
|
||||
return (-as->num_locals + local_num) * WORD_SIZE;
|
||||
STATIC int asm_x86_local_offset_from_esp(asm_x86_t *as, int local_num) {
|
||||
(void)as;
|
||||
// Stack is full descending, ESP points to local0
|
||||
return local_num * WORD_SIZE;
|
||||
}
|
||||
|
||||
void asm_x86_mov_local_to_r32(asm_x86_t *as, int src_local_num, int dest_r32) {
|
||||
asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, src_local_num), dest_r32);
|
||||
asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, src_local_num), dest_r32);
|
||||
}
|
||||
|
||||
void asm_x86_mov_r32_to_local(asm_x86_t *as, int src_r32, int dest_local_num) {
|
||||
asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, dest_local_num));
|
||||
asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, dest_local_num));
|
||||
}
|
||||
|
||||
void asm_x86_mov_local_addr_to_r32(asm_x86_t *as, int local_num, int dest_r32) {
|
||||
int offset = asm_x86_local_offset_from_ebp(as, local_num);
|
||||
int offset = asm_x86_local_offset_from_esp(as, local_num);
|
||||
if (offset == 0) {
|
||||
asm_x86_mov_r32_r32(as, dest_r32, ASM_X86_REG_EBP);
|
||||
asm_x86_mov_r32_r32(as, dest_r32, ASM_X86_REG_ESP);
|
||||
} else {
|
||||
asm_x86_lea_disp_to_r32(as, ASM_X86_REG_EBP, offset, dest_r32);
|
||||
asm_x86_lea_disp_to_r32(as, ASM_X86_REG_ESP, offset, dest_r32);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r32, mp_uint_t label) {
|
||||
asm_x86_write_byte_1(as, OPCODE_CALL_REL32);
|
||||
asm_x86_write_word32(as, 0);
|
||||
mp_uint_t dest = get_label_dest(as, label);
|
||||
mp_int_t rel = dest - as->base.code_offset;
|
||||
asm_x86_pop_r32(as, dest_r32);
|
||||
// PC rel is usually a forward reference, so need to assume it's large
|
||||
asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
|
||||
asm_x86_write_word32(as, rel);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void asm_x86_push_local(asm_x86_t *as, int local_num) {
|
||||
asm_x86_push_disp(as, ASM_X86_REG_EBP, asm_x86_local_offset_from_ebp(as, local_num));
|
||||
asm_x86_push_disp(as, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, local_num));
|
||||
}
|
||||
|
||||
void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32) {
|
||||
asm_x86_mov_r32_r32(as, temp_r32, ASM_X86_REG_EBP);
|
||||
asm_x86_add_i32_to_r32(as, asm_x86_local_offset_from_ebp(as, local_num), temp_r32);
|
||||
asm_x86_mov_r32_r32(as, temp_r32, ASM_X86_REG_ESP);
|
||||
asm_x86_add_i32_to_r32(as, asm_x86_local_offset_from_esp(as, local_num), temp_r32);
|
||||
asm_x86_push_r32(as, temp_r32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32) {
|
||||
void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) {
|
||||
// TODO align stack on 16-byte boundary before the call
|
||||
assert(n_args <= 5);
|
||||
if (n_args > 4) {
|
||||
|
@ -487,20 +511,10 @@ void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32)
|
|||
if (n_args > 0) {
|
||||
asm_x86_push_r32(as, ASM_X86_REG_ARG_1);
|
||||
}
|
||||
#ifdef __LP64__
|
||||
// We wouldn't run x86 code on an x64 machine. This is here to enable
|
||||
// testing of the x86 emitter only.
|
||||
asm_x86_mov_i32_to_r32(as, (int32_t)(int64_t)ptr, temp_r32);
|
||||
#else
|
||||
// If we get here, sizeof(int) == sizeof(void*).
|
||||
asm_x86_mov_i32_to_r32(as, (int32_t)ptr, temp_r32);
|
||||
#endif
|
||||
|
||||
// Load the pointer to the function and make the call
|
||||
asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_FUN_TABLE, fun_id * WORD_SIZE, temp_r32);
|
||||
asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32));
|
||||
// this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all
|
||||
/*
|
||||
asm_x86_write_byte_1(as, OPCODE_CALL_REL32);
|
||||
asm_x86_write_word32(as, ptr - (void*)(as->code_base + as->base.code_offset + 4));
|
||||
*/
|
||||
|
||||
// the caller must clean up the stack
|
||||
if (n_args > 0) {
|
||||
|
|
33
py/asmx86.h
33
py/asmx86.h
|
@ -84,7 +84,6 @@ static inline void asm_x86_end_pass(asm_x86_t *as) {
|
|||
|
||||
void asm_x86_mov_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
|
||||
void asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32);
|
||||
void asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32);
|
||||
void asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);
|
||||
void asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);
|
||||
void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp);
|
||||
|
@ -101,7 +100,9 @@ void asm_x86_sub_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
|
|||
void asm_x86_mul_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
|
||||
void asm_x86_cmp_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b);
|
||||
void asm_x86_test_r8_with_r8(asm_x86_t *as, int src_r32_a, int src_r32_b);
|
||||
void asm_x86_test_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b);
|
||||
void asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8);
|
||||
void asm_x86_jmp_reg(asm_x86_t *as, int src_r86);
|
||||
void asm_x86_jmp_label(asm_x86_t *as, mp_uint_t label);
|
||||
void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label);
|
||||
void asm_x86_entry(asm_x86_t *as, int num_locals);
|
||||
|
@ -110,7 +111,11 @@ void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32);
|
|||
void asm_x86_mov_local_to_r32(asm_x86_t *as, int src_local_num, int dest_r32);
|
||||
void asm_x86_mov_r32_to_local(asm_x86_t *as, int src_r32, int dest_local_num);
|
||||
void asm_x86_mov_local_addr_to_r32(asm_x86_t *as, int local_num, int dest_r32);
|
||||
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32);
|
||||
void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r64, mp_uint_t label);
|
||||
void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32);
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define ASM_X86_REG_FUN_TABLE ASM_X86_REG_EBP
|
||||
|
||||
#if defined(GENERIC_ASM_API) && GENERIC_ASM_API
|
||||
|
||||
|
@ -137,20 +142,31 @@ void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32);
|
|||
#define REG_LOCAL_3 ASM_X86_REG_EDI
|
||||
#define REG_LOCAL_NUM (3)
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define REG_FUN_TABLE ASM_X86_REG_FUN_TABLE
|
||||
|
||||
#define ASM_T asm_x86_t
|
||||
#define ASM_END_PASS asm_x86_end_pass
|
||||
#define ASM_ENTRY asm_x86_entry
|
||||
#define ASM_EXIT asm_x86_exit
|
||||
|
||||
#define ASM_JUMP asm_x86_jmp_label
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_x86_test_r8_with_r8(as, reg, reg); \
|
||||
if (bool_test) { \
|
||||
asm_x86_test_r8_with_r8(as, reg, reg); \
|
||||
} else { \
|
||||
asm_x86_test_r32_with_r32(as, reg, reg); \
|
||||
} \
|
||||
asm_x86_jcc_label(as, ASM_X86_CC_JZ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
|
||||
do { \
|
||||
asm_x86_test_r8_with_r8(as, reg, reg); \
|
||||
if (bool_test) { \
|
||||
asm_x86_test_r8_with_r8(as, reg, reg); \
|
||||
} else { \
|
||||
asm_x86_test_r32_with_r32(as, reg, reg); \
|
||||
} \
|
||||
asm_x86_jcc_label(as, ASM_X86_CC_JNZ, label); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
|
||||
|
@ -158,14 +174,15 @@ void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32);
|
|||
asm_x86_cmp_r32_with_r32(as, reg1, reg2); \
|
||||
asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \
|
||||
} while (0)
|
||||
#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX)
|
||||
#define ASM_JUMP_REG(as, reg) asm_x86_jmp_reg((as), (reg))
|
||||
#define ASM_CALL_IND(as, idx) asm_x86_call_ind(as, idx, mp_f_n_args[idx], ASM_X86_REG_EAX)
|
||||
|
||||
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num))
|
||||
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest))
|
||||
#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32_aligned((as), (imm), (reg_dest))
|
||||
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x86_mov_local_to_r32((as), (local_num), (reg_dest))
|
||||
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src))
|
||||
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest))
|
||||
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x86_mov_reg_pcrel((as), (reg_dest), (label))
|
||||
|
||||
#define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg))
|
||||
#define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg))
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define WORD_SIZE (4)
|
||||
#define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80))
|
||||
#define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800))
|
||||
#define NUM_REGS_SAVED (5)
|
||||
|
||||
void asm_xtensa_end_pass(asm_xtensa_t *as) {
|
||||
as->num_const = as->cur_const;
|
||||
|
@ -67,26 +68,37 @@ void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) {
|
|||
mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte
|
||||
as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4);
|
||||
|
||||
// adjust the stack-pointer to store a0, a12, a13, a14 and locals, 16-byte aligned
|
||||
as->stack_adjust = (((4 + num_locals) * WORD_SIZE) + 15) & ~15;
|
||||
asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust);
|
||||
// adjust the stack-pointer to store a0, a12, a13, a14, a15 and locals, 16-byte aligned
|
||||
as->stack_adjust = (((NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15;
|
||||
if (SIGNED_FIT8(-as->stack_adjust)) {
|
||||
asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust);
|
||||
} else {
|
||||
asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust);
|
||||
asm_xtensa_op_sub(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9);
|
||||
}
|
||||
|
||||
// save return value (a0) and callee-save registers (a12, a13, a14)
|
||||
// save return value (a0) and callee-save registers (a12, a13, a14, a15)
|
||||
asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);
|
||||
asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A12, ASM_XTENSA_REG_A1, 1);
|
||||
asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A13, ASM_XTENSA_REG_A1, 2);
|
||||
asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A14, ASM_XTENSA_REG_A1, 3);
|
||||
for (int i = 1; i < NUM_REGS_SAVED; ++i) {
|
||||
asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_xtensa_exit(asm_xtensa_t *as) {
|
||||
// restore registers
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A14, ASM_XTENSA_REG_A1, 3);
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A13, ASM_XTENSA_REG_A1, 2);
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A12, ASM_XTENSA_REG_A1, 1);
|
||||
for (int i = NUM_REGS_SAVED - 1; i >= 1; --i) {
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i);
|
||||
}
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);
|
||||
|
||||
// restore stack-pointer and return
|
||||
asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust);
|
||||
if (SIGNED_FIT8(as->stack_adjust)) {
|
||||
asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust);
|
||||
} else {
|
||||
asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust);
|
||||
asm_xtensa_op_add_n(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9);
|
||||
}
|
||||
|
||||
asm_xtensa_op_ret_n(as);
|
||||
}
|
||||
|
||||
|
@ -149,7 +161,8 @@ void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) {
|
|||
asm_xtensa_op_movi(as, reg_dest, i32);
|
||||
} else {
|
||||
// load the constant
|
||||
asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, 4 + as->cur_const * WORD_SIZE);
|
||||
uint32_t const_table_offset = (uint8_t *)as->const_table - as->base.code_base;
|
||||
asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, const_table_offset + as->cur_const * WORD_SIZE);
|
||||
// store the constant in the table
|
||||
if (as->const_table != NULL) {
|
||||
as->const_table[as->cur_const] = i32;
|
||||
|
@ -159,16 +172,52 @@ void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) {
|
|||
}
|
||||
|
||||
void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src) {
|
||||
asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, 4 + local_num);
|
||||
asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, NUM_REGS_SAVED + local_num);
|
||||
}
|
||||
|
||||
void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num) {
|
||||
asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, 4 + local_num);
|
||||
asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, NUM_REGS_SAVED + local_num);
|
||||
}
|
||||
|
||||
void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num) {
|
||||
asm_xtensa_op_mov_n(as, reg_dest, ASM_XTENSA_REG_A1);
|
||||
asm_xtensa_op_addi(as, reg_dest, reg_dest, (4 + local_num) * WORD_SIZE);
|
||||
uint off = (NUM_REGS_SAVED + local_num) * WORD_SIZE;
|
||||
if (SIGNED_FIT8(off)) {
|
||||
asm_xtensa_op_addi(as, reg_dest, ASM_XTENSA_REG_A1, off);
|
||||
} else {
|
||||
asm_xtensa_op_movi(as, reg_dest, off);
|
||||
asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A1);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label) {
|
||||
// Get relative offset from PC
|
||||
uint32_t dest = get_label_dest(as, label);
|
||||
int32_t rel = dest - as->base.code_offset;
|
||||
rel -= 3 + 3; // account for 3 bytes of movi instruction, 3 bytes call0 adjustment
|
||||
asm_xtensa_op_movi(as, reg_dest, rel); // imm has 12-bit range
|
||||
|
||||
// Use call0 to get PC+3 into a0
|
||||
// call0 destination must be aligned on 4 bytes:
|
||||
// - code_offset&3=0: off=0, pad=1
|
||||
// - code_offset&3=1: off=0, pad=0
|
||||
// - code_offset&3=2: off=1, pad=3
|
||||
// - code_offset&3=3: off=1, pad=2
|
||||
uint32_t off = as->base.code_offset >> 1 & 1;
|
||||
uint32_t pad = (5 - as->base.code_offset) & 3;
|
||||
asm_xtensa_op_call0(as, off);
|
||||
mp_asm_base_get_cur_to_write_bytes(&as->base, pad);
|
||||
|
||||
// Add PC to relative offset
|
||||
asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A0);
|
||||
}
|
||||
|
||||
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) {
|
||||
if (idx < 16) {
|
||||
asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
|
||||
} else {
|
||||
asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx);
|
||||
}
|
||||
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0);
|
||||
}
|
||||
|
||||
#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
|
|
|
@ -113,12 +113,12 @@ void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op);
|
|||
|
||||
// raw instructions
|
||||
|
||||
static inline void asm_xtensa_op_add(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 8, reg_dest, reg_src_a, reg_src_b));
|
||||
static inline void asm_xtensa_op_add_n(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {
|
||||
asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(10, reg_dest, reg_src_a, reg_src_b));
|
||||
}
|
||||
|
||||
static inline void asm_xtensa_op_addi(asm_xtensa_t *as, uint reg_dest, uint reg_src, int imm8) {
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 12, reg_dest, reg_src, imm8 & 0xff));
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 12, reg_src, reg_dest, imm8 & 0xff));
|
||||
}
|
||||
|
||||
static inline void asm_xtensa_op_and(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {
|
||||
|
@ -133,6 +133,10 @@ static inline void asm_xtensa_op_bccz(asm_xtensa_t *as, uint cond, uint reg_src,
|
|||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI12(6, reg_src, cond, 1, rel12 & 0xfff));
|
||||
}
|
||||
|
||||
static inline void asm_xtensa_op_call0(asm_xtensa_t *as, int32_t rel18) {
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALL(5, 0, rel18 & 0x3ffff));
|
||||
}
|
||||
|
||||
static inline void asm_xtensa_op_callx0(asm_xtensa_t *as, uint reg) {
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 0));
|
||||
}
|
||||
|
@ -238,6 +242,11 @@ void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32);
|
|||
void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src);
|
||||
void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num);
|
||||
void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num);
|
||||
void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label);
|
||||
void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx);
|
||||
|
||||
// Holds a pointer to mp_fun_table
|
||||
#define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15
|
||||
|
||||
#if defined(GENERIC_ASM_API) && GENERIC_ASM_API
|
||||
|
||||
|
@ -262,30 +271,29 @@ void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_nu
|
|||
#define REG_LOCAL_3 ASM_XTENSA_REG_A14
|
||||
#define REG_LOCAL_NUM (3)
|
||||
|
||||
#define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE
|
||||
|
||||
#define ASM_T asm_xtensa_t
|
||||
#define ASM_END_PASS asm_xtensa_end_pass
|
||||
#define ASM_ENTRY asm_xtensa_entry
|
||||
#define ASM_EXIT asm_xtensa_exit
|
||||
|
||||
#define ASM_JUMP asm_xtensa_j_label
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
|
||||
asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_EQ, reg, label)
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
|
||||
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
|
||||
asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_NE, reg, label)
|
||||
#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
|
||||
asm_xtensa_bcc_reg_reg_label(as, ASM_XTENSA_CC_EQ, reg1, reg2, label)
|
||||
#define ASM_CALL_IND(as, ptr, idx) \
|
||||
do { \
|
||||
asm_xtensa_mov_reg_i32(as, ASM_XTENSA_REG_A0, (uint32_t)ptr); \
|
||||
asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); \
|
||||
} while (0)
|
||||
#define ASM_JUMP_REG(as, reg) asm_xtensa_op_jx((as), (reg))
|
||||
#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx))
|
||||
|
||||
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), (local_num), (reg_src))
|
||||
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm))
|
||||
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src))
|
||||
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), (local_num))
|
||||
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_xtensa_mov_reg_pcrel((as), (reg_dest), (label))
|
||||
|
||||
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \
|
||||
do { \
|
||||
|
@ -300,7 +308,7 @@ void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_nu
|
|||
#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_or((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_xor((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_and((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_add((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_add_n((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src))
|
||||
#define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src))
|
||||
|
||||
|
|
16
py/bc.c
16
py/bc.c
|
@ -302,7 +302,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw
|
|||
// MP_BC_MAKE_CLOSURE_DEFARGS
|
||||
// MP_BC_RAISE_VARARGS
|
||||
// There are 4 special opcodes that have an extra byte only when
|
||||
// MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled:
|
||||
// MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled (and they take a qstr):
|
||||
// MP_BC_LOAD_NAME
|
||||
// MP_BC_LOAD_GLOBAL
|
||||
// MP_BC_LOAD_ATTR
|
||||
|
@ -396,18 +396,20 @@ uint mp_opcode_format(const byte *ip, size_t *opcode_size) {
|
|||
uint f = (opcode_format_table[*ip >> 2] >> (2 * (*ip & 3))) & 3;
|
||||
const byte *ip_start = ip;
|
||||
if (f == MP_OPCODE_QSTR) {
|
||||
if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {
|
||||
if (*ip == MP_BC_LOAD_NAME
|
||||
|| *ip == MP_BC_LOAD_GLOBAL
|
||||
|| *ip == MP_BC_LOAD_ATTR
|
||||
|| *ip == MP_BC_STORE_ATTR) {
|
||||
ip += 1;
|
||||
}
|
||||
}
|
||||
ip += 3;
|
||||
} else {
|
||||
int extra_byte = (
|
||||
*ip == MP_BC_RAISE_VARARGS
|
||||
|| *ip == MP_BC_MAKE_CLOSURE
|
||||
|| *ip == MP_BC_MAKE_CLOSURE_DEFARGS
|
||||
#if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
|
||||
|| *ip == MP_BC_LOAD_NAME
|
||||
|| *ip == MP_BC_LOAD_GLOBAL
|
||||
|| *ip == MP_BC_LOAD_ATTR
|
||||
|| *ip == MP_BC_STORE_ATTR
|
||||
#endif
|
||||
);
|
||||
ip += 1;
|
||||
if (f == MP_OPCODE_VAR_UINT) {
|
||||
|
|
|
@ -106,6 +106,7 @@ extern const mp_obj_module_t mp_module_ujson;
|
|||
extern const mp_obj_module_t mp_module_ure;
|
||||
extern const mp_obj_module_t mp_module_uheapq;
|
||||
extern const mp_obj_module_t mp_module_uhashlib;
|
||||
extern const mp_obj_module_t mp_module_ucryptolib;
|
||||
extern const mp_obj_module_t mp_module_ubinascii;
|
||||
extern const mp_obj_module_t mp_module_urandom;
|
||||
extern const mp_obj_module_t mp_module_uselect;
|
||||
|
|
|
@ -167,13 +167,13 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) {
|
|||
|
||||
mp_map_t *map = NULL;
|
||||
if (type == &mp_type_module) {
|
||||
map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj));
|
||||
map = &mp_obj_module_get_globals(obj)->map;
|
||||
} else {
|
||||
if (type == &mp_type_type) {
|
||||
type = MP_OBJ_TO_PTR(obj);
|
||||
}
|
||||
if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
|
||||
map = mp_obj_dict_get_map(type->locals_dict);
|
||||
if (type->locals_dict != NULL) {
|
||||
map = &type->locals_dict->map;
|
||||
}
|
||||
}
|
||||
if (map != NULL) {
|
||||
|
|
325
py/compile.c
325
py/compile.c
|
@ -172,7 +172,18 @@ STATIC uint comp_next_label(compiler_t *comp) {
|
|||
return comp->next_label++;
|
||||
}
|
||||
|
||||
STATIC void compile_increase_except_level(compiler_t *comp) {
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
STATIC void reserve_labels_for_native(compiler_t *comp, int n) {
|
||||
if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
|
||||
comp->next_label += n;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define reserve_labels_for_native(comp, n)
|
||||
#endif
|
||||
|
||||
STATIC void compile_increase_except_level(compiler_t *comp, uint label, int kind) {
|
||||
EMIT_ARG(setup_block, label, kind);
|
||||
comp->cur_except_level += 1;
|
||||
if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
|
||||
comp->scope_cur->exc_stack_size = comp->cur_except_level;
|
||||
|
@ -182,6 +193,8 @@ STATIC void compile_increase_except_level(compiler_t *comp) {
|
|||
STATIC void compile_decrease_except_level(compiler_t *comp) {
|
||||
assert(comp->cur_except_level > 0);
|
||||
comp->cur_except_level -= 1;
|
||||
EMIT(end_finally);
|
||||
reserve_labels_for_native(comp, 1);
|
||||
}
|
||||
|
||||
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
|
||||
|
@ -556,6 +569,11 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int
|
|||
}
|
||||
this_scope->num_def_pos_args = n_pos_defaults;
|
||||
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
// When creating a function/closure it will take a reference to the current globals
|
||||
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS;
|
||||
#endif
|
||||
|
||||
// make closed over variables, if any
|
||||
// ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
|
||||
int nfree = 0;
|
||||
|
@ -1173,23 +1191,24 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst, bool added, id_info_t *id_info) {
|
||||
if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
|
||||
if (id_info->kind != ID_INFO_KIND_UNDECIDED && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
compile_syntax_error(comp, pn, translate("identifier redefined as global"));
|
||||
return;
|
||||
}
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
|
||||
// if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
|
||||
id_info = scope_find_global(comp->scope_cur, qst);
|
||||
id_info = scope_find_global(comp->scope_cur, id_info->qst);
|
||||
if (id_info != NULL) {
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst, bool added, id_info_t *id_info) {
|
||||
if (added) {
|
||||
scope_find_local_and_close_over(comp->scope_cur, id_info, qst);
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
|
||||
if (id_info->kind == ID_INFO_KIND_UNDECIDED) {
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
|
||||
scope_check_to_close_over(comp->scope_cur, id_info);
|
||||
if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
compile_syntax_error(comp, pn, translate("no binding for nonlocal found"));
|
||||
}
|
||||
|
@ -1211,12 +1230,11 @@ STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_
|
|||
int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
|
||||
for (int i = 0; i < n; i++) {
|
||||
qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]);
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED);
|
||||
if (is_global) {
|
||||
compile_declare_global(comp, (mp_parse_node_t)pns, qst, added, id_info);
|
||||
compile_declare_global(comp, (mp_parse_node_t)pns, id_info);
|
||||
} else {
|
||||
compile_declare_nonlocal(comp, (mp_parse_node_t)pns, qst, added, id_info);
|
||||
compile_declare_nonlocal(comp, (mp_parse_node_t)pns, id_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1524,8 +1542,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
|||
uint l1 = comp_next_label(comp);
|
||||
uint success_label = comp_next_label(comp);
|
||||
|
||||
EMIT_ARG(setup_block, l1, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
compile_increase_except_level(comp);
|
||||
compile_increase_except_level(comp, l1, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
|
||||
compile_node(comp, pn_body); // body
|
||||
EMIT(pop_block);
|
||||
|
@ -1579,8 +1596,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
|||
uint l3 = 0;
|
||||
if (qstr_exception_local != 0) {
|
||||
l3 = comp_next_label(comp);
|
||||
EMIT_ARG(setup_block, l3, MP_EMIT_SETUP_BLOCK_FINALLY);
|
||||
compile_increase_except_level(comp);
|
||||
compile_increase_except_level(comp, l3, MP_EMIT_SETUP_BLOCK_FINALLY);
|
||||
}
|
||||
compile_node(comp, pns_except->nodes[1]);
|
||||
if (qstr_exception_local != 0) {
|
||||
|
@ -1595,7 +1611,6 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
|||
compile_delete_id(comp, qstr_exception_local);
|
||||
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
}
|
||||
EMIT_ARG(jump, l2);
|
||||
EMIT_ARG(label_assign, end_finally_label);
|
||||
|
@ -1603,7 +1618,6 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
|||
}
|
||||
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
EMIT(end_except_handler);
|
||||
|
||||
EMIT_ARG(label_assign, success_label);
|
||||
|
@ -1614,8 +1628,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
|||
STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
|
||||
uint l_finally_block = comp_next_label(comp);
|
||||
|
||||
EMIT_ARG(setup_block, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
|
||||
compile_increase_except_level(comp);
|
||||
compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
|
||||
|
||||
if (n_except == 0) {
|
||||
assert(MP_PARSE_NODE_IS_NULL(pn_else));
|
||||
|
@ -1631,7 +1644,6 @@ STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n
|
|||
compile_node(comp, pn_finally);
|
||||
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
}
|
||||
|
||||
STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
|
@ -1667,30 +1679,24 @@ STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *n
|
|||
compile_node(comp, body);
|
||||
} else {
|
||||
uint l_end = comp_next_label(comp);
|
||||
if (MICROPY_EMIT_NATIVE && comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
|
||||
// we need to allocate an extra label for the native emitter
|
||||
// it will use l_end+1 as an auxiliary label
|
||||
comp_next_label(comp);
|
||||
}
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
|
||||
// this pre-bit is of the form "a as b"
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)nodes[0];
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
EMIT_ARG(setup_block, l_end, MP_EMIT_SETUP_BLOCK_WITH);
|
||||
compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH);
|
||||
c_assign(comp, pns->nodes[1], ASSIGN_STORE);
|
||||
} else {
|
||||
// this pre-bit is just an expression
|
||||
compile_node(comp, nodes[0]);
|
||||
EMIT_ARG(setup_block, l_end, MP_EMIT_SETUP_BLOCK_WITH);
|
||||
compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH);
|
||||
EMIT(pop_top);
|
||||
}
|
||||
compile_increase_except_level(comp);
|
||||
// compile additional pre-bits and the body
|
||||
compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
|
||||
// finish this with block
|
||||
EMIT_ARG(with_cleanup, l_end);
|
||||
reserve_labels_for_native(comp, 3); // used by native's with_cleanup
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1708,6 +1714,7 @@ STATIC void compile_yield_from(compiler_t *comp) {
|
|||
EMIT_ARG(get_iter, false);
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
|
||||
EMIT_ARG(yield, MP_EMIT_YIELD_FROM);
|
||||
reserve_labels_for_native(comp, 3);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_ASYNC_AWAIT
|
||||
|
@ -1749,8 +1756,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
|
|||
|
||||
EMIT_ARG(label_assign, continue_label);
|
||||
|
||||
EMIT_ARG(setup_block, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
compile_increase_except_level(comp);
|
||||
compile_increase_except_level(comp, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
|
||||
compile_load_id(comp, context);
|
||||
compile_await_object_method(comp, MP_QSTR___anext__);
|
||||
|
@ -1771,7 +1777,6 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
|
|||
EMIT_ARG(label_assign, try_finally_label);
|
||||
EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
EMIT(end_except_handler);
|
||||
|
||||
EMIT_ARG(label_assign, try_else_label);
|
||||
|
@ -1792,46 +1797,70 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
|
|||
// no more pre-bits, compile the body of the with
|
||||
compile_node(comp, body);
|
||||
} else {
|
||||
uint try_exception_label = comp_next_label(comp);
|
||||
uint no_reraise_label = comp_next_label(comp);
|
||||
uint try_else_label = comp_next_label(comp);
|
||||
uint end_label = comp_next_label(comp);
|
||||
qstr context;
|
||||
uint l_finally_block = comp_next_label(comp);
|
||||
uint l_aexit_no_exc = comp_next_label(comp);
|
||||
uint l_ret_unwind_jump = comp_next_label(comp);
|
||||
uint l_end = comp_next_label(comp);
|
||||
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
|
||||
// this pre-bit is of the form "a as b"
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)nodes[0];
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
compile_store_id(comp, context);
|
||||
compile_load_id(comp, context);
|
||||
EMIT(dup_top);
|
||||
compile_await_object_method(comp, MP_QSTR___aenter__);
|
||||
c_assign(comp, pns->nodes[1], ASSIGN_STORE);
|
||||
} else {
|
||||
// this pre-bit is just an expression
|
||||
compile_node(comp, nodes[0]);
|
||||
context = MP_PARSE_NODE_LEAF_ARG(nodes[0]);
|
||||
compile_store_id(comp, context);
|
||||
compile_load_id(comp, context);
|
||||
EMIT(dup_top);
|
||||
compile_await_object_method(comp, MP_QSTR___aenter__);
|
||||
EMIT(pop_top);
|
||||
}
|
||||
|
||||
compile_load_id(comp, context);
|
||||
EMIT_ARG(load_method, MP_QSTR___aexit__, false);
|
||||
// To keep the Python stack size down, and because we can't access values on
|
||||
// this stack further down than 3 elements (via rot_three), we don't preload
|
||||
// __aexit__ (as per normal with) but rather wait until we need it below.
|
||||
|
||||
EMIT_ARG(setup_block, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT);
|
||||
compile_increase_except_level(comp);
|
||||
// compile additional pre-bits and the body
|
||||
// Start the try-finally statement
|
||||
compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
|
||||
|
||||
// Compile any additional pre-bits of the "async with", and also the body
|
||||
EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
|
||||
compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body);
|
||||
// finish this with block
|
||||
EMIT_ARG(adjust_stack_size, -3);
|
||||
|
||||
// Finish the "try" block
|
||||
EMIT(pop_block);
|
||||
EMIT_ARG(jump, try_else_label); // jump over exception handler
|
||||
|
||||
EMIT_ARG(label_assign, try_exception_label); // start of exception handler
|
||||
EMIT(start_except_handler);
|
||||
// At this point, after the with body has executed, we have 3 cases:
|
||||
// 1. no exception, we just fall through to this point; stack: (..., ctx_mgr)
|
||||
// 2. exception propagating out, we get to the finally block; stack: (..., ctx_mgr, exc)
|
||||
// 3. return or unwind jump, we get to the finally block; stack: (..., ctx_mgr, X, INT)
|
||||
|
||||
// at this point the stack contains: ..., __aexit__, self, exc
|
||||
// Handle case 1: call __aexit__
|
||||
// Stack: (..., ctx_mgr)
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception
|
||||
EMIT(rot_two);
|
||||
EMIT_ARG(jump, l_aexit_no_exc); // jump to code below to call __aexit__
|
||||
|
||||
// Start of "finally" block
|
||||
// At this point we have case 2 or 3, we detect which one by the TOS being an exception or not
|
||||
EMIT_ARG(label_assign, l_finally_block);
|
||||
|
||||
// Detect if TOS an exception or not
|
||||
EMIT(dup_top);
|
||||
EMIT_LOAD_GLOBAL(MP_QSTR_Exception);
|
||||
EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
|
||||
EMIT_ARG(pop_jump_if, false, l_ret_unwind_jump); // if not an exception then we have case 3
|
||||
|
||||
// Handle case 2: call __aexit__ and either swallow or re-raise the exception
|
||||
// Stack: (..., ctx_mgr, exc)
|
||||
EMIT(dup_top);
|
||||
EMIT(rot_three);
|
||||
EMIT(rot_two);
|
||||
EMIT_ARG(load_method, MP_QSTR___aexit__, false);
|
||||
EMIT(rot_three);
|
||||
EMIT(rot_three);
|
||||
EMIT(dup_top);
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
EMIT_ARG(attr, MP_QSTR___class__, MP_EMIT_ATTR_LOAD); // get type(exc)
|
||||
|
@ -1842,32 +1871,37 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
|
|||
#endif
|
||||
EMIT(rot_two);
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value
|
||||
// at this point the stack contains: ..., __aexit__, self, type(exc), exc, None
|
||||
// Stack: (..., exc, __aexit__, ctx_mgr, type(exc), exc, None)
|
||||
EMIT_ARG(call_method, 3, 0, 0);
|
||||
|
||||
compile_yield_from(comp);
|
||||
EMIT_ARG(pop_jump_if, true, no_reraise_label);
|
||||
EMIT_ARG(raise_varargs, 0);
|
||||
EMIT_ARG(pop_jump_if, false, l_end);
|
||||
EMIT(pop_top); // pop exception
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // replace with None to swallow exception
|
||||
EMIT_ARG(jump, l_end);
|
||||
EMIT_ARG(adjust_stack_size, 2);
|
||||
|
||||
EMIT_ARG(label_assign, no_reraise_label);
|
||||
EMIT(pop_except);
|
||||
EMIT_ARG(jump, end_label);
|
||||
|
||||
EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
EMIT(end_except_handler);
|
||||
|
||||
EMIT_ARG(label_assign, try_else_label); // start of try-else handler
|
||||
// Handle case 3: call __aexit__
|
||||
// Stack: (..., ctx_mgr, X, INT)
|
||||
EMIT_ARG(label_assign, l_ret_unwind_jump);
|
||||
EMIT(rot_three);
|
||||
EMIT(rot_three);
|
||||
EMIT_ARG(label_assign, l_aexit_no_exc);
|
||||
EMIT_ARG(load_method, MP_QSTR___aexit__, false);
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
|
||||
EMIT(dup_top);
|
||||
EMIT(dup_top);
|
||||
EMIT_ARG(call_method, 3, 0, 0);
|
||||
compile_yield_from(comp);
|
||||
EMIT(pop_top);
|
||||
EMIT_ARG(adjust_stack_size, -1);
|
||||
|
||||
EMIT_ARG(label_assign, end_label);
|
||||
|
||||
// End of "finally" block
|
||||
// Stack can have one of three configurations:
|
||||
// a. (..., None) - from either case 1, or case 2 with swallowed exception
|
||||
// b. (..., exc) - from case 2 with re-raised exception
|
||||
// c. (..., X, INT) - from case 3
|
||||
EMIT_ARG(label_assign, l_end);
|
||||
compile_decrease_except_level(comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2688,6 +2722,7 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
|
||||
EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
|
||||
reserve_labels_for_native(comp, 1);
|
||||
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
|
||||
pns = (mp_parse_node_struct_t *)pns->nodes[0];
|
||||
#if MICROPY_PY_ASYNC_AWAIT
|
||||
|
@ -2701,6 +2736,7 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
} else {
|
||||
compile_node(comp, pns->nodes[0]);
|
||||
EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
|
||||
reserve_labels_for_native(comp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2733,6 +2769,9 @@ STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
|
|||
}
|
||||
|
||||
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_HASCONSTS;
|
||||
#endif
|
||||
EMIT_ARG(load_const_obj, get_const_object(pns));
|
||||
}
|
||||
|
||||
|
@ -2755,7 +2794,7 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
|||
} else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
||||
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
|
||||
#if MICROPY_DYNAMIC_COMPILER
|
||||
mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));
|
||||
mp_uint_t sign_mask = -((mp_uint_t)1 << (mp_dynamic_compiler.small_int_bits - 1));
|
||||
if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {
|
||||
// integer fits in target runtime's small-int
|
||||
EMIT_ARG(load_const_small_int, arg);
|
||||
|
@ -2767,6 +2806,9 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
|||
} else {
|
||||
EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));
|
||||
}
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_HASCONSTS;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
EMIT_ARG(load_const_small_int, arg);
|
||||
|
@ -2789,6 +2831,9 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
|||
const byte *data = qstr_data(arg, &len);
|
||||
EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
|
||||
}
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_HASCONSTS;
|
||||
#endif
|
||||
break;
|
||||
case MP_PARSE_NODE_TOKEN:
|
||||
default:
|
||||
|
@ -2810,6 +2855,25 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
|||
}
|
||||
}
|
||||
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
STATIC int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_annotation) {
|
||||
int native_type = MP_NATIVE_TYPE_OBJ;
|
||||
if (MP_PARSE_NODE_IS_NULL(pn_annotation)) {
|
||||
// No annotation, type defaults to object
|
||||
} else if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
|
||||
qstr type_name = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
|
||||
native_type = mp_native_type_from_qstr(type_name);
|
||||
if (native_type < 0) {
|
||||
comp->compile_error = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, translate("unknown type '%q'"), type_name);
|
||||
native_type = 0;
|
||||
}
|
||||
} else {
|
||||
compile_syntax_error(comp, pn_annotation, translate("annotation must be an identifier"));
|
||||
}
|
||||
return native_type;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) {
|
||||
// check that **kw is last
|
||||
if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
|
||||
|
@ -2819,6 +2883,7 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
|
||||
qstr param_name = MP_QSTR_NULL;
|
||||
uint param_flag = ID_FLAG_IS_PARAM;
|
||||
mp_parse_node_struct_t *pns = NULL;
|
||||
if (MP_PARSE_NODE_IS_ID(pn)) {
|
||||
param_name = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
if (comp->have_star) {
|
||||
|
@ -2830,8 +2895,9 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
}
|
||||
} else {
|
||||
assert(MP_PARSE_NODE_IS_STRUCT(pn));
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
||||
pns = (mp_parse_node_struct_t *)pn;
|
||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
|
||||
// named parameter with possible annotation
|
||||
param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
if (comp->have_star) {
|
||||
// comes after a star, so counts as a keyword-only parameter
|
||||
|
@ -2852,10 +2918,12 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
// bare star
|
||||
// TODO see http://www.python.org/dev/peps/pep-3102/
|
||||
// assert(comp->scope_cur->num_dict_params == 0);
|
||||
pns = NULL;
|
||||
} else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
|
||||
// named star
|
||||
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
|
||||
param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
pns = NULL;
|
||||
} else {
|
||||
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
|
||||
// named star with possible annotation
|
||||
|
@ -2864,6 +2932,7 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
}
|
||||
} else {
|
||||
// double star with possible annotation
|
||||
assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
|
||||
param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
|
||||
|
@ -2872,14 +2941,21 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
}
|
||||
|
||||
if (param_name != MP_QSTR_NULL) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
|
||||
if (!added) {
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED);
|
||||
if (id_info->kind != ID_INFO_KIND_UNDECIDED) {
|
||||
compile_syntax_error(comp, pn, translate("name reused for argument"));
|
||||
return;
|
||||
}
|
||||
id_info->kind = ID_INFO_KIND_LOCAL;
|
||||
id_info->flags = param_flag;
|
||||
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
if (comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER && pn_name == PN_typedargslist_name && pns != NULL) {
|
||||
id_info->flags |= compile_viper_type_annotation(comp, pns->nodes[1]) << ID_FLAG_VIPER_TYPE_POS;
|
||||
}
|
||||
#else
|
||||
(void)pns;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2891,49 +2967,6 @@ STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
|
|||
compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
|
||||
}
|
||||
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) {
|
||||
if (!MP_PARSE_NODE_IS_STRUCT(pn)) {
|
||||
// no annotation
|
||||
return;
|
||||
}
|
||||
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_name) {
|
||||
// named parameter with possible annotation
|
||||
// fallthrough
|
||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_star) {
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
|
||||
// named star with possible annotation
|
||||
pns = (mp_parse_node_struct_t *)pns->nodes[0];
|
||||
// fallthrough
|
||||
} else {
|
||||
// no annotation
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star);
|
||||
// double star with possible annotation
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
mp_parse_node_t pn_annotation = pns->nodes[1];
|
||||
|
||||
if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
|
||||
qstr param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
|
||||
id_info_t *id_info = scope_find(comp->scope_cur, param_name);
|
||||
assert(id_info != NULL);
|
||||
|
||||
if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
|
||||
qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
|
||||
EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);
|
||||
} else {
|
||||
compile_syntax_error(comp, pn_annotation, translate("parameter annotation must be an identifier"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // MICROPY_EMIT_NATIVE
|
||||
|
||||
STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) {
|
||||
uint l_top = comp_next_label(comp);
|
||||
uint l_end = comp_next_label(comp);
|
||||
|
@ -2948,6 +2981,7 @@ tail_recursion:
|
|||
compile_node(comp, pn_inner_expr);
|
||||
if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {
|
||||
EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
|
||||
reserve_labels_for_native(comp, 1);
|
||||
EMIT(pop_top);
|
||||
} else {
|
||||
EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
|
||||
|
@ -3022,6 +3056,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
comp->scope_cur = scope;
|
||||
comp->next_label = 0;
|
||||
EMIT_ARG(start_pass, pass, scope);
|
||||
reserve_labels_for_native(comp, 6); // used by native's start_pass
|
||||
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
// reset maximum stack sizes in scope
|
||||
|
@ -3053,28 +3088,14 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
comp->have_star = false;
|
||||
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
|
||||
}
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
else if (scope->emit_options == MP_EMIT_OPT_VIPER) {
|
||||
// compile annotations; only needed on latter compiler passes
|
||||
// only needed for viper emitter
|
||||
|
||||
// argument annotations
|
||||
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);
|
||||
|
||||
// pns->nodes[2] is return/whole function annotation
|
||||
mp_parse_node_t pn_annotation = pns->nodes[2];
|
||||
if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
|
||||
// nodes[2] can be null or a test-expr
|
||||
if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
|
||||
qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
|
||||
EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);
|
||||
} else {
|
||||
compile_syntax_error(comp, pn_annotation, translate("return annotation must be an identifier"));
|
||||
}
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
if (scope->emit_options == MP_EMIT_OPT_VIPER) {
|
||||
// Compile return type; pns->nodes[2] is return/whole function annotation
|
||||
scope->scope_flags |= compile_viper_type_annotation(comp, pns->nodes[2]) << MP_SCOPE_FLAG_VIPERRET_POS;
|
||||
}
|
||||
#endif // MICROPY_EMIT_NATIVE
|
||||
}
|
||||
#endif // MICROPY_EMIT_NATIVE
|
||||
|
||||
compile_node(comp, pns->nodes[3]); // 3 is function body
|
||||
// emit return if it wasn't the last opcode
|
||||
|
@ -3117,10 +3138,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
// so we use the blank qstr.
|
||||
qstr qstr_arg = MP_QSTR_;
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
|
||||
assert(added);
|
||||
id_info->kind = ID_INFO_KIND_LOCAL;
|
||||
scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
|
||||
scope->num_pos_args = 1;
|
||||
}
|
||||
|
||||
|
@ -3160,10 +3178,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
|
||||
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
|
||||
assert(added);
|
||||
id_info->kind = ID_INFO_KIND_LOCAL;
|
||||
scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL);
|
||||
}
|
||||
|
||||
compile_load_id(comp, MP_QSTR___name__);
|
||||
|
@ -3393,6 +3408,17 @@ STATIC void scope_compute_things(scope_t *scope) {
|
|||
if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
}
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
// This function makes a reference to a global variable
|
||||
if (scope->emit_options == MP_EMIT_OPT_VIPER
|
||||
&& mp_native_type_from_qstr(id->qst) >= MP_NATIVE_TYPE_INT) {
|
||||
// A casting operator in viper mode, not a real global reference
|
||||
} else {
|
||||
scope->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// params always count for 1 local, even if they are a cell
|
||||
if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
|
||||
id->local_num = scope->num_locals++;
|
||||
|
@ -3476,6 +3502,14 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
#endif
|
||||
} else {
|
||||
compile_scope(comp, s, MP_PASS_SCOPE);
|
||||
|
||||
// Check if any implicitly declared variables should be closed over
|
||||
for (size_t i = 0; i < s->id_info_len; ++i) {
|
||||
id_info_t *id = &s->id_info[i];
|
||||
if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
scope_check_to_close_over(s, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update maximim number of labels needed
|
||||
|
@ -3530,11 +3564,10 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
case MP_EMIT_OPT_NATIVE_PYTHON:
|
||||
case MP_EMIT_OPT_VIPER:
|
||||
if (emit_native == NULL) {
|
||||
emit_native = NATIVE_EMITTER(new)(&comp->compile_error, max_num_labels);
|
||||
emit_native = NATIVE_EMITTER(new)(&comp->compile_error, &comp->next_label, max_num_labels);
|
||||
}
|
||||
comp->emit_method_table = &NATIVE_EMITTER(method_table);
|
||||
comp->emit = emit_native;
|
||||
EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);
|
||||
break;
|
||||
#endif // MICROPY_EMIT_NATIVE
|
||||
|
||||
|
|
|
@ -30,15 +30,6 @@
|
|||
#include "py/parse.h"
|
||||
#include "py/emitglue.h"
|
||||
|
||||
// These must fit in 8 bits; see scope.h
|
||||
enum {
|
||||
MP_EMIT_OPT_NONE,
|
||||
MP_EMIT_OPT_BYTECODE,
|
||||
MP_EMIT_OPT_NATIVE_PYTHON,
|
||||
MP_EMIT_OPT_VIPER,
|
||||
MP_EMIT_OPT_ASM,
|
||||
};
|
||||
|
||||
// the compiler will raise an exception if an error occurred
|
||||
// the compiler will clear the parse tree before it returns
|
||||
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl);
|
||||
|
|
22
py/emit.h
22
py/emit.h
|
@ -51,10 +51,6 @@ typedef enum {
|
|||
|
||||
#define MP_EMIT_BREAK_FROM_FOR (0x8000)
|
||||
|
||||
#define MP_EMIT_NATIVE_TYPE_ENABLE (0)
|
||||
#define MP_EMIT_NATIVE_TYPE_RETURN (1)
|
||||
#define MP_EMIT_NATIVE_TYPE_ARG (2)
|
||||
|
||||
// Kind for emit_id_ops->local()
|
||||
#define MP_EMIT_IDOP_LOCAL_FAST (0)
|
||||
#define MP_EMIT_IDOP_LOCAL_DEREF (1)
|
||||
|
@ -102,7 +98,6 @@ typedef struct _mp_emit_method_table_id_ops_t {
|
|||
} mp_emit_method_table_id_ops_t;
|
||||
|
||||
typedef struct _emit_method_table_t {
|
||||
void (*set_native_type)(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2);
|
||||
void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope);
|
||||
void (*end_pass)(emit_t *emit);
|
||||
bool (*last_emit_was_return_value)(emit_t *emit);
|
||||
|
@ -162,7 +157,12 @@ typedef struct _emit_method_table_t {
|
|||
void (*end_except_handler)(emit_t *emit);
|
||||
} emit_method_table_t;
|
||||
|
||||
void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst);
|
||||
int mp_native_type_from_qstr(qstr qst);
|
||||
|
||||
static inline void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
|
||||
scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
|
||||
}
|
||||
|
||||
void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst);
|
||||
void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst);
|
||||
|
||||
|
@ -178,11 +178,11 @@ extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops;
|
|||
extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops;
|
||||
|
||||
emit_t *emit_bc_new(void);
|
||||
emit_t *emit_native_x64_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_x86_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_thumb_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_arm_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_xtensa_new(mp_obj_t *error_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_x64_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_x86_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_thumb_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_arm_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
|
||||
emit_t *emit_native_xtensa_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
|
||||
|
||||
void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels);
|
||||
|
||||
|
|
|
@ -331,6 +331,10 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
|||
// the highest slot in the state (fastn[0], see vm.c).
|
||||
n_state = 1;
|
||||
}
|
||||
#if MICROPY_DEBUG_VM_STACK_OVERFLOW
|
||||
// An extra slot in the stack is needed to detect VM stack overflow
|
||||
n_state += 1;
|
||||
#endif
|
||||
emit_write_code_info_uint(emit, n_state);
|
||||
emit_write_code_info_uint(emit, scope->exc_stack_size);
|
||||
}
|
||||
|
@ -916,7 +920,6 @@ void mp_emit_bc_end_except_handler(emit_t *emit) {
|
|||
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
const emit_method_table_t emit_bc_method_table = {
|
||||
NULL, // set_native_type is never called when emitting bytecode
|
||||
mp_emit_bc_start_pass,
|
||||
mp_emit_bc_end_pass,
|
||||
mp_emit_bc_last_emit_was_return_value,
|
||||
|
|
|
@ -30,26 +30,10 @@
|
|||
|
||||
#if MICROPY_ENABLE_COMPILER
|
||||
|
||||
void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
|
||||
// name adding/lookup
|
||||
bool added;
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, &added);
|
||||
if (added) {
|
||||
scope_find_local_and_close_over(scope, id, qst);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {
|
||||
// name adding/lookup
|
||||
bool added;
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, &added);
|
||||
if (added) {
|
||||
if (SCOPE_IS_FUNC_LIKE(scope->kind)) {
|
||||
id->kind = ID_INFO_KIND_LOCAL;
|
||||
} else {
|
||||
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
|
||||
}
|
||||
} else if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
|
||||
if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
// rebind as a local variable
|
||||
id->kind = ID_INFO_KIND_LOCAL;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,9 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
|
|||
#endif
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#if !MICROPY_DEBUG_PRINTERS
|
||||
const size_t len = 0;
|
||||
#endif
|
||||
DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
|
||||
#endif
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
|
@ -131,10 +134,8 @@ mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_ar
|
|||
switch (rc->kind) {
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
case MP_CODE_NATIVE_PY:
|
||||
fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
|
||||
break;
|
||||
case MP_CODE_NATIVE_VIPER:
|
||||
fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
|
||||
fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
|
||||
break;
|
||||
#endif
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
|
|
|
@ -30,6 +30,15 @@
|
|||
|
||||
// These variables and functions glue the code emitters to the runtime.
|
||||
|
||||
// These must fit in 8 bits; see scope.h
|
||||
enum {
|
||||
MP_EMIT_OPT_NONE,
|
||||
MP_EMIT_OPT_BYTECODE,
|
||||
MP_EMIT_OPT_NATIVE_PYTHON,
|
||||
MP_EMIT_OPT_VIPER,
|
||||
MP_EMIT_OPT_ASM,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MP_CODE_UNUSED,
|
||||
MP_CODE_RESERVED,
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
#define GENERIC_ASM_API (1)
|
||||
#include "py/asmarm.h"
|
||||
|
||||
// Word indices of REG_LOCAL_x in nlr_buf_t
|
||||
#define NLR_BUF_IDX_LOCAL_1 (3) // r4
|
||||
#define NLR_BUF_IDX_LOCAL_2 (4) // r5
|
||||
#define NLR_BUF_IDX_LOCAL_3 (5) // r6
|
||||
|
||||
#define N_ARM (1)
|
||||
#define EXPORT_FUN(name) emit_native_arm_##name
|
||||
#include "py/emitnative.c"
|
||||
|
|
1364
py/emitnative.c
1364
py/emitnative.c
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,11 @@
|
|||
#define GENERIC_ASM_API (1)
|
||||
#include "py/asmthumb.h"
|
||||
|
||||
// Word indices of REG_LOCAL_x in nlr_buf_t
|
||||
#define NLR_BUF_IDX_LOCAL_1 (3) // r4
|
||||
#define NLR_BUF_IDX_LOCAL_2 (4) // r5
|
||||
#define NLR_BUF_IDX_LOCAL_3 (5) // r6
|
||||
|
||||
#define N_THUMB (1)
|
||||
#define EXPORT_FUN(name) emit_native_thumb_##name
|
||||
#include "py/emitnative.c"
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
#define GENERIC_ASM_API (1)
|
||||
#include "py/asmx64.h"
|
||||
|
||||
// Word indices of REG_LOCAL_x in nlr_buf_t
|
||||
#define NLR_BUF_IDX_LOCAL_1 (5) // rbx
|
||||
#define NLR_BUF_IDX_LOCAL_2 (6) // r12
|
||||
#define NLR_BUF_IDX_LOCAL_3 (7) // r13
|
||||
|
||||
#define N_X64 (1)
|
||||
#define EXPORT_FUN(name) emit_native_x64_##name
|
||||
#include "py/emitnative.c"
|
||||
|
|
|
@ -9,10 +9,16 @@
|
|||
#define GENERIC_ASM_API (1)
|
||||
#include "py/asmx86.h"
|
||||
|
||||
// Word indices of REG_LOCAL_x in nlr_buf_t
|
||||
#define NLR_BUF_IDX_LOCAL_1 (5) // ebx
|
||||
#define NLR_BUF_IDX_LOCAL_2 (7) // esi
|
||||
#define NLR_BUF_IDX_LOCAL_3 (6) // edi
|
||||
|
||||
// x86 needs a table to know how many args a given function has
|
||||
STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
|
||||
[MP_F_CONVERT_OBJ_TO_NATIVE] = 2,
|
||||
[MP_F_CONVERT_NATIVE_TO_OBJ] = 2,
|
||||
[MP_F_NATIVE_SWAP_GLOBALS] = 1,
|
||||
[MP_F_LOAD_NAME] = 1,
|
||||
[MP_F_LOAD_GLOBAL] = 1,
|
||||
[MP_F_LOAD_BUILD_CLASS] = 0,
|
||||
|
@ -56,9 +62,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
|
|||
[MP_F_DELETE_GLOBAL] = 1,
|
||||
[MP_F_NEW_CELL] = 1,
|
||||
[MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3,
|
||||
[MP_F_SETUP_CODE_STATE] = 5,
|
||||
[MP_F_ARG_CHECK_NUM_SIG] = 3,
|
||||
[MP_F_SETUP_CODE_STATE] = 4,
|
||||
[MP_F_SMALL_INT_FLOOR_DIVIDE] = 2,
|
||||
[MP_F_SMALL_INT_MODULO] = 2,
|
||||
[MP_F_NATIVE_YIELD_FROM] = 3,
|
||||
};
|
||||
|
||||
#define N_X86 (1)
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
#define GENERIC_ASM_API (1)
|
||||
#include "py/asmxtensa.h"
|
||||
|
||||
// Word indices of REG_LOCAL_x in nlr_buf_t
|
||||
#define NLR_BUF_IDX_LOCAL_1 (8) // a12
|
||||
#define NLR_BUF_IDX_LOCAL_2 (9) // a13
|
||||
#define NLR_BUF_IDX_LOCAL_3 (10) // a14
|
||||
|
||||
#define N_XTENSA (1)
|
||||
#define EXPORT_FUN(name) emit_native_xtensa_##name
|
||||
#include "py/emitnative.c"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue