Hi I’m really new to Kotlin Native. I’m trying to ...
# kotlin-native
r
Hi I’m really new to Kotlin Native. I’m trying to develop with Kotlin Nativ for Raspberry Pi. I successfully added the pigpio library and can use it, but sometimes I have the problem, that the program exits with:
sigHandler: Unhandled signal 11, terminating
My code looks like this:
Copy code
package ch.lichtwellenreiter.omrr

import kotlinx.cinterop.staticCFunction
import pigpio.*

const val GPIO_BUTTON = 6
var lastChange: UInt = 0u

fun main() {
    initGPIO()
    setupButton()

    while (true) {}
}

private fun initGPIO() {
    if (gpioInitialise() < 0) {
        println("GPIO Error initialising")
        return
    }
}

private fun setupButton() {
    val buttonPort = GPIO_BUTTON.toUInt()
    initPortWithMode(buttonPort, PI_INPUT)

    gpioSetAlertFunc(buttonPort, flankChangeDetected)
}

private fun initPortWithMode(port: UInt, mode: Int) {
    if (gpioSetMode(port, mode.toUInt()) < 0) {
        println("Could not set mode for GPIO$port")
        return
    }
}

val flankChangeDetected = staticCFunction<Int, Int, UInt, Unit> { gpio, level, tick ->
    val ticker = tick
    val pin = gpio
    val lvl = level


    when (lvl) {
        0 -> {
            val time = ticker - lastChange
            lastChange = ticker
            println(tick)
            if ((time > 55u && time < 61u) || (time > 113u && time < 119u)) println(time)
            println("Button Pressed down, level 0")
        }
        1 -> {
            val time = ticker - lastChange
            lastChange = ticker
            println(tick)
            if ((time > 55u && time < 61u) || (time > 113u && time < 119u)) println(time)
            println("Button released, level 1")
        }
        2 -> println("Button GPIO timeout, no level change")
    }
}
The error occurs not every time, I could not identify the exact place in code where it happens, but I think it is the access to
lastChange
inside the when expression. Has anyone some experience with such errors? Is there a way to copy the value from a C Int or UInt?
g
Hello @Roger Kreienbühl. I think

this KotlinConf talk

can help you.
r
Hi @Glen Thanks for your response. This talk was the starting point for actually get Kotlin Native a try. Sadly ther is no use of the callback function
Copy code
val flankChangeDetected = staticCFunction<Int, Int, UInt, Unit> { gpio, level, tick ->
in the talk. Because signal 11 is a segment violation, I think the value of lastChange or tick causes the error. Sometimes I compile the program and run it without errors, but sometimes the exactly same program (no changes) a second time compiled causes this error.
g
Weird behavior. Could it be a compiler bug?🤔
r
I don’t know, this only happens if I want to access a value a second time as far as I can say
g
Please, @Roger Kreienbühl,why do you need
lastChange
as a global variable?
Why not make it local to the callback?
r
Because I have to calculate the time since the last change of the pin level
Copy code
val time = ticker - lastChange
g
You could make lastChange local to the main() function.
r
Hmm, but how to use it in
Copy code
flankChangeDetected
g
You could make flankChangeDetected a higher-order function, with two parameters, the first being lastChange, and the second being the callback.
r
Am I missing something?
flankChangeDetected
is called from C, how should this work?
g
You could write something like :
val flankChangeDetected : ((change: Int, callback: staticCFunction<Int, Int, UInt, Unit>) -> Unit) = //callbackFunction
.
And inside the callback function, you can call the change variable.
r
Sorry, I amalso quiet new to Kotlin. At the moment I don’t see how I can set this as callback with
Copy code
gpioSetAlertFunc(buttonPort, flankChangeDetected)
g
Please does it work when you compile and run?
r
I have no clue how I should insert this in the code? How can
flankChangeDetected
be registered as callback when I use it as higher-order function? The way you posted it, it looks like i can pass a callback function to
flankChangeDetected
, but
flankChangeDetected
is the callback function, which I need to use in
gpioSetAlertFunc(buttonPort, flankChangeDetected)
, or do I understand something wrong?
g
Yeah, its true. There is no way of doing that transformation.
r
With some println I figured out, that the error definitely has to be on the line
lastChange = ticker
g
OK.
n
Below is an example of doing a callback with Kotlin Native (based on the pigpio example - http://abyz.me.uk/rpi/pigpio/cif.html#gpioSetAlertFunc ):
Copy code
fun aFunction(gpio: Int, level: Int, tick: UInt) {
    // May need to call this function if the callback is called from 
    // a different thread other than the main thread, otherwise a segmentation fault "might" occur.
    initRuntimeIfNeeded()
    println("GPIO $gpio became $level at $tick")
}

// Use staticCFunction function to convert a top level Kotlin function to a static C function.
gpioSetAlertFunc(4, staticCFunction(::aFunction))
👍 1
r
I have tried to change this whit no luck, the problem is the same I also tried to print the global variable
lastChange
in the callback without any usage of
tick
,
level
or
gpio
and the error still occurs. It seems to me, that the access to the global variable
lastChange
inside the callback is the problem, access to
tick
,
level
or
gpio
works without any problems
g
Please, @Roger Kreienbühl, why do you need
lastChange
as a global variable? You could just create it inside the callback function.
r
No, thats not possible, because the value that I set in one callback, I need in the next callback to compare them
g
Another suggestion(not sure whether it will work) is to create functions that access and modify the global variable. Something like
fun setChange(newValue : UInt) { lastChange = newValue }
r
I can try in the evening. Another idea that I had was, that the acces is not allowed if the callback is on another thread, so I will also try AtomicInt
g
Yeah, that seems like a good idea...
r
Will give feedback when I have tried it
g
👍
r
Sorry for my late feedback I have found a solution now With this code it works:
Copy code
@SharedImmutable
val sharedData = SharedData()

class SharedData {
    var lastChange = AtomicInt(0)
}
👍 1
g
Nice...