[RFC] Peripherals as scoped singletons

Motivation
Today, in svd2rust and cortex-m APIs, peripherals are modeled as global singletons that require
some synchronization, e.g. a critical section like interrupt::free, to be modified.
The consequences of this choice is that (a) driver APIs are not ergonomic as one would expect, see
below:
use stm32f103xx::TIM6;

// Periodic timer
struct Timer<'a>(&'a TIM6);

impl<'a> Timer<'a> { .. }

fn main() {
    interrupt::free(|cs| {
        let tim6 = TIM6.borrow(cs);
        let timer = Timer(tim);
        timer.init(..);
        // ..
        timer.resume();
    });
}

interrupt!(TIM6, tim6);

fn tim6() {
    interrupt::free(|cs| {
        let tim6 = TIM6.borrow(cs);
        let timer = Timer(tim);
        timer.clear_update_flag();
        // ..
    });
}

Here the Timer abstraction has to be reconstructed in each execution context. One would prefer to
instantiate Timer as a static variable and then use that from each execution context. However,
that's not possible with this Timer struct because of the non-static lifetime of the inner field.
(It is possible to remove the inner field from Timer at the expense of having a critical section
per method call -- which has worse performance than the non-static lifetime approach).
Even worst is that (b) driver abstractions can be easily broken due to the global visibility
property of peripherals. This means that there's no way to e.g. make sure that TIM6 is only used
as a Timer in main and tim6. Nothing prevents you, or some other crate author, from silently
using TIM6 in other execution context -- TIM6 doesn't even have to appear as a function argument
because it's always in scope. This issue not only breaks abstractions; you can also have race
conditions on TIM6 -- yes, even with interrupt::free you can have race conditions and that's
totally memory safe per Rust definition -- if Timer is being used in other execution contexts
and you don't know about it.
So, what can we do to fix these issues? We can remove the root of all these problems: global
visibility.
This RFC is proposing to go from global singletons to scoped singletons. Instead of having
peripheral singletons with global visibility you'll have to explicitly import a peripheral
singleton into scope, into the current execution context. Because we are talking about singletons
here you can only import singleton P into scope (execution context) S once. IOW, if you imported P
into an execution context S then you can't import P into another scope S'.
This RFC not only addresses the problems (a) and (b) mentioned above; it also helps us tackle the
problem of compile time checked configuration -- more about that later on.
Detailed design
Zero sized proxies that represent a peripheral register block, as shown below, will be added to
cortex-m and svd2rust generated crates.
pub struct GPIOA { _marker: PhantomData<*const ()> }

// Peripherals are `Send` but *not* `Sync`
unsafe impl Send for GPIOA {}

impl Deref for GPIOA {
    type Target = gpioa::RegisterBlock;

    fn deref(&self) -> &gpio::RegisterBlock { /* .. */ }
}

These proxies will be impossible to directly instantiate. Instead there will be a guarded function
that returns all the proxies only once.
pub struct Peripherals {
    pub GPIOA: GPIOA,
    pub GPIOB: GPIOB,
    // ..
}

impl Peripherals {
    pub fn all() -> Option<Self> {
        interrupt::free(|_| unsafe {
            static mut USED = false;

            if USED {
                None
            } else {
                USED = true;
                Some(Peripherals { .. })
            }
        })
    }
}

The user will be able to access the proxies like this:
fn main() {
    let p = Peripherals::all().unwrap(); // first call: OK
    //let p = Peripherals::all().unwrap(); // a second call would panic!

    p.GPIOA.bsrr.write(|w| /* .. */);
    p.GPIOB.bsrr.write(|w| /* .. */);
}

Thus the proxies are singletons: there can only exist a single instance of each of them during the
whole lifetime of the program. The proxies are also scoped, in this case they are tied to main, so
they are not visible to other execution contexts, unless they are explicitly moved into another
execution context.
Zero cost
An unsafe, unguarded variant of Peripherals::all will also be provided:
static mut USED = false;

impl Peripherals {
    pub fn all() -> Option<Self> {
        interrupt::free(|_| unsafe { /* .. */ })
    }

    // NOTE for safety this function can only be called once and before `Peripherals::all` is called
    pub unsafe fn _all() -> Self {
        USED = true;
        Peripherals { .. }
    }
}

When only the unsafe variant is used the cost of having scoped singletons becomes zero:
fn main() {
    let p = unsafe { Peripherals::_all() };

    p.GPIOA.bssr.write(|w| /* .. */)
}

This program has the same cost as using a global, unsynchronized GPIOA register block (which is
what you see in C HALs).
Sidestepping the proxy
Each peripheral will provide a static method, ptr, that returns a raw pointer into the register
block:
impl GPIOA {
    pub fn ptr() -> *const gpioa::RegisterBlock {
        0x4001_0800 as *const _
    }
}

This is useful for implementing safe APIs that perform "unsynchronized" reads on registers that
have no side effect when read:
impl DWT {
    /// Reads the cycle counter
    // NOTE this is a static method and doesn't require an instance of `DWT`
    pub fn cyccnt() -> u32  {
        unsafe { (*DWT::ptr()).cyccnt.read() }
    }
}

// time something
let before = DWT::cyccnt();
// ..
let after = DWT::cyccnt();
let elapsed = after.wrapping_sub(before);

Enabling new APIs
Scoped singletons effectively give move semantics to peripherals. This enables richer, type safer
APIs than what can be expressed with the current peripheral API. Let's see some examples:
(you can find some initial experiments with these APIs in the singletons branch of the f3
repository)
Type state as a contract
Digital I/O pins can be configured as inputs, outputs or to some special functionality like serial,
SPI or I2C. In some cases you want to configure a pin to operate in a certain mode for the duration
of the whole program; that is you don't want the pin to be re-configured by mistake.
Type state is a good way to encode this property: a type is used to encode the state of an object.
To transition the object from a state to another it needs to be moved so that the previous state
can no longer be used.
Here's a tentative GPIO API that uses type state:
use blue_pill::GpioExt;

let p = Peripherals::all().unwrap();

// from `GpioExt`: `fn pins(self) -> gpioa::Pins`
// `Pins` is a struct that contains all the pins. Each pin is (also) a singleton (!).
let pins = p.GPIOA.pins();

// `fn as_output(self) -> Output<Self>`
// `as_output` configures a pin as an output pin
let pa0 = pins.PA0.as_output();

// `fn as_input(self) -> Input<Self>`
// `as_input` configures a pin as an input pin
let pa1 = pins.PA1.as_input();

// `Output::high(&mut self)`
// set PA0 high (to 3.3V)
pa0.high();

// `Input::is_high(&self) -> bool`
if pa1.is_high() {
    // ..
}

// this would cause a compile error because `PA0` is not in the `Input` state
// pa0.is_high();

// this would cause a compile error because `PA1` is not in the `Output` state
// pa1.high();

// this would cause a compile error because `GPIOA` was consumed by the `pins` call
// p.GPIOA.moder.modify(|_, w| /* configure PA0 as an input */)

Here the Input and Output newtypes are used to encode the type state. The most important part
here is that GPIOA is consumed to generate the individual pins and thus it can't no longer be
used to configure the pins -- which would break Input / Output contract of "this pin can only
be used as an input for the rest of the program".
Compile time pin allocation
On modern microcontrollers a single pin can be configured to have one of many functionalities
(Serial, PWM, I2C, etc.). This lets vendor pack more peripherals in a microcontroller without
increasing the number of pins.
A problem that arises from this flexibility is that one might wrongly configure two, or more,
peripherals to use the same pin. With move semantics you can construct an API that ensures that
this can't happen:
let p = Peripherals::all().unwrap();
let pins = p.GPIOA.pins();

// use PA9 and PA10 for the USART1 serial port

// NOTE consumes `pa9`
let tx = pa9.as_usart1_tx();

// NOTE consumes `pa10`
let rx = pa10.as_usart1_rx();

// `Serial::new` in turn consumes `tx` and `rx`
let serial = Serial::new(p.USART1, (tx, rx), 115_200.bps());

// this would error because `pa9` was consumed above
//let ch2 = pa9.as_tim1_ch2();
//let pwm = Pwm::new(p.TIM1, ch2, 10.khz());

Here we have high level abstractions like Serial consume the pins they are going to use. This way
once one such abstraction is created no other abstraction can't use any of the pins the first one is
using.
Non overlapping register access
The "split" technique used for GPIO pins can also be used to split a peripherals in "parts" that (a)
modify different registers and (b) modify non overlapping parts of a same register. This comes in
handy with peripherals like the DMA which usually interacts with several other peripherals.
Vendors usually design their DMA peripherals so that even if the settings related to different
channels are stored in a single register that register can be modified atomically using e.g. "clear
flag" bits (no RMW operation required to clear a flag). If the vendor doesn't provide such mechanism
bit banding can probably be used in its place, if the device has support for it.
RTFM protects peripherals at the register block level. Without move semantics, to clear "transfer
complete" interrupt flags from two interrupts handlers running at different priorities you would
need a lock in the lowest priority handler:
// priority = 2
fn dma1_channel1(r: DMA1_CHANNEL1::Resources) {
    r.DMA1.lock(|dma1| {
        // clear the transfer complete flag for this channel
        dma1.ifcr.write(|w| w.ctcif1().set_bit());
        // ..
    });
}

// priority = 3
fn dma1_channel2(r: DMA1_CHANNEL2::Resources) {
    let dma1 = r.DMA1;
    // clear the transfer complete flag for this channel
    dma1.ifcr.write(|w| w.ctcif2().set_bit())
    // ..
}

But with move semantics you can split the DMA in channels and assign exclusive access to each
channel to each interrupt handler:
fn init(p: init::Peripherals) -> init::LateResourceValues {
    let channels = p.DMA1.split();

    // ..

    init::LateResourceValues { CH1: channels.1, CH2: channels.2 }
}

// priority = 2
// resources = [CH1]
fn dma1_channel1(r: DMA1_CHANNEL1::Resources) {
    // clear the transfer complete flag for this channel
    r.CH1.clear_transfer_complete_flag();
}

// priority = 3
// resources = [CH2]
fn dma1_channel2(r: DMA1_CHANNEL2::Resources) {
    // clear the transfer complete flag for this channel
    r.CH2.clear_transfer_complete_flag();
}

Thus no locking is needed. Each channel will operate on a non-overlapping portion of the shared
IFCR register.
Configuration freezing
In some cases you want to configure the core and peripherals clocks to operate at certain
frequencies during initialization and then make sure that these frequencies are not changed later at
runtime.
Again, move semantics can help here by "discarding" the peripheral in charge of clock configuration
once the clock has been configured:
use blue_pill::RccExt;

let p = Peripherals::all().unwrap();

// .. use `p.RCC`, or a higher level API based on it, to configure the clocks ..

// from `RccExt`: `fn clocks(self) -> Clocks`
// `clocks` contains information about the operating frequency of the peripheral buses
let clocks = p.RCC.freeze();

// To compute USART1 internal prescalers and achieve the desired baud rate,
// information about the current clock configuration is required.
// `clocks` provides that information
let serial = Serial::new(p.USART1, (tx, rx), &clocks, 115_200.bps());

Here, once the clock is configured, its configuration gets frozen by consuming / discarding the
RCC peripheral. With this ... move the clock frequencies can no longer be changed. Freezing RCC
returns a Clocks struct that contains the frequency of every peripheral bus. This information is
required to properly configure the operating frequency of each peripheral so it's passed to
peripherals' init functions.
Drawbacks
Regression when not using RTFM
And you still want to use interrupts.
RTFM supports moving runtime initialized resources into tasks (interrupts) at zero, or very little,
cost but if you are not using RTFM then a static variable is required to share a peripheral
between e.g. main and an interrupt handler. Putting a peripheral singleton in a static variable
means making it globally visible which means you have global singletons again, and all their
disadvantages, but with worse performance (because an Option and a RefCell are needed, see
below) than what you get with today's API.
With this RFC:
// you want to share `GPIOA` between `main` and `exti0`
// but this makes it global so any other execution context can also use it
static GPIOA: Mutex<RefCell<Option<GPIOA>>> = Mutex::new(RefCell::new(None));

fn main() {
    // initialize `GPIOA`
    let p = Peripherals::all().unwrap();
    interrupt::free(move |cs| {
        *GPIOA.borrow(cs).borrow_mut() = Some(p.GPIOA);
    });

    loop {
        interrupt::free(|cs| {
            let gpioa = GPIOA.borrow(cs).borrow().as_ref().unwrap();

            // ..
        });

        // ..
    }
}

interrupt!(EXTI0, exti0);

fn exit0() {
    interrupt::free(|cs| {
        let gpioa = GPIOA.borrow(cs).borrow().as_ref().unwrap();

        // ..
    });
}

With today's API:
// you don't have the RefCell + Option overhead but you still have global visibility

fn main() {
    loop {
        interrupt::free(|cs| {
            let gpioa = GPIOA.borrow(cs);

            // ..
        });

        // ..
    }
}

interrupt!(EXTI0, exti0);

fn exit0() {
    interrupt::free(|cs| {
        let gpioa = GPIOA.borrow(cs);

        // ..
    });
}

Compare this to RTFM + this RFC:
app! {
    resources: {
         static GPIOA: GPIOA;
    },

    idle: {
        resources: [GPIOA],
    },

    tasks: {
        EXTI0: {
            path: exti0,
            resources: [GPIOA],
        },
    },
}

fn init(p: init::Peripherals) -> init::LateResourceValues {
    init::LateResourceValues {
        GPIOA: p.GPIOA,
    }
}

fn idle(t: &mut Threshold, r: idle::Resources) -> ! {
    loop {
        r.GPIOA.claim(threshold, |gpioa| {
            // do stuff with `r.GPIOA`
        });

        // ..
    }
}

fn exti0(r: EXTI0::Resources) {
     // do stuff with `r.GPIOA`
}

No Mutex, no RefCell, no Option and no global visibility. Plus only idle needs a lock to
access GPIOA. Without this RFC, even with RTFM, it's possible to access GPIOA from
an execution context that's not idle or exti0 due to this issue / bug / hole:
japaric/cortex-m-rtfm#13.
It breaks the world
Breaking changes in cortex-m, svd2rust and cortex-m-rtfm are required to implement this.
Unresolved questions

Should we have finer grained access to peripherals as in a GPIOA::take() that returns
Option<GPIOA> (in addition to Peripherals::all() -- one would invalidate the other)?

The unsafe variant, Peripherals::_all, needs a better name.

Implementation bits
Note that the implementation is a bit crude at this point. Expect bugs. Still, I'm posting now to
get feedback and to allow others to experiment.

The f3 repo contains a high level API, and examples that use it, based on this RFC.
japaric/cortex-m#65
japaric/svd2rust#158
japaric/cortex-m-rtfm#50

cc @pftbest @thejpster @therealprof @hannobraun @nagisa @kjetilkjeka

EDIT: I realized that it may not be obvious how the RFC solves problem (a) so here's an example:
Let's say that you want to use a serial port in idle and in some interrupt handler. You know that
idle only needs to use the transmitter half the serial port and the interrupt handler only needs
to use the receiver part.
app! {
    resources: {
        static TX: Tx;
        static RX: Rx;
    },

    idle: {
        resources: [TX],
    },

    tasks: {
        EXTI0: {
            path: exti0,
            resources: [RX],
        },
    },
}

fn init(p: init::Peripherals) -> init::LateResourceValues {
    // consumes `GPIOA`
    let pins = p.GPIOA.pins();

    // consumes `PA9`
    let pa9 = pins.PA9.as_usart1_tx();

    // consumes `PA10`
    let pa10 = pins.PA10.as_usart1_rx();

    // consumes `USART1`, `pa9` and `pa10`
    let serial: Serial = Serial::new(p.USART1, (pa9, pa10), 115_200.bps());

    // consumes `serial`
    let (tx, rx): (Tx, Rx) = serial.split();

    // initializes the resources `TX` and `RX`
    init::LateResourceValues {
        TX: tx,
        RX: rx,
    }
}

fn idle(_t: &mut Threshold, r: idle::Resources) -> ! {
    let tx: &mut Tx = r.TX;

    loop {
        // do stuff with `tx`
    }
}

fn exti0(_t: &mut Threshold, r: EXTI0::Resources) {
    let rx: &mut Rx = r.RX;

    // do stuff with `rx`
}

With all the moves in init you are sure that:

No task or crate (dependency) can reconfigure the pins through GPIOA, because it (GPIOA) was
created (cf. the init::Peripherals argument of init) and consumed in init.

No task or crate (dependency) can reconfigure or drive the pins PA9 and PA10, because both
pins were created and consumed in init.

No task or crate (dependency) can do serial I/O through USART1 because it (USART1) was created
and   consumed in init.

No task or crate (dependency) other than idle can do serial writes because only idle has
access to Tx.

No task or crate (dependency) other than exti0 can do serial reads because only exti0 has
access to Rx.

Without this RFC you can't have any of these guarantees because the svd2rust API lets you use
GPIOA, USART1 in any execution context so even a function foo with signature fn() (note:
no arguments) can reconfigure the pins or start a serial operation.

This is very nice! It fixes my main (and basically only) complaint about rtfm - the need to reconstruct peripherals in every task. Sadly, I haven't had any time to do more with rtfm, but I'll definitely check this out in more depth when I get the time.

To transition the object from a state to another it needs to be moved so that the previous state
can no longer be used.

@japaric How do I "move" a peripheral? For some applications it is very important to being able to switch GPIO pins from input to output and back on-the-fly.
I do like the idea of the peripheral proxy quite a bit but I'm absolutely not hot about this:

static GPIOA: Mutex<RefCell<Option>> = Mutex::new(RefCell::new(None));

It would be great if there was a simple way to get an abstracted static peripheral proxy object (same for other fixed memory blocks as scratch space, but that is a different topic) as an alternative to obtaining the singleton.

How do I "move" a peripheral?

You write a method that takes self, not &self or &mut self, and that would be a move. But
maybe that's not the answer you wanted?.

For some applications it is very important to being able to switch GPIO pins from input to output and back on-the-fly.

You can continue use type state in straight line code to transition from input mode to output mode.
You just need an API to go from input to unconfigured and from output to unconfigured (the f3 repo
already has this, I think nvm I didn't check in that):
fn foo(pa0: PA0) -> PA0 {
    // `as_input` has signature `fn(self) -> Input<Self>`
    let input: Input<PA0> = pa0.as_input();

    // do input stuff

    // `unwrap` has signature `fn(self) -> PA0`
    let pa0 = input.unwrap();

    // `as_output` has signature `fn(self) -> Output<Self>`
    let output: Output<PA0> = pa0.as_output();

    // do output stuff

    output.unwrap()
}

Alternatively you could create an Io abstraction that automatically shifts from one mode to the
other:
enum Mode {
    Input,
    Output,
}

struct Io<P> {
    pin: P,
    mode: Mode,
}

let io: Io<PA0> = pa0.as_io(Mode::Input);

if io.is_high() {
     // ..

     // automatically changes the mode to `Output`
     io.set_low();

     // ..
}

If your pin is stored in a static variable and you still want to use type state then you'll have
to do a bit of "Option dancing" to get things to work:
// `pa0` is stored in a `static` variable (resource) so it can *not* be moved out.
// At best you can get a `&mut` reference to the `static`.
fn bar(resource: &mut Option<PA>) {
    // start of the dance
    if let Some(pa0) = resource.take() {
        // the definition of `foo` is above
        let pa0 = foo(pa0);

        // end of the dance
        *resource = Some(pa0);
    } else {
        // unreachable because the `resource` is always in the `Some` variant
        // we still need to `Option` to temporarily move `PA0` out of the resource
    }
}

It would be great if there was a simple way to get ..

There is: you use RTFM.

I have appended an example of how this proposal solves problem (a) to the RFC text (see the issue description).
I forgot to cc the embed-rs people. They have been using move semantics / ownership since long ago so maybe they have feedback on this proposal. cc @oli-obk @phil-opp please see the issue description.

Do I understand correctly that each peripheral has a global flag to check
if it was created or not?
Is pa0 in your last example a zero sized type?
On 22 Nov 2017 09:35, "Jorge Aparicio"<EMAIL_ADDRESS>wrote:

I have appended an example of how this proposal solves problem (a) to the
RFC text (see the issue description).
I forgot to cc the embed-rs people. They have been using move semantics /
ownership since long ago so maybe they have feedback on this proposal. cc
@oli-obk https://github.com/oli-obk @phil-opp
https://github.com/phil-opp please see the issue description.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/japaric/svd2rust/issues/157#issuecomment-346256841,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABgB3FHOhC4vMBo4pn-LiBof_GnfXx4Hks5s48CjgaJpZM4QmGtI
.

Implementation wise, the differences between your proposal and our impl are:

No addresses returned by some function on the type, instead we generate a &'static mut SomeRegister from the address. &'static mut is equivalent to ownership semantics, because if you have a function taking a &'static mut, the original is borrowed indefinitely.

I think your method compiles down to less code though, should be trivial to convert our stuff to not use &self, but Self::ptr

When not using RTFM, we still don't need statics, we have an interrupt system that works similar to crossbeam. There's three ways to give data to an interrupt

You can borrow data in an interrupt (if it impls Sync)
Or you can move it into the interrupt, never to see it again (move || some_data.action())
Or you can move it into the interrupt and get it back when you unregister the interrupt

The interrupt system is initialized via the same ownership semantics that we use for all hardware

Some thoughts

The ptr method should probably be an associated constant or an #[inline(always)] const fn to guarantee that rustc will optimize it even in debug mode. This will be a very common operation that could seriously penalize debug mode
We've had issues with device drivers being locked into the board's config, even though technically the driver just wants to get a handle to some pins. Binding the type system more closely to the specific hardware will make this somewhat harder.

Do I understand correctly that each peripheral has a global flag to check if it was created or not?

No, there's a single global flag for whether you obtained the handle for the entire hardware. After that, you just zero-cost extract the hardware components that you want.

@pftbest

Do I understand correctly that each peripheral has a global flag to check if it was created or not?

Not in the main proposal. In the main proposal there's a single boolean that guards all the peripherals. I initially implemented this using a per peripheral boolean but didn't see much advantage in doing that so that became the alternative to the main proposal (it's under "unresolved questions" in the RFC text).
Also note that the boolean never gets cleared when the peripheral is dropped. The boolean is not some sort of lock.
(In the f3 implementation there's actually two booleans to guard the peripherals. One for core peripherals and one for device peripherals. It might be possible to just have one boolean but two booleans was easier to implement).

Is pa0 in your last example a zero sized type?

Yes.
@oli-obk
Thanks for the input.

I think your method compiles down to less code though

I think so too but haven't measured. In particular you are guaranteed that static FOO: GPIOA = .. will have a zero size memory representation since everything is a zero sized type. OTOH, with your approach USART{1,2,3} can all have the same type &'static mut USART whereas we would have to use traits to abstract over the different USART types.

When not using RTFM, we still don't need statics, we have an interrupt system that works similar to crossbeam.

I have yet to look at your interrupt system but I recall that you mentioned during rustfest that your approach doesn't support priority levels (all the interrupts had the same priority). Is that still the case?
I'm not 100% sure that reconfigurable interrupt handlers are compatible with RTFM (SRP); RTFM wants everything to be statically (compile time) defined.

The ptr method should probably be  ...

Our code is already very bloated in debug mode due to the svd2rust API so I don't think this would help much 😅.

We've had issues with device drivers being locked into the board's config

I don't think I fully understand what's the issue here. Could you point me to an example?

I'm 100% on board with this concept. I'm currently working on a HAL for LPC82x, and what I'm doing is very much in line with what you're suggesting here, with the caveat that I the user must promise not to access the peripheral directly. This RFC would be a huge improvement for me.
Thank you, @japaric, this is great work!
I have a question about this piece of code from the original issue:
pub struct GPIOA { _marker: PhantomData<*const ()> }

Why the PhantomData field? If the purpose of the field is prevent construction of the struct from outside the module, a simple () should suffice. What am I missing?

Here the Input and Output newtypes are used to encode the type state.

Have you considered using type parameters instead of newtypes to encode the type state? Something along those lines:
struct PA0<State> {
    _state: State,
}

impl<State> PA0<State> {
    fn as_output(self) -> PA0<Output> { ... }
}

impl PA0<Output> {
    fn set_high(&mut self) { ... }
}

I don't know if that's a better solution in this specific case, but in general, I see the following advantages over newtypes:

Methods that are available in every state are straight-forward to implement.
Scales well to multiple types of state. Implementing methods that are available for any combination of states is straight-forward.
You can use a default value for the type parameter to hide it, and make working with the API more convenient. This doesn't make much sense with pin input/output, but is nice if the type state encodes whether something is initialized or not (as depending on a type without qualification would always refer to the initialized version).

RTFM supports moving runtime initialized resources into tasks (interrupts) at zero, or very little,
cost but if you are not using RTFM then a static variable is required to share a peripheral
between e.g. main and an interrupt handler. Putting a peripheral singleton in a static variable
means making it globally visible which means you have global singletons again, and all their
disadvantages, but with worse performance (because an Option and a RefCell are needed, see
below) than what you get with today's API.

How does putting a peripheral in a static variable imply that the peripheral becomes globally visible? The static variable can live in a module and not be pub. Then you can use free or associated functions in that module to provide a limited API. You might not even need all that Mutex/RefCell business, if whatever your API does, doesn't happen to require it.

Breaking changes in cortex-m, svd2rust and cortex-m-rtfm are required to implement this.

I don't care. This is enough of an improvement to be worth the breaking changes.

Should we have finer grained access to peripherals as in a GPIOA::take() that returns
Option<GPIOA> (in addition to Peripherals::all() -- one would invalidate the other)?

I don't know the answer to this question, but at least I never had the need for this kind of fine-grained access.

The unsafe variant, Peripherals::_all, needs a better name.

Maybe all_unsafe? Or maybe Peripherals::take for the safe variant and force_take for the unsafe one?
I don't feel strongly about any of those, just throwing around some suggestions.

Note that the implementation is a bit crude at this point. Expect bugs. Still, I'm posting now to
get feedback and to allow others to experiment.

I haven't looked at any of the pull requests so far, and I'm busy enough right now that I might not get to it for the foreseeable futures. However, feel free to ping me if you need feedback on something. I'll gladly make time.

If the purpose of the field is prevent construction of the struct from outside the module, a simple () should suffice. What am I missing?

This clears all OIBITS like Send and Sync

I have yet to look at your interrupt system but I recall that you mentioned during rustfest that your approach doesn't support priority levels (all the interrupts had the same priority). Is that still the case?

Our mutexes don't support priority levels, so all critical sections block all interrupts. This can cause priority inversion. We just haven't gotten around to implementing Mutexes with priority level support into the interrupt system.

I don't think I fully understand what's the issue here. Could you point me to an example?

Take the simple example of a "Button driver" that's nothing more than a debouncer. We need to implement it to take a specific GPIO pin instead of just "something that we can read a bit from".

If the purpose of the field is prevent construction of the struct from outside the module, a simple () should suffice. What am I missing?

This clears all OIBITS like Send and Sync

Ah, makes sense. Thank you!

@hannobraun
Thanks for taking the time to comment.

Have you considered using type parameters instead ..

Short answer: no. But I'll explore that option at some point.
In general, you shouldn't take the examples in the RFC as "the right way to do it" but rather as a
"one way to do it" or "just to showcase that this is possible at all".
I'm using newtypes instead of the more standard Foo<State> because I originally thought of putting
the pin proxies and the pins() method in the device crate and that coherence might be a problem
(can't impl YourType<MyType>). But then I realized that since SVD files target device families
and that one size fits all is not appropriate for pins: for example, you want GPIOC to be split into
PC1{3,4,5} if the device has a few pins and into PC{0,...,15} if the device has many pins so you
need a different Pins struct per device.

How does putting a peripheral in a static variable imply that the peripheral becomes globally
visible? The static variable can live in a module and not be pub.

Right, it may not be global in the literal sense but it's still "global" to the module where it's
defined and any function can access the static without declaring that it will do so (i.e. the
static doesn't have to appear as an argument of the function). To me allowing this undeclared
dependency is as bad as global visibility.

You might not even need all that Mutex/RefCell business, if whatever your API does, doesn't happen
to require it.

If you are OK with using unsafe code / static mut then you can skip the Mutex / RefCell /
Option. But, with the current proposal, it's always the end user who has to "create" the singletons
so if you want to put a singleton in a static variable the end user would have to do it.
@oli-obk
Thanks for the pointers. I'll take a closer look at that example and the interrupt system you are
using during the week.

@japaric Thanks for the explanation, seems like all bases are covered.

@japaric

In general, you shouldn't take the examples in the RFC as "the right way to do it" but rather as a
"one way to do it" or "just to showcase that this is possible at all".

Thanks, I realize that. I just wanted to make sure you're aware of the possibility, but I guess that whole discussion was a bit off-topic from the beginning. I think we all agree that this RFC allows us to build better abstractions. The details of how those abstractions will look like exactly are probably not that relevant at this point.

How does putting a peripheral in a static variable imply that the peripheral becomes globally visible? The static variable can live in a module and not be pub.

Right, it may not be global in the literal sense but it's still "global" to the module where it's
defined and any function can access the static without declaring that it will do so (i.e. the
static doesn't have to appear as an argument of the function). To me allowing this undeclared
dependency is as bad as global visibility.

I think we agree that this situation is not ideal, but I strongly disagree that it is "just as bad as global visibility". It might be close to as bad, if it's a huge module. But if only 2-3 functions have access to that static? I think that's acceptable.

If you are OK with using unsafe code / static mut then you can skip the Mutex / RefCell /
Option. But, with the current proposal, it's always the end user who has to "create" the singletons
so if you want to put a singleton in a static variable the end user would have to do it.

Makes sense. In any case, I think the trade-off is worth it.

This looks like a really nice improvement. I vote for move fast and break things.

OK. There seems to consensus on this RFC so I'll land the pieces in all the repos in the coming days.
There are a few implementation details to iron out:

Decide on better names for Peripherals::{all,_all}. If anyone has a suggestion please comment on the svd2rust PR (the link to the PR is in this issue description).

Figure out whether we can have a single PERIPHERALS static boolean for both core peripherals and device peripherals. Right now the implementation uses two statics (which results in two peripheral sets so you end with p.core.ITM and p.device.TIM3 in application code) because that was easier to implement, but I think it should possible to only have a single static (and a single set of peripherals).

This requires a new minor release of cortex-m-rtfm. I'd like to land the "safe &'static mut references" feature and drop the static_ref::Static wrapper before making a new minor release. The first change supersedes the static_ref::Static abstraction (which I think is still memory unsafe) and it's required to have memory safe DMA transfer APIs. The original RFC for the &'static mut feature is japaric/cortex-m-rtfm#47 but I think it's safer to go with the implementation in japaric/cortex-m-rtfm#50. I'll write a new RFC to discuss the trade-offs.

Finally I have been sketching APIs for more peripherals in this branch (clock configuration, pwm, capture, DMA, etc.) of the blue-pill crate.

@japaric I've played around a bit with the singletons and it simplifies things quite a bit. I am a bit puzzled about the _all() function. You said it can only be called once but you seem to use debug_assert!() which means I can call it just fine multiple times since I'm using optimised builds only which seems a bit counter intuitive (code that works fine when optimised but breaks in debug mode). Is there a reason for that and wouldn't there be a better way to check this at compile-time rather than run-time?

This looks like a nice improvement that will be very helpful today and to what I expect the long term embedded rust will be like. In case my heart emoji didn't express my feelings strongly enough, I'm all for breaking all kinds of things to land this!
I've been totally swamped with work the last week and probably will be the next week as well. I will take some time looking at the details as soon as i can.

@japaric

Figure out whether we can have a single PERIPHERALS static boolean for both core peripherals and device peripherals. Right now the implementation uses two statics (which results in two peripheral sets so you end with p.core.ITM and p.device.TIM3 in application code) because that was easier to implement, but I think it should possible to only have a single static (and a single set of peripherals).

For what it's worth, I don't mind having two peripheral sets. Actually, I think it might be a bit nicer, as it makes it more obvious how platform-dependent a given piece of code is.
If I remember correctly, the flags might be optimized away anyway. If that's true, I don't really see a reason to try to unify them, if that makes things more complicated.

Finally I have been sketching APIs for more peripherals in this branch (clock configuration, pwm, capture, DMA, etc.) of the blue-pill crate.

FYI, I've been working on APIs for clock stuff to, in my LPC82x HAL (which I've published this morning). There are also the beginnings of a generic interface in there, which I plan to submit to embedded-hal once it has matured a little.

I am a bit puzzled about the _all() function. You said it can only be called once but you seem to use debug_assert!() which means I can call it just fine multiple times since I'm using optimised builds only which seems a bit counter intuitive (code that works fine when optimised but breaks in debug mode). Is there a reason for that and wouldn't there be a better way to check this at compile-time rather than run-time?

I haven't looked at the code yet, but I supect the point is to minimize overhead in release mode, while making mistakes obvious in debug mode. This has precedent in Rust itself, as integer overflow will cause a panic in debug mode and do nothing in release mode, for the same reason.
It would be great if there was a way to guarantee at compile-time that the method if only called once. However, I don't know how we could do that reliable. My guess is that it's currently not practical.

It would be great if there was a way to guarantee at compile-time that the method if only called once. However, I don't know how we could do that reliable. My guess is that it's currently not practical.

That's actually easy to do as a clippy lint. You strap a #[clippy(once)] attribute on a function, and clippy guarantees that all #[clippy(once)] functions are only ever called once. There will be false positives where we'll tell you we can't prove it's only called once. E.g. if someone makes a function pointer out of the function, we won't be able to prove that noone's duplicating the pointer. So essentially #[clippy(once)] requires that the function is never turned into a function pointer and any function calling the function is also #[clippy(once)].
Open an issue on the clippy repo if you consider this solution practical

@hannobraun

I haven't looked at the code yet, but I supect the point is to minimize overhead in release mode, while making mistakes obvious in debug mode. This has precedent in Rust itself, as integer overflow will cause a panic in debug mode and do nothing in release mode, for the same reason.

Well, with embedded projects debug code might not always fit in the flash so sometimes it's simply practical to use it. I never use debug code so I'm not too happy about catching this "problem" only in debug versions. Also if this is called so often that it would become a performance problem, you're very much doing it wrong anyway since this is only supposed to be called once so it shouldn't be a problem, no? ;)

@oli-obk

That's actually easy to do as a clippy lint. You strap a #[clippy(once)] attribute on a function, and clippy guarantees that all #[clippy(once)] functions are only ever called once. There will be false positives where we'll tell you we can't prove it's only called once. E.g. if someone makes a function pointer out of the function, we won't be able to prove that noone's duplicating the pointer. So essentially #[clippy(once)] requires that the function is never turned into a function pointer and any function calling the function is also #[clippy(once)].

This is very cool, I like it. The only problem I see in this particular case is that code generated by svd2rust is very clippy unfriendly and requires a lot of adjusting and/or test gating to be usable at all. :(

The only problem I see in this particular case is that code generated by svd2rust is very clippy unfriendly and requires a lot of adjusting and/or test gating to be usable at all. :(

You won't be using it on svd2rust, you'd use it on your crate, and clippy would have to transitively prove the correctness of #[clippy(once)] stuff.
Also you can just turn off all lints except for the once lint ;)

@oli-obk My own crate contains clippy unfriendly svd2rust generated code. I know I can do some stuff selectively in clippy, but I haven't figured out how to get rid of the specific warnings in the svd2rust code via configuration. Clippy is an incredible tool which I'm using extensively for any projects but the MCU stuff...

@oli-obk

That's actually easy to do as a clippy lint.

I didn't know this. This is awesome. Thanks!

Open an issue on the clippy repo if you consider this solution practical

I presume this is missing "don't"? Otherwise it's confusing :-)
@therealprof

Well, with embedded projects debug code might not always fit in the flash so sometimes it's simply practical to use it. I never use debug code so I'm not too happy about catching this "problem" only in debug versions.

You're right, but you don't have to do a full-blown debug build to get debug assertions. You can enable them separately. See Cargo documentation.

Also if this is called so often that it would become a performance problem, you're very much doing it wrong anyway since this is only supposed to be called once so it shouldn't be a problem, no? ;)

I don't think performance is the issue, but code size could be. Granted, a single assert! likely won't make a difference, but if we as a community decide that assert!s in release code are okay, this will quickly add up to the point where using Rust on very small microcontrollers will become very hard.

I presume this is missing "don't"? Otherwise it's confusing :-)

No. We don't have this lint. Open an issue if you want this lint implemented.

@hannobraun I'm in general no big fan of panic! in MCU code but since this door was already opened and work is under way to improve it, we might as well use it for assert!s, too. I'd still prefer to have a compile time check and/or a lint for this.

@oli-obk Oh, I just remembered why I said I earlier, that I believe static checking might not be practical: The dependency graph could contain multiple versions of the same crate. Do you know how that affects the Clippy lint?
This might not be a big issue in pracice though. (And now that I think about it, unless the statics are #[no_mangle], which they might be, I don't know, a debug_assert! won't catch that case either. At least I don't think.)

@oli-obk

No. We don't have this lint. Open an issue if you want this lint implemented.

Oh, good thing I asked then. I've added it to my task list, so I can look into it later.

The dependency graph could contain multiple versions of the same crate. Do you know how that affects the Clippy lint?

I believe multiple crates defining the same peripherals would result in the design laid out in this RFC to provide the guarantees it claims to provide. i.e. One would be able to run Peripherals::all() from one version of crate and Peripherals::all() from the other, essentially ending up in you having two sets of peripherals.
I feel like it would be desirable to make it impossible to link multiple versions of the crate defining peripherals in case this is implemented. (A simple way to do so would be to define a global symbol with a well-known name)

@nagisa

I feel like it would be desirable to make it impossible to link multiple versions of the crate defining peripherals in case this is implemented.

Yes, this what brought up in the pre-RFC (#151). The proposed solution was to add a #[no_mangle] to the static to make different minor versions of a device crate un-link-able. I had forgotten about it :-); I'll roll it later.
You can still break singletons if some implements an alternative singleton system for peripherals that uses different names for the static variables.
@therealprof
_all is unsafe. It doesn't matter if it has the debug_assert! or not -- that assert doesn't make the function safe. It's common, or I think it is, to check the preconditions of unsafe functions in dev mode to try to catch bugs.
@oli-obk
Can clippy trace the call graph then? Can it handle independent call graphs (an interrupt handler is the root of an independent call graph)? Could it get all these:
// defined in some other crate
fn call_me_once() { /* .. */ }

fn main() {
    call_me_once(); // assume this is the only intended call

    call_me_once(); // easy to catch

    foo(); // less (?) easy to catch
}

// could be defined in some other crate
fn foo() {
    call_me_once();
}

// could be defined in some other crate
// dead code
fn bar() {
    call_me_once();  // false positive
}

// could be defined in some other crate
// interrupt handler
#[no_mangle]
pub fn EXTI0() {
    call_me_once(); // hard to catch?
}

Could it get all these:

all the other functions would be required to also have #[clippy(once)], it's contageous.
For the interrupt handler, I'd just assume #[no_mangle] functions would also be forbidden to contain calls to #[clippy(once)] functions. We'll err on the safe side and forbid all calls that we can't trivially prove.

@japaric

_all is unsafe. It doesn't matter if it has the debug_assert! or not -- that assert doesn't make the function safe. It's common, or I think it is, to check the preconditions of unsafe functions in dev mode to try to catch bugs.

That sounds rather weird to me: Either this tries to catch abuse or it doesn't, just doing this under certain circumstances sounds like a recipe for disaster.
As I said, I'm not at all a fan of panic!ing MCU code at all and I do think that keeping this as an unguarded unsafe function is perfectly fine.

@japaric one alternative would be to use linkonce_odr linkage, but not sure how supported between linkers it is.

@oli-obk

all the other functions would be required to also have #[clippy(once)], it's contageous.

I see. You get a warning if a clippy(once) function is called from a function not marked as clippy(once). I think that might be enough for RTFM.
@therealprof
If you, as an end user, want to construct Peripherals you should use the safe, guarded alls constructor. The unsafe, unguarded _alls constructor is not meant to be used by an end user but to cosntruct safe abstractions (e.g. rtfm::init) that the end user can then use.

@japaric That is fully understood.
It is still insane if you develop code with release type builds (like I always do for MCUs for a number of reasons, e.g. because I like looking (and comparing) at the (dis-)assembly) and call _all() more than once and then someone else uses the code by accident (because it's the default build type) or on purpose with a debug build and all of a sudden it goes boom...
If it is enforced it should be always and properly enforced so there's no possible way to miss it. However to me it looks like just documenting why it is unsafe and removing the debug_assert! would be a better way to go.

All the pieces required to implement this RFC have landed in the master branches of cortex-m, cortex-m-rtfm and svd2rust. :tada:
However, there are quite a few things to do before releasing a new minor version of those crates (e.g. updating the documentation). I have created a milestone for each repo to track the things to do. If you think anything else should be done before the next minor version release now's your chance: open an issue or leave a comment on an existing issue requesting adding it to the milestone.

This requires a new minor release of cortex-m-rtfm. I'd like to land the "safe &'static mut references" feature and drop the static_ref::Static wrapper before making a new minor release.

BTW, the RFC for that change is in japaric/cortex-m-rtfm#59 if you have any thoughts / comments about it.
I have run out of embedded Rust time for this week; I'll be back (late) next week.
Thanks again everyone for your input.


Incorrect CSS variable usages in the BitLink component

Short summary (3-5 sentences) describing the issue.
Reproduce steps
The simplest set of steps to reproduce the issue. If possible, reference a commit that demonstrates the issue.
Expected result
What would happen if there wasn't a bug.
Actual result
What is actually happening.
Additional detail
Optional, details of the root cause if known. Delete this section if you have no additional details to add.

not valid anymore


New command: m365 pp dataflow get

Usage
m365 pp dataflow get
Description
Gets information about the specified data flow
Options

Option
Description

-i, --id <id>
The id of the dataflow to retrieve details for.

-e, --environmentName <environmentName>
The name of the environment where the dataflows are located.

--asAdmin
Run the command as admin and retrieve dataflows for environments you do not have explicitly assigned permissions to.

Examples
Retrieve dataflow in the given Power Platform environment.
m365 pp dataflow get --id d87a7535-dd31-4437-bfe1-95340acd55c5  --environmentName Default-d87a7535-dd31-4437-bfe1-95340acd55c5

Default properties
N/a
Additional Info
Checkout: https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/reference/msdyn_dataflow?view=dataverse-latest
In this case the API call would be ${dynamicsApiUrl}/api/data/v9.2/msdyn_dataflows(dataflowid)

LGTM 👍
Lets open it up 🚢🚀


Add tests for rgb/data

This is a part of a series of PR to add testing for Revealed and Confidential raw byte data structures. The PRs are broken into parts for easier review.
This PR contains only the encoding/decoding tests. The testing framework might be refactored later when other tests are added. Garbage data is tested for EnumValueNotKnown error.

Added commit_encode and conceal testing on Revealed structures. The test logic is in test_confidential function. For ease of review, one-liners are provided. Please let me know if I am missing any major test cases.


Select2Mixin hashedSelector fix, with test

There's already been action on this error: PR #158, issue #154. In this PR, though, I added a test that failed with the "undefined hashedSelector" javascript error, and now it passes with the fix (from issue #154).
Note: I'm not completely sure this won't break other Widgets, but at least we have a test for Select2Widget while we fix the others if needed.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 12b00c108408a98bfe4b9a214d4c94592e1f2b54 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

And the obligatory "Thanks @coveralls for notifying us".... 13 times.

@bcail looks really promising, just take a quick look over my comments.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

Coverage increased (+0.72%) to 57.14% when pulling 537c8ec40be684a38ec374dd064a9fa65f4572f0 on bcail:master into 42b73198b726e2e9278a0889a608ea7c31811d61 on applegrew:master.

updated

I'll look into it


Windows server 2019?

What do i need to make it work for this distro? It's kind a like win 10 ent? I May be wrong, but i like your opinion on it 😄

What do i need to make it work for this distro? It's kind a like win 10 ent? I May be wrong, but i like your opinion on it 😄

Server OS'es don't really come with a lot of bloat.
What are your main goals?

Also this is not a place for discussions and questions. Please see https://github.com/simeononsecurity/Windows-Optimize-Harden-Debloat/discussions


Support connection_timeout below 1 second

Is there a way to configure the client to have connection_timeout that is below 1 second?
For example something like:
uri = "amqp://guest:guest@localhost"
amqp_client_options = { connection_timeout: 0.5 }
AMQP::Client.new(uri, **amqp_client_options).connect

If not supported, do you have it on the roadmap, and if yes, when could we expect it?

Have you tried 500.milliseconds?
On Fri, 15 Dec 2023, 12:49 Йордан Пулов, @.***> wrote:

Is there a way to configure the client to have connection_timeout that is
below 1 second?
For example something like:
uri = @.***"amqp_client_options = { connection_timeout: 0.5 }AMQP::Client.new(uri, **amqp_client_options).connect
If not supported, do you have it on the roadmap, and if yes, when could we
expect it?
—
Reply to this email directly, view it on GitHub
https://github.com/cloudamqp/amqp-client.rb/issues/23, or unsubscribe
https://github.com/notifications/unsubscribe-auth/AABL6TWN7Z5EKXKW7472JSLYJQ2MPAVCNFSM6AAAAABAWKPEISVHI2DSMVQWIX3LMV43ASLTON2WKOZSGA2DGNJYHA3TMMI
.
You are receiving this because you are subscribed to this thread.Message
ID: @.***>

@carlhoerberg do you refer to the in_milliseconds method as the one suggested by you is not implemented?
3.0.5 :146 > 500.milliseconds
(irb):146:in `<main>': undefined method `milliseconds' for 500:Integer (NoMethodError)
Did you mean?  in_milliseconds

Also, I do believe that since it parses the time to int
3.0.5 :145 > 1.in_milliseconds
 => 1000

and the lib is described to accept integers, it's not acting as expected and it's setting the timeout to be 1000 seconds.
So to get back on the question, is the connection_timeout: 0.5 valid approach, or is there any other valid approach to define timeout below 1 second?

Oh, sorry, thought the issue was on amqp-client.cr haha. Will look into why a float isn't accepted in this lib.

Probably just replace .to_i with .to_f here: https://github.com/cloudamqp/amqp-client.rb/blob/main/lib/amqp/client/connection.rb#L409

And note that it's connect_timeout. not connection_timeout


make it possible to do bulk changes to tags meta data

For example, changing the deadband to the same value for 1000 different tags is not really an option. It must be possible to make bulk changes, for example by first selecting all tags to be changed, enter the new value and click 'commit' ... or something.

A function with file- export and import for bulk changes would be nice.


[SDL 0140] Android Manifest Metadata

Proposal: Android Manifest Metadata

The current Android library relies on a lot of internal methods and functions that try and prevent developers from making changes to their apps. However, as Android becomes more and more strict on what system level methods are available the SDL library will need to move to more conventional methods to accomplish certain goals. One of the ways to achieve this is requiring developers to add metadata fields to the SdlBroadcastReceiver. This will allow the library to query all SDL enabled apps and retrieve attributes about them without having to perform any inter-app communication.

Review: https://github.com/smartdevicelink/sdl_evolution/issues/395
Steering Committee Decision:

It was noted in the Steering Committee that an app partner would only have to include the first line (router_service_version) in their manifest to implement this change at a minimum. The other lines are for corner case integrations.  It was also clarified that the package “com.livio” was used in the proposal as an example declaration and would be specific to each app partner’s integration. Finally, it was confirmed that this information would be included in the Android Guide once implemented.  The Steering Committee then voted to accept this proposal.

Fixed with #686


Command Failed on Windows with wait: true

Related to https://github.com/mikaelbr/node-notifier/issues/33
I am running node-notifier inside nw.js v0.12.3 on Windows 10.
The notification pops without a problem and you can even start multiple notifications but it seems that after the first notification times out, the app will crash.
This only happens when wait: true. Keeping it as as false, doesn't cause any crashes and doesn't seem to limit any functionality.
index.js:28 Caught exception: Error: Command failed: C:\Users\MLM\AppData\Local\Temp\nw17184_28\node_modules\node-notifier\vendor\toaster\toast.exe -sound false -p file://C:\Users\MLM\AppData\Local\Temp\s-11617-11904-ohnmpb -m a -t EricTroupeTester @ MadLittleMods/asdf1234 -q true -w true
    index.js:28 (anonymous function)
    events.js:80
    emitOneevents.js:150
    emitnode.js:256
    process._fatalException

index.js:29 Error: Command failed: C:\Users\MLM\AppData\Local\Temp\nw17184_28\node_modules\node-notifier\vendor\toaster\toast.exe -sound false -p file://C:\Users\MLM\AppData\Local\Temp\s-11617-11904-ohnmpb -m a -t EricTroupeTester @ MadLittleMods/asdf1234 -q true -w true

    at ChildProcess.exithandler (child_process.js:716)
    at emitTwo (events.js:85)
    at ChildProcess.emit (events.js:153)
    at maybeClose (child_process.js:984)
    at Process.ChildProcess._handle.onexit (child_process.js:1057)index.js:29 (anonymous function)events.js:80 emitOneevents.js:150 emitnode.js:256 process._fatalException

You can see the source code here:
https://github.com/gitterHQ/desktop/pull/100/files#diff-d74e5f0a212623b40b7c84b3d6313d78R49

Thanks for your issue! I'll look into it

Here is a slightly better stacktrace that has some references into the node-notifer code:
Error
	cmd: "C:\Users\MLM\AppData\Local\Temp\nw13016_25400\node_modules\node-notifier\vendor\toaster\toast.exe -sound false -p C:\Users\MLM\AppData\Local\Temp\gitter-notification-avatars_\116123-10160-e4vl6c -m afwe -t MadLittleMods @ MadLittleMods/asdf1234 -q true -w true"
	code: 3
	killed: false
	message: "Command failed: C:\Users\MLM\AppData\Local\Temp\nw13016_25400\node_modules\node-notifier\vendor\toaster\toast.exe -sound false -p C:\Users\MLM\AppData\Local\Temp\gitter-notification-avatars_\116123-10160-e4vl6c -m afwe -t MadLittleMods @ MadLittleMods/asdf1234 -q true -w true↵"
	signal: null

Error: Command failed: C:\Users\MLM\AppData\Local\Temp\nw13016_25400\node_modules\node-notifier\vendor\toaster\toast.exe -sound false -p C:\Users\MLM\AppData\Local\Temp\gitter-notification-avatars_\116123-10160-e4vl6c -m afwe -t MadLittleMods @ MadLittleMods/asdf1234 -q true -w true

    at ChildProcess.exithandler (child_process.js:716:12)
    at emitTwo (events.js:85:13)
    at ChildProcess.emit (events.js:153:7)
    at maybeClose (child_process.js:984:16)
    at Process.ChildProcess._handle.onexit (child_process.js:1057:5)C:\Users\MLM\AppData\Local\Temp\nw13016_25400\utils\notifier.js:138 (anonymous function)C:\Users\MLM\AppData\Local\Temp\nw13016_25400\node_modules\node-notifier\lib\utils.js:165 (anonymous function)C:\Users\MLM\AppData\Local\Temp\nw13016_25400\node_modules\node-notifier\lib\utils.js:53 (anonymous function)child_process.js:723 exithandlerevents.js:85 emitTwoevents.js:153 emitchild_process.js:984 maybeClosechild_process.js:1057 ChildProcess._handle.onexit

On Windows 10, I'm trying to create a notification that doesn't disappear until it is closed.
with wait: true it closes and there is an error in the console.
Error: Command failed: node_modules\node-notifier\vendor\toaster\toast.exe -m Hello -t Node Notification: -q true -w true(…) "Timeout

@mikaelbr I can confirm this. Is there any workaround to make sticky notifications until this is fixed? I'd like to help but sadly it seems like the error arises from toast.exe.

I'm somewhat getting around this by checking if error.code == 3 && error.killed == false && error.toString().indexOf('Command failed') > -1 and then firing another notification or executing some user-was-too-slow-action. Would love to see a fix anyway.

Same issue here with Windows 10 trying to use the wait: true option. I have a similar stack trace.
Error: Command failed: C:\src\ElectronExample4\node_modules\node-notifier\vendor\toaster\toast.exe -p C:\src\ElectronExample4\image\favicon.png -m Notification Message -t Notification Title -w true(…) "Error: Command failed: C:\src\ElectronExample4\node_modules\node-notifier\vendor\toaster\toast.exe -p C:\src\ElectronExample4\image\favicon.png -m Notification Message -t Notification Title -w true

    at ChildProcess.exithandler (child_process.js:214:12)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:852:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)"

I am also failing to get 'sticky' toasts on Windows 10 and 7
Is https://github.com/nels-o/toaster/issues/2 relevant to this?
7 returns null error
10 same as @djpereira

I'm still having this issue when using gulp-notify, which is using node-notifier 4.6.1. I'm on Windows 10, node 6.9.1, and npm 3.10.8. Usage is like this:
var eventMessage = 'File ' + event.path + ' was ' + event.type + ', running tasks...';
        return gulp.src('').pipe(plug.notify({
            onLast: true,
            message: eventMessage
        }));

Error is:
Message:
    Command failed: C:\Users\sam_julien\Source\Repos\PT-UI\PT_UI\node_modules\gulp-notify\node_modules\node-notifier\vendor\toaster\toast.exe -onLast true -p C:\Users\sam_julien\Source\Repos\PT-UI\PT_UI\node_modules\gulp-notify\assets\gulp.png -m File C:\Users\sam_julien\Source\Repos\PT-UI\PT_UI\code\app\contractors\contractor-service.js was changed, running tasks... -t Gulp notification -q true
Unhandled Exception: System.IO.DirectoryNotFoundException: The system cannot find the path specified. (Exception from HRESULT: 0x80070003)
   at ShellHelpers.IPersistFile.Save(String pszFileName, Boolean fRemember)
   at toast.Program.InstallShortcut(String shortcutPath)
   at toast.Program.TryCreateShortcut()
   at toast.Program.Main(String[] args)

Removing the onLast and only passing in the message didn't change anything. Any ideas?

How does this work now in master branch when switching toaster. Could someone please test out by doing:
npm i mikaelbr/node-notifier

Closing this as we've switched toaster implementation.


Simplify Class and Object JNI wrappers

In this PR:
#1101
The Class and Object helpers in JavaWrappers were updated to restrict external access to the m_class and m_object internal members. The goal is to ensure when setting the member variables to a new jobject it using a global JNI ref (through calling env->NewGlobalRef). Doing so protects external classes and child classes from instantiating local JNI references that may become stale before the lifetime of the wrapper object. It does not however protect the Class and Object wrappers from misusing the jobject references.
Instead of making Class and Object aware of the need to create a global JNI reference a new templated class should be created to store the jobject reference and ensure we're creating global references. The Class and Object wrappers could then use that new container for their jclass and jobject member variables and remove the duplicated responsibility of maintaining global references.
Alternatively it might warrant looking into using the fbjni wrapper library instead of the custom JavaWrappers implementation.

@ryantrem says there is a team that used fbjni successfully with JSI, so maybe we should use that also some day.

Closing for now. Reopen if we want to fix this.


Add custom backend type

Fixes #547
This allows the usage such as:
import os
import requests
import json
import openai

openai.api_base = "https://my-custom-api-url"
openai.api_type = 'custom'

response = openai.ChatCompletion.create(
    engine="custom",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},
    ],
    headers={
        "X-My-Custom-Authentication-Header": "some_value"
    },
    backend_url='/request_path_where_the_openai_model/responds' # appended to openai.api_base
)

print(response)
print(response['choices'][0]['message']['content'])

No need for this pull request anymore, as the feature was fixed in #547


Fixing checkstyle error in Unit Tests.

e2e Tests failing due to Checkstyle errors in merged PR. (https://github.com/data-integrations/google-cloud/pull/1218)

@CuriousVini Can you please have a look at the unit test failures. (https://github.com/data-integrations/google-cloud/actions/runs/4382608971/jobs/7671851760)

Issue fixed.


Function won't get recognized in x86 decompile

Hello.
I was trying to play around with the program, and it does is work really well.
I downloaded the tool from the repository, and also the DATA from the ghidra-data repository, compiled them, I have the *.fidbf into the folder and everything else got without any problem.
Now, to the actual problem, I'm getting serious problem to make it recognize some "basic" functions of a x86 executable.
Following an example of the code decompiled, into the entry function:

The highlighted function with the cursor right now, is the WinMain function, but it seems it can't recognize it, like it can't also recognize functions like the _getcwd or _getdcwd. But, if I goes to put it manually the corrent function name, and reapply the datatype from the Data Type Manager, it will update also all the variables into the parameters to the correct one.
Is me that I'm asking for too much, or I'm doing something wrong?
If some info is amiss please tell me that I will add more info as possible.
Thanks.

It is currently asking too much of Ghidra to recognize main or WinMain, as it's not the true entry point of the binary, and there is nothing in the file format that points to it.
_getcwd should potentially be recognizable by the FID...can you post your binary?

For WinMain, I said it as an example, for the fact that, given that he knows the parameters type, and all are declared correclty, I thought that he could recognise it without any problem.
I don't know if I can post it, it is an executable from a licensed videogame (an old one).

Functions like memset are recognized because their function body bytes are recognized by the FID.  Since WinMain is a user-defined function with unknown function bytes, the FID will not be able to match it.  Yes, WinMain has a known function signature, but the FID matches on function body bytes, not signature.  So while Ghidra has a data type for WinMain, it doesn't know how to find it because it doesn't know anything about the bytes contains within the function.

Ok, I now understand for that type of functions how it works. Let's say that is just more something needed to be understand manually how to find where it start (that, is not a large a problem, that is a minor issue).
For the binary, I will add the link as follow: https://easyupload.io/la42gq, if it won't work out, we can just remove it out.
For the function _getcwd, it has been called back at 0x00402cac.

I found out it was a _getcwd because I did some compare with IDA, and saw over there what was going to callback this function, else honestly I didn't had so much an idea what it was eheh.
I'm just learning how to enter into all of this, I tried differently things for a day, at least I preferred to write here to understand a little more how it works.
Thanks again for your replies!

If you want to explore the FID, you can enable the plugin the the CodeBrowser:

File -> Configure...
Check Function ID
Click Close
Tools -> Function ID -> Table Viewer -> vsOlder_x86.fidbf
Tables -> Strings Table

Unfortunately this table doesn't use Ghidra's filterable tables, but you can select all the rows (ctrl + a), right click, and export the table to a CSV file.
When I did this, i see an entry for _getcwd, so I'm not sure why it's not getting labeled in Ghidra.  I'm going to consider this a bug that requires investigation on our part.

I've already enabled the plugin, I will give a look over this table how u just said to me, I thank u very much.
If can help for the bug, there are more functions that won't get recognised, but I think that are all connected one under the other, like the _splitpath or _makepath, or also the toupper and the _chdrive and _chdir, u can find them all at function at the address 0x00403150.
Thanks again for your reply! Really appreciated!


abnormal susceptibility to aneurysm induced morbidity/mortality

Consider adding:
abnormal susceptibility to aneurysm induced morbidity/mortality
DEF: differences from the expected moribund state caused by aneurysm rupture following experimental induction of heart or vessel wall weakening by chemical and/or physical means
decreased susceptibility to aneurysm induced morbidity/mortality
DEF: reduced likelihood that an organism will display the expected moribund state caused by aneurysm rupture following experimental induction of heart or vessel wall weakening by chemical and/or physical means
increased susceptibility to aneurysm induced morbidity/mortality
DEF: increased likelihood that an organism will display the expected moribund state caused by aneurysm rupture following experimental induction of heart or vessel wall weakening by chemical and/or physical means

Added:
abnormal susceptibility to aneurysm induced morbidity/mortality MP:0031279
decreased susceptibility to aneurysm induced morbidity/mortality MP:0031280
increased susceptibility to aneurysm induced morbidity/mortality MP:0031281


Flathub Titles Take 2

This is a second attempt at resolving #272.
Why?
When adding Flathub software, the only thing that shows is the app icon. It's not clear what any of the software is unless you are familiar with its icon. Additionally, you can not search the list.
By adding titles to the listings, the options are more descriptive, and you can use Find in Page in the browser to find what you are looking for.
What's different now?
There were 2 reasons the original change was reverted:

Listings were showing in a single column
Long titles were disturbing alignment

These have both been resolved via:

This was an artifact of cached CSS. After doing a full reload via Shift + refresh, the new CSS was fully loading and everything is aligned correctly.
Titles have been truncated to not wrap or overflow. This has no effect on being able to search in page, as the truncation was done with CSS, so the full title is still searchable.

Screenshot

This change will affect all custom stores (GOG, EPIC and Flathub). can you please check how it looks on those?

I don't have any GOG games, so nothing is listed, but I checked the Epic store, and it looks fine. I also confirmed that it uses the same views, so there's no reason why the game store listings should render any different than flat hub listings.
So I think this should be good to go 👍

Looks good. One request. Could you add more margin between the bottom of the text and the next row? That would make it much clearer as to what the text is attached to.

I pulled the title up a little to be more coupled with the card image, and gave some more padding below.

Awesome, thank you!

🎉


RuntimeErrors are assumed to be maximum recursion depth exceeded

It seems to be a result of https://github.com/Cal-CS-61A-Staff/ok-client/blob/6f61f1e0d326fc31b872ec0ad5856131360074f8/client/sources/common/doctest_case.py#L225.

It seems to be because of https://github.com/Cal-CS-61A-Staff/ok-client/blob/6f61f1e0d326fc31b872ec0ad5856131360074f8/client/sources/common/doctest_case.py#L225.

I hardcoded that in there under the assumption the most common RuntimeError would be maximum recursion depth. Just wondering, what other runtime error did you see?

The error, "Your final strategy should not call max_scoring_rolls" is
raised as a RuntimeError.
On Wed, Feb 4, 2015 at 10:44 PM, albert12132<EMAIL_ADDRESS>wrote:

I hardcoded that in there under the assumption the most common
RuntimeError would be maximum recursion depth. Just wondering, what other
runtime error did you see?
—
Reply to this email directly or view it on GitHub
https://github.com/Cal-CS-61A-Staff/ok-client/issues/47#issuecomment-73001925
.


ipodtouch0218: Watch clovervibesdubai.com

ipodtouch0218 requests the watch of the watch_keyword clovervibesdubai\.com. See the MS search here and the Stack Exchange search in text, in URLs, and in code.

clovervibesdubai\.com has been seen in 1 true positive, 0 false positives, and 0 NAAs.

Rejected by Spevacus in Charcoal HQ. Reason: 'Duplicate, whoopsies'


Support 'run_on_start' config option

I'd like to be able to avoid running Consistency Fail when Guard starts up. It takes time, and is not important to me until I change the model/schema files. A configuration option for this would be useful. It would still be possible to hit ↵ to manually run everything.
The RuboCop Guard Plugin supports this through all_on_start: false - see implementation.
The RSpec Guard Plugin also supports all_on_start: false (false is actually the default) - see implementation.
It should be quite quick to duplicate this functionality for this plugin. Perhaps the option run_on_start is a better name, because "all" doesn't really make sense for consistency_fail, however.
The (optional) config would become:
guard :consistency_fail, run_on_start: false do
  watch(%r{^app/model/(.+)\.rb})
  watch(%r{^db/schema.rb})
end

Does this sound useful? If so, I can put together a PR.

Sounds good @olliebennett Please send a PR


Prepare public or restricted deployment on github

Cleanup code, including comments
maybe some refactoring is required (remove custom tables except generic classes)
cleanup build, deploy atrifacts to mavencentral?
maybe create subprojects for ddutils and APIs jars...

Done.


[derive] Clean up AsBytes support on repr(packed)

Unify our handling of repr(packed) and repr(transparent) when deriving AsBytes, and bring error messages up to date with the fact that we support both of these reprs on generic structs.
Closes #127

@djkoloski can you take a look at this when you get a chance?


Added support for 'form-horizontal' and 'form-inline' in BS3 renderer

Well, I do not like this modification for latte macros, they should stay as ligthweight as it's possible. Renderer may be modified to support other these styles but the "style" should be defined and not detected.


Improve ILI9xxx display support for SPI to MCU interfaces

In rare types of displays, discrete shift registers can be found to convert the SPI data stream to the ILI9xxx 16-bit MCU interface. Examples for that would be the "Pico ResTouch LCD 3.5" shield or "Pico Eval Board" by Waveshare.
This PR extends the current driver stack with this new optional feature.

@rexut Thanks. There are efforts to move this driver to the "MIPI DBI driver class", see #64587, IIRC there are also plans to support 16 bit interfaces. Perhaps @danieldegrasse can comment on this.

This is an interesting display- from what I can tell, it looks like the shift registers are being used to convert the SPI frames to 16 bit parallel RGB data? It looks like the final output format would be something like an 8080 interface, is that right?
I do think this kind of feature could be abstracted by the MIPI DBI API. Could you look at #64587 and see if you think a custom MIPI DBI driver would accomplish what you need here? It seems like the restriction this enforces is that all writes need to be 16 bits, whether the data sent is a command or display data

This is an interesting display- from what I can tell, it looks like the shift registers are being used to convert the SPI frames to 16 bit parallel RGB data? It looks like the final output format would be something like an 8080 interface, is that right?

Exactly. The ILI9xxx of the assembled LCD panel is hard-coded to talk via the 8080 interface. Waveshare has built a discrete shift register in front of it to access the LCD panel. This makes it an ordinary SPI device again for the outside world. BUT! any access to commands or data in the display RAM must be 16-bit wide.

I do think this kind of feature could be abstracted by the MIPI DBI API. Could you look at #64587 and see if you think a custom MIPI DBI driver would accomplish what you need here? It seems like the restriction this enforces is that all writes need to be 16 bits, whether the data sent is a command or display data

@danieldegrasse: I can try that. But I need to find some more free time for that. However, as I understand it, the MIPI DBI API is a "new" alternative for this type of displays in Zephyr and is still a work in progress. I will definitely have a look at that. Thanks for the hint.
@jfischer-no: Nevertheless, this PR now "only" extends the existing driver. This has already been main line, available and immediately usable for a long time. I could therefore imagine that this tweak will first be integrated into the existing systems via this PR and then the new MIPI DBI API will also be equipped with this feature.

Exactly. The ILI9xxx of the assembled LCD panel is hard-coded to talk via the 8080 interface. Waveshare has built a discrete shift register in front of it to access the LCD panel. This makes it an ordinary SPI device again for the outside world. BUT! any access to commands or data in the display RAM must be 16-bit wide.

I love the ingenuity

@danieldegrasse: I can try that. But I need to find some more free time for that. However, as I understand it, the MIPI DBI API is a "new" alternative for this type of displays in Zephyr and is still a work in progress. I will definitely have a look at that. Thanks for the hint.

It is still a work in progress, but I think the implementation is relatively complete. I'm not opposed to adding support the way you are here, I just think that both approaches solve the same problem. The hope with the MIPI DBI API is that it can be more generic. I appreciate that this is a very one-off restriction though, and not really something that many displays would need. Are you aware of other displays with this kind of restriction?

Exactly. The ILI9xxx of the assembled LCD panel is hard-coded to talk via the 8080 interface. Waveshare has built a discrete shift register in front of it to access the LCD panel. This makes it an ordinary SPI device again for the outside world. BUT! any access to commands or data in the display RAM must be 16-bit wide.

I love the ingenuity

@danieldegrasse: I can try that. But I need to find some more free time for that. However, as I understand it, the MIPI DBI API is a "new" alternative for this type of displays in Zephyr and is still a work in progress. I will definitely have a look at that. Thanks for the hint.

It is still a work in progress, but I think the implementation is relatively complete. I'm not opposed to adding support the way you are here, I just think that both approaches solve the same problem. The hope with the MIPI DBI API is that it can be more generic. I appreciate that this is a very one-off restriction though, and not really something that many displays would need. Are you aware of other displays with this kind of restriction?

No, I don't know any further displays with such kind of special interconnection – I think, it's more a quirks to reuse cheap panels from stock than a intended system architecture.
However, the last few weeks I was busy with a Zephyr Meetup preparation and wasn't able to answer. Now I'm back to business and found some time to port this really special solution to the new MIPI DBI driver class for SPI.
What should I say – thank you for this new abstraction layer. From the original hack on ILI9xxx driver to this new MIPI DBI class extension I found a really better solution to integrate the correct byte stuffing – now without a preallocated 16-bit word data buffer. Before this was possible, because all ILI9xxx chips can only receive 32 byte at once. Now, with the more abstract MIPI DBI API, such kind of restriction have to avoid and the new Type C4 operating mode (SPI 4-wire 16-bit) as completely independent of amount of data to processed.
Please, have a look on the new code and tell me your opinion of improvements or better code. Thanks.

Thanks for the work here. I'm slightly concerned about adding too many MIPI DBI modes to the header, since there are strictly only 3 modes defined by the spec. Could we instead add a devicetree prop to the MIPI DBI SPI driver that allows the user to specify a minimum write size? From my understanding, that is the only restriction this setup introduces versus a standard SPI interface.

Thanks for the work here. I'm slightly concerned about adding too many MIPI DBI modes to the header, since there are strictly only 3 modes defined by the spec. Could we instead add a devicetree prop to the MIPI DBI SPI driver that allows the user to specify a minimum write size? From my understanding, that is the only restriction this setup introduces versus a standard SPI interface.

Hm, good idea. I had something similar in mind at first, but then I didn't want to tinker too much with the MIPI DBI SPI driver. But if that's your way of thinking too, then let's do it that way. Give me a few more days (maybe weeks). I'll have to find some time between the daily tasks.

Now I'm back from the "embedded world" in Nuremberg and can use the next few weeks for a revision. Can someone remove the "stall" label?

The last change set has now been revised.
The former introduction of the new, non-standardized operating mode has been removed. Instead, there are now two new constant values for the minimum required transmission of bits via the SPI bus. This value can optionally be set to either 8 or 16 via the DTS as the "xfr-min-bits" property, with 8 being the default setting if nothing is defined in the DTS (default behaviour in mode MIPI_DBI_MODE_SPI_4WIRE). Like the operating modes, both constants are accessible via the header "dt-bindings/mipi_dbi/mipi_dbi.h" and can therefore be used via the new symbols MIPI_DBI_SPI_XFR_8BIT (default) or MIPI_DBI_SPI_XFR_16BIT in a DTS file.
Both new constants are interpreted in the functional part of the MIPI DBI SPI driver exclusively for the SPI 4 wire operating mode (type C3). The behavior of type C1 remains unchanged. The combination of MIPI_DBI_MODE_SPI_4WIRE and MIPI_DBI_SPI_XFR_8BIT (default setting) still corresponds exactly to the current behavior.
@danieldegrasse : let me know, if I'm completely wrong with the selected dt-binding file for the new "xfr-min-bits" property in "dts/bindings/mipi-dbi/zephyr,mipi-dbi-spi.yaml". For my own, this looks correct. The new property will describe the hardware interconnection similar to the correct wiring of reset and command/data selection GPIO and also if it would be possible to read back any data from the SPI device.

@jfischer-no: as a collaborator of the display drivers (sadly no maintainer is listed) I would ask you for a +1 on review. As you mentioned, the display driver is now completely untouched. All the bitstream magic is done at MIPI DBI SPI level, one level above all display drivers. So theoretically it would be possible to support every display in the same way.

@Dino-Li, I'm going to change myself to the assignee on this PR, as it modifies code in the MIPI DBI subsystem (which I maintain). If you feel this is incorrect, please go ahead and change the assignee back to yourself.

@jfischer-no @Dino-Li @danieldegrasse : What are the next steps in the review/merge process? Is there anything else I need to do so that the PR will be accepted?

@Dino-Li or @jfischer-no could you please provide a review on this PR so we can move this forwards?

@ioannis-karachalios requested your review on this since you have to the MIPI DBI drivers, feel free to remove your request

Just a note- as the feature freeze is now active, this PR will have to go in after 3.7 release. Adding the correct milestone to reflect that

@danieldegrasse please revisit

@danieldegrasse I still have the outstanding improvements on the table, but won't get to them again until the fall. If the GH bot sets the issue to stall again, please mark it as active again - I'm on it.

Hi @danieldegrasse. Thanks for reverting the "stale" flag for me once again. Yes, I'm still on here. Unfortunately, porting our downstream project Bridle to Zephyr v4 has been slowing me down massively since Vienna. I can only work on it in my limited spare time and a lot has happened in tooling, testing and documentation. But I think that the Christmas season will give me a little more flexibility. Thank you for your patience.

@jfischer-no could you take a look?


Add all the W3C, WHATWG specifications

Those specifications are not present, do we want to add all of them?

They should be.

Updated the list to include some more of the specifications.


SERVER_PORT variable removed?

Is there an existing issue for this?

[X] I have searched the existing issues

Question
Coming back to the game after a bit, was re-aligning my config and noticed the SERVER_PORT was removed?
Found this commit but no notes why the removal took place
https://github.com/mornedhels/enshrouded-server/pull/56/commits/3a7df26d1e6e2098e992be00a51c764c912b0d59
I was wondering why?

Hey @faandg,
well there is no official note on the changelogs, but on their docs for the server they mentioned the removal of that port.
https://enshrouded.zendesk.com/hc/en-us/articles/19191581489309-Server-Roles-Configuration#h_01HZ29QC64ANFG7N4X39XRZ1MK
The environment variable is ignored and you only need to open the queryport in your firewall and docker config.

@cp-fabian-pittroff alright, thanks for the clarification!


SetString(2^64-1) is wrong

         const expected = "18446744073709551615"
         r, _ := new(Big).SetString(expected)
         if r.String() != expected {
                 t.Fatalf("expected %s, got %s", expected, r.String())
         }

output
expected<PHONE_NUMBER>3709551615, got 0.0000000000000000000

That's embarrassing, sorry.

Similar issue
        expected := "18446744073709551615"
        a, _ := new(Big).SetString("18446744073709551614")
        b, _ := new(Big).SetString("1")
        z := new(Big).Add(a, b)
        if z.String() != expected {
                t.Fatalf("expected %s, got %s", expected, z.String())
        }

output
expected<PHONE_NUMBER>3709551615, got 0E+4

Thanks. I went through and found one more. I'm curious: how did you stumble upon this?

I was writing tests for my own code using special values and unexpectedly found it

If you can/want to, could you send me the tests? I always like adding more.


Latest version (1.2.0) doesn't have any published code.

When downloading the actual archive from registry.npmjs.com, it only contains the following files:

.editorconfig
LICENSE
package.json
README.md

File link: node-curseforge-1.2.0.tgz
This is most likely caused due to the fact that the publishing workflow doesn't have a build step, it only runs npm ci and publishes.

I'll never understand Github actions.

Newest Action does build now and publish properly, I am not happy about the way it does it but it does and that's all that matters.


kartta map page does not work in Safari browser

fixed by https://github.com/kartta-labs/kartta/pull/22
tested in Chrome/Firefox/Safari on Mac OS X, and Chrome/Firefox on Linux

Also tested in Edge on Mac OS X.
If anyone can test in Edge on Windows, please create a new issue if it doesn't work; if it does work, just leave a note here saying so.


[Feature Request] Host resource usage

Now We had info about Host node resource, maybe add resource usage let us more understanding about the resource usage of the server host/node will help us conducive to better planning and use of our resources.
Some example like this:

Duplicate of https://github.com/portainer/portainer/issues/611


perf: adds (some) arm64 assembly for 4 and 6 words modulus

Description
This PR refactors the code generation in field/ to allow some space for the various scenarios (generating only amd64, amd64 and arm64, none), depending on modulus size.
It adds element.Mul and element.Butterfly in arm64 assembly.
Context is to make the library and its direct users more cost efficient on arm machines.
How has this been benchmarked?
cherry picked, running on c8g.16xlarge;
bls12-377/fr
ElementMul-64                       25.6ns ± 0%  23.5ns ± 0%   -8.31%
ElementButterfly-64                 9.79ns ± 0%  5.32ns ± 0%  -45.69%

bls12-377/fp
ElementMul-64                       52.8ns ± 0%  44.8ns ± 0%  -15.10%
ElementButterfly-64                 12.4ns ± 0%   6.6ns ± 0%  -46.72%

bls12-377/fr/fft
FFT/fft_2**18bits-64                                    2.93ms ± 0%  2.03ms ± 0%  -30.83%  (p=0.029 n=4+4)
FFT/fft_2**18bits_(coset)-64                            3.31ms ± 0%  2.39ms ± 0%  -27.83%  (p=0.029 n=4+4)

bls12-377/fr/sis
15-20% improvements

bls12-377/
10-15% improvements on most ecc point operations

bw6-761/fp
BenchmarkElementMul-16     250           182           -27.18%

This is fantastic! Thanks


vbuild -c build works but vbuild -c --dev failed

vbuild -c build works but vbuild -c --dev failed
ERROR in ./src/index.js
Module not found: Error: Can't resolve 'vue-style-loader!css-loader' in 'C:\Projects\Baseline\client'
 @ ./src/index.js 7:0-50
 @ multi ./~/vbuild/lib/dev-client.es6 src/index.js

ERROR in ./src/index.js
Module not found: Error: Can't resolve 'vue-style-loader!css-loader' in 'C:\Projects\Baseline\client'
 @ ./src/index.js 8:0-41
 @ multi ./~/vbuild/lib/dev-client.es6 src/index.js

 ERROR  Compiling failed!

Content of vbuild.config.js:
const path = require('path')

module.exports = (options, req) => {
    const webpack = req('webpack')

    return {
        entry: 'src/index.js',
        html: {
            title: 'test-project',
            template: './src/index.html'
        },
        webpack: {
            resolve: {
                modules: [path.resolve('src')]
            },
            plugins: [
                new webpack.ProvidePlugin({
                    jQuery: "jquery",
                    $: "jquery",
                    "window.jQuery": "jquery",
                    "window.$": "jquery"
                })
            ]
        },
        vendor: ['jquery', 'lodash', 'materialize-css', 'materialize-css/dist/css/materialize.css', 'mdi/css/materialdesignicons.css', 'animate.css', 'sweetalert', 'sweetalert/dist/sweetalert.css', 'moment', 'vue', 'vue-router', 'vuex', 'vuex-router-sync', 'vee-validate']
    }
}

What's the vbuild version? Any other changes to your app code or how to reproduce this.

Seems it's caused by importing .css file, fixed in v6.10.2, webpack 2 doesn't support combining loaders with !

P.S. the vendor option is unnecessary now, everything you require will be split.

Noticed that vbuild 6.x no longer split out vendor css like vbuild 5.x. Is this a bug? This is the case with or without vendor option in vbuild.config.js

It's fixed in master


[FS-BQ-Export] Insufficient info from UNAUTHENTICATED failure

Describe your configuration

Extension name: firestore-bigquery-export (storage-resize-images, firestore-send-email, etc)
Extension version: 0.1.12

Describe the problem
Running fs-bq-import-collection leads me to an error message with insufficient information to know what to do next.
Steps to reproduce:
I ran the following command and the answers to the interact questions:
? What is your Firebase project ID? **<MY_PROJECT_NAME>**
? What is the path of the the Cloud Firestore Collection you would like to import from? (This may, or may not, be the same Collection for which you plan to
mirror changes.) **<MY_COLLECTION_NAME>**
? Would you like to import documents via a Collection Group query? **No**
? What is the ID of the BigQuery dataset that you would like to use? (A dataset will be created if it doesn't already exist) **<MY_DATASET_NAME>**
? What is the identifying prefix of the BigQuery table that you would like to import to? (A table will be created if one doesn't already exist) **<MY_PREFIX_NAME>**
? How many documents should the import stream into BigQuery at once? **300**
? Where would you like the BigQuery dataset to be located? **us**
? Would you like to run the import across multiple threads? **No**

Expected result
Command is successful; data loads to BigQuery without errors/issues.
Actual result
I get the following error message:
Importing data from Cloud Firestore Collection: <MY_COLLECTION_NAME>, to BigQuery Dataset: <MY_DATASET_NAME>, Table: <MY_PREFIX_NAME>_raw_changelog
Error importing Collection to BigQuery: Error: 16 UNAUTHENTICATED: Failed to retrieve auth metadata with error: invalid_grant

and I have no idea what I need to look into w.r.t. auth metadata to become authenticated.  My user account is the only one that has created these projects (Firebase and BigQuery) and I've done all of the configuration via command line (firebase, gcloud, bq, etc...)

Ends up being a need to run gcloud auth application-default login as documented in the GENERATE SCHEMA VIEWS documentation.
It is not clear to me that this step/requirement is easy to identify in the documentation?  Also, might the error message be a bit more specific?


enable fuzzy matching for $state.is

For example it would be quite nice to be able to do
if (!$state.is("foo.*")) {
}

instead of
if (!$state.is("foo.tap") && !$state.is("foo.bar" )) {
}

I would be more than willing to PR this in, wanted to get your thoughts before I implemented.

doesn't work when:
state: base (abstract)
state: base.auth (abstract)
state: base.auth.login (common state)
$state.is('base.auth.*') => undefined
$state.is('base.auth') => false
$state.is('base') => false
$state.is('base.*') => undefined
$state.is('') => undefined
;(