Skip to content

Conversation

@e-tobi
Copy link

@e-tobi e-tobi commented May 23, 2020

parenthesis-typo caused tls_reg_read() to hang on invalid register

jimmo and others added 30 commits March 11, 2020 13:01
This commit ensures that the BLE stack is active before allowing operations
that may otherwise crash if it's not active.  It also clarifies the state
better (adding the "stopping" state) and renames mp_bluetooth_is_enabled to
the more self-explanatory mp_bluetooth_is_active.
Most error handling is done via `bluetooth_handle_errno()` already.
Replace the remaining few manual checks with calls to that function.
This fixes a crash, caused by NimBLE continuing to call the Python BLE
interrupt handler after soft reboot.
This commit changes the BLE _IRQ_SCAN_RESULT data from:

    addr_type, addr, connectable, rssi, adv_data

to:

    addr_type, addr, adv_type, rssi, adv_data

This allows _IRQ_SCAN_RESULT to handle all scan result types (not just
connectable and non-connectable passive scans), and to distinguish between
them using adv_type which is an integer taking values 0x00-0x04 per the BT
specification.

This is a breaking change to the API, albeit a very minor one: the existing
connectable value was a boolean and True now becomes 0x00, False becomes
0x02.

Documentation is updated and a test added.

Fixes micropython#5738.
This is needed for BLE.config('mac') to work on esp32.
The double-% was added in 11de839 (Jun
2014) when such errors were formatted with printf.  But then
55830dd (Dec 2018) changed
mp_obj_new_exception_msg() to not format the message, as discussed
in micropython#3004.  So such error strings are no longer formatted and a % is just
that.
This eliminates the need for the sizeof regex fixup by rearranging things a
bit.  All other bitfields already use the parentheses around expressions
with sizeof, so one case is fixed by following this convention.

VM_MAX_STATE_ON_STACK is the only remaining problem and it can be worked
around by changing the order of the operands.
This is an extremely minimal port to the NXP i.MX RT, in the style of the
SAMD port  It's largely based on the TinyUSB mimxrt implementation, using
the NXP SDK.  It currently supports the Teensy 4.0 board with a REPL over
the USB-VCP interface.

This commit also adds the NXP SDK submodule (also from TinyUSB) to
lib/nxp_driver.

Note: if you already have the tinyusb submodule initialized recursively you
will need to run the following as the tinyusb sub-submodules have been
rearranged (upstream):

    git submodule deinit lib/tinyusb
    rm -rf .git/modules/lib/tinyusb
    git submodule update --init lib/tinyusb
This commit adds micropython.heap_locked() which returns the current
lock-depth of the heap, and can be used by Python code to check if the heap
is locked or not.  This new function is configured via
MICROPY_PY_MICROPYTHON_HEAP_LOCKED and is disabled by default.

This commit also changes the return value of micropython.heap_unlock() so
it returns the current lock-depth as well.
So that they are skipped when running on a target that doesn't support the
native emitter, eg a nanbox build.
Adds support in the zephyr port to mount a file system if a block device
(sdhc disk access or flash area) is available. The mount point is either
"/sd" or "/flash" depending on the type of block device.

Tested with an sdhc disk access block device and fatfs on the
mimxrt1050_evk board.

Tested with a flash area block device and littlefs on the reel_board.
Enables the zephyr usb device stack and mass storage class on the
mimxrt1050_evk board. The mass storage class is backed by the sdhc disk
access driver, so it's now possible to browse and modify the contents of
the SD card from a USB host (your PC). This is in preparation to support
writing a main.py script to the SD card, and then executing it after the
next reset.
Adds support in the zephyr port to execute main.py if the file system is
enabled and the file exists. Existing support for executing a main.py
frozen module is preserved, since pyexec_file_if_exists() works just
like pyexec_frozen_module() if there's no vfs.
Follow up to dd0bc26 which changed the
parameter list of the IRQ_SCAN_RESULT event.  Adapt
ble_temperature_central.py accordingly.
STATE_NEW will return HUP when polled so put active UDP sockets into a new
state which is different to STATE_NEW.

Fixes issue micropython#5758.
Fixes UDP non-blocking recv so it returns EAGAIN instead of ETIMEDOUT.
Timeout waiting for incoming data is also improved by replacing 100ms delay
with poll_sockets(), as is done in other parts of this module.

Fixes issue micropython#5759.
Also support MP_STREAM_GET_FILENO ioctl.  The stdio flush change was done
previously for the unix port in 3e0b46b.
These changes make this POSIX file implementation equivalent to the unix
file implementation.
The implementation in extmod/vfs_posix_file.c is now equivalent to that in
ports/unix/file.c, so remove the latter and use the former instead.
@robert-hh
Copy link

Looks better this way.

@robert-hh
Copy link

I tested that again and it works. I'm sure that I tested it before. Just as a hint: I use the repository here just as a "backport" place. Usually I maintain a repo here: https://github.com/robert-hh/micropython/tree/w60x
It is linked to the up-to-date version of MicroPython and has for instance uasyncio included, but threading excluded. The latter seems not to work. Still on my to-do list. Anyhow, uasyncio is faster and more efficient.

@e-tobi
Copy link
Author

e-tobi commented May 24, 2020

I've created a PR in your fork as well.
What exactly is the "official" MP W60x repository then? Thhis one from WinnerMicro or yours?
uasyncio is cool - I'll test this.

Which SDK version are you using? I test with G3.02. With G3.04 I can't make it compile in the 1M flash version.

Currently I run into problems getting OneWire to work, because the W60x-SDK has no "real" OPEN_DRAIN mode. I'm working on this right now.

@robert-hh
Copy link

robert-hh commented May 24, 2020

The "Official one" is the one from Winner Micro. I'm using my fork because I prefer to have a recent Micropython version. I changed it already to match your PR form yesterday.
I am using G3.04. SDK. I have a copy here with a few minor modifications. https://github.com/robert-hh/WM_SDK_W60X. I avoid the 1M flash problem by modifying the loader file. tools/link_w600_1m.ld

  FLASH (rx) : ORIGIN = 0x8010100, LENGTH = 600K /* 600KB-256B */

That way you cannot use the compressed flash method any more. You can then also increase the size of the flash FS.

By modifying the flash script you can also prevent the file system to be erased all the time change:
./${DLIMG} -c ${SERIAL_NAME} -ds 2M -dl "${BUILD}/${TARGET}.fls" -eo all -rs rts
into
./${DLIMG} -c ${SERIAL_NAME} -ds 2M -dl "${BUILD}/${TARGET}.fls" -eo secboot -rs rts

About Onewire: the software version of I2C has the same problems. It uses the macros from include/mphalport.h:

static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
    tls_gpio_cfg(pin, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
}
static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) {
    tls_gpio_cfg(pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
    tls_gpio_write(pin, 0);
}
static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) {
    tls_gpio_cfg(pin, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
    tls_gpio_write(pin, 1);
}

@robert-hh
Copy link

I managed to get some reading from a DS18B20 sensor using a modified modonewire.c file (copy below). That's just the working state. The biggest problem is, that the timing of mp_hal_delay_us() is wrong. As a first hack, I modified the values in modonewire.c to tell, whether it would work then. Next is to fix mp_hal_delay_us(). I moved modonewire.c into the modules folder of the W60x port.
onewire.py and ds18x20.py are the ones from micropython/drivers/onewire. The test script is the one from the docs.

/*
 * This file is part of the MicroPython project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2017 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 <stdio.h>
#include <stdint.h>

#include "py/obj.h"
#include "py/mphal.h"

#include "mphalport.h"
#include "wm_io.h"
#include "wm_gpio.h"
/******************************************************************************/
// Low-level 1-Wire routines

#define TIMING_RESET1 (190) // (480)
#define TIMING_RESET2 (35) // (70)
#define TIMING_RESET3 (150) // (410)
#define TIMING_READ1 (1) // (5)
#define TIMING_READ2 (1) // (5)
#define TIMING_READ3 (20) // (40)
#define TIMING_WRITE1 (3) / (10)
#define TIMING_WRITE2 (20) // (50)
#define TIMING_WRITE3 (4) // (10)

STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) {
    mp_hal_pin_od_low(pin);
    mp_hal_delay_us(TIMING_RESET1);
    uint32_t i = mp_hal_quiet_timing_enter();
    mp_hal_pin_od_high(pin);
    mp_hal_delay_us_fast(TIMING_RESET2);
    int status = !mp_hal_pin_read(pin);
    mp_hal_quiet_timing_exit(i);
    mp_hal_delay_us(TIMING_RESET3);
    return status;
}

STATIC int onewire_bus_readbit(mp_hal_pin_obj_t pin) {
    mp_hal_pin_od_high(pin);
    uint32_t i = mp_hal_quiet_timing_enter();
    mp_hal_pin_od_low(pin);
    mp_hal_delay_us_fast(TIMING_READ1);
    mp_hal_pin_od_high(pin);
    mp_hal_delay_us_fast(TIMING_READ2);
    int value = mp_hal_pin_read(pin);
    mp_hal_quiet_timing_exit(i);
    mp_hal_delay_us_fast(TIMING_READ3);
    return value;
}

STATIC void onewire_bus_writebit(mp_hal_pin_obj_t pin, int value) {
    uint32_t i = mp_hal_quiet_timing_enter();
    mp_hal_pin_od_low(pin);
    mp_hal_delay_us_fast(TIMING_WRITE1);
    if (value) {
        mp_hal_pin_od_high(pin);
    }
    mp_hal_delay_us_fast(TIMING_WRITE2);
    mp_hal_pin_od_high(pin);
    mp_hal_delay_us_fast(TIMING_WRITE3);
    mp_hal_quiet_timing_exit(i);
}

/******************************************************************************/
// MicroPython bindings

STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) {
    return mp_obj_new_bool(onewire_bus_reset(mp_hal_get_pin_obj(pin_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset);

STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) {
    return MP_OBJ_NEW_SMALL_INT(onewire_bus_readbit(mp_hal_get_pin_obj(pin_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit);

STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) {
    mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
    uint8_t value = 0;
    for (int i = 0; i < 8; ++i) {
        value |= onewire_bus_readbit(pin) << i;
    }
    return MP_OBJ_NEW_SMALL_INT(value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte);

STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) {
    onewire_bus_writebit(mp_hal_get_pin_obj(pin_in), mp_obj_get_int(value_in));
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit);

STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) {
    mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
    int value = mp_obj_get_int(value_in);
    for (int i = 0; i < 8; ++i) {
        onewire_bus_writebit(pin, value & 1);
        value >>= 1;
    }
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebyte_obj, onewire_writebyte);

STATIC mp_obj_t onewire_crc8(mp_obj_t data) {
    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
    uint8_t crc = 0;
    for (size_t i = 0; i < bufinfo.len; ++i) {
        uint8_t byte = ((uint8_t *)bufinfo.buf)[i];
        for (int b = 0; b < 8; ++b) {
            uint8_t fb_bit = (crc ^ byte) & 0x01;
            if (fb_bit == 0x01) {
                crc = crc ^ 0x18;
            }
            crc = (crc >> 1) & 0x7f;
            if (fb_bit == 0x01) {
                crc = crc | 0x80;
            }
            byte = byte >> 1;
        }
    }
    return MP_OBJ_NEW_SMALL_INT(crc);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_crc8_obj, onewire_crc8);

STATIC const mp_rom_map_elem_t onewire_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewire) },

    { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&onewire_reset_obj) },
    { MP_ROM_QSTR(MP_QSTR_readbit), MP_ROM_PTR(&onewire_readbit_obj) },
    { MP_ROM_QSTR(MP_QSTR_readbyte), MP_ROM_PTR(&onewire_readbyte_obj) },
    { MP_ROM_QSTR(MP_QSTR_writebit), MP_ROM_PTR(&onewire_writebit_obj) },
    { MP_ROM_QSTR(MP_QSTR_writebyte), MP_ROM_PTR(&onewire_writebyte_obj) },
    { MP_ROM_QSTR(MP_QSTR_crc8), MP_ROM_PTR(&onewire_crc8_obj) },
};

STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table);

const mp_obj_module_t mp_module_onewire = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&onewire_module_globals,
};

@e-tobi
Copy link
Author

e-tobi commented May 24, 2020

Thanks for your work!
I took a different route and implemented OPEN_DRAIN support directly into machine_pin.c. I think this might be the better way, so no libraries calling these functions need to be modified.
I'll provide a PR once I've tested everything.

I've also stumbled upon the timing problem. delay_us is way off - a simple loop with 2 x 500 µs delays resulted in a 390 Hz signal, while 1 kHz is expected. I fixed this by using tls_usleep in mphalport.c (will provide a PR for this as well).

Now I'm trying to get this all together working with the unmodified OneWire code from MP.

@robert-hh
Copy link

Implementing OPEN_DRAIN in the PIN class is surely a good thing. You have to store in the pin object the output mode, and then you can decide upon writing a 1, which way to go. That seems straightforward. But at a few files mp_hal_pin_write() is called, which

drivers/bus/softqspi.c
drivers/bus/softspi.c
drivers/memory/spiflash.c
extmod/modonewire.c

For these you have to extend mp_hal_pin_obj_t to carry the output mode too.

Using tls_usleep() instead of delay_us() does not work for me. After a few delays, the micro simply stalls.
B.t.w.: Do you know where delay_us is implemented? I looked for it and did not find it. But I may have bad eyes today.

@e-tobi
Copy link
Author

e-tobi commented May 24, 2020

delay_us is exported in the wlan-library (wlan.lib/wlan.a) -

@robert-hh
Copy link

OK. No wonder that I did not find it in the sources. And I did not look yet into the linker map (and ignored grep telling it).

EddieParis and others added 19 commits May 27, 2020 16:15
The PWM driver uses a double buffer for the PWM timing array, one in
current use and the other one to update when changing duty parameters.
The issue was that once the duty parameters were changed the updated buffer
was applied immediately without synchronising to the start of the PWM
period.  By moving the buffer toggling/swapping to the interrupt when the
cycle is done there are no more glitches.
The linker script was included in the "$^" inputs, causing the build to
fail:

 LINK build/firmware.elf
 powerpc64le-linux-gnu-ld: error: linker script file 'powerpc.lds' appears multiple times

As a fix the linker script is left as a dependency of the elf, but only the
object files are linked.
Most developers use a compiler which is called powerpc64le-linux-gnu-gcc.
The env NAME="foo" syntax doesn't appear to set the name in the Travis web
interface.  Instead use the syntax from the docs:

 https://docs.travis-ci.com/user/build-stages/#naming-your-jobs-within-build-stages
Otherwise scheduled functions may execute during the hard callback and then
fail if they try to allocate heap memory.
Otherwise functions like memset might get optimised to call themselves (eg
with gcc 10).  And provide CFLAGS_BUILTIN so these options can be changed
by a port if needed.

Fixes issue micropython#6053.
Older implementations deal with infinity/negative zero incorrectly.  This
commit adds generic fixes that can be enabled by any port that needs them,
along with new tests cases.
Older versions do not have "inline" so fetch the definition from
mpconfigport.h.
Add configuration which otherwise has to be set via the UI so the file is
more self-contained, and remove configuration which is not needed because
it's the same as the default.  The major change here is that for a while
now Appveyor has been using Visual Studio 2015 by default while we still
want to support 2013.
This renames a few identifiers to follow the usual naming convention of
mp_<module>_<name>.  This makes them easier to find, e.g. when grep'ing.
This suppresses the Parsing: <file> as language C lines.  This makes
parsing run a bit faster and on CI it makes for less scrolling through logs
(and black already uses the -q option).
The code previously called rtc_get_reset_reason which is a "raw" reset
cause.  The ESP-IDF massages that for the proper reset cause available from
esp_reset_reason.

Fixes issue micropython#5134.
Microwatt may have firmware that places data in r3, which was used to
detect microwatt vs powernv.  This breaks the existing probing of the UART
type in this powerpc port.

Instead build only the appropriate UART into the firmware, selected by
passing the option UART=potato or UART=lpc_serial to the Makefile.

A future enhancement would be to parse the device tree and configure
MicroPython based on the settings.
The powerpc port can be built with two different UART drivers, so build
both in CI.

The default compiler is now powerpc64le-linux-gnu- so it does not need to
be specified on the command line.
This adds a new command line option `-v` to `tools/codeformat.py` to enable
verbose printing of all files that are scanned.

Normally `uncrustify` and `black` are called with the `-q` option so
setting verbose suppresses the `-q` option and on `black` also enables the
`-v` option which makes it print out all file names matching the filter
similar to how `uncrustify` does by default.
@robert-hh1
Copy link

This change sneaked in as part of the most recent merges. So the PR can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.