• Use the Force (on stlinkv2's)

    08/27/2020 at 22:08 3 comments

    The cheap stlinkv2 usb dongles can be feisty.  Yeah, you can pick them up for $3 with free shipping from faraway if you are willing to wait for them to show up.  And that can really have some appeal to the underfunded programmer.

    After finishing the first minimum viable product version of the software for a neat embedded device, the programming apparatus immediately decided to take a long-lunch.  The stlinkv2's in it stopped playing nice.  I started by updating the firmware to the latest from ST, which did not work.  Fortunately, it did not entirely brick the programmers.  After flashing many versions of the official firmware from ST, I have found that the one mentioned here still works with stm8flash for the most part.  It's older, but that's what works for now.

    https://www.carminenoviello.com/2016/02/26/restore-st-link-interface-bad-update-2-26-15-firmware/

    This software that ST provides is a java app that other folks have written at-length about.  There seems to be a different zip file version of it for every version of the stlinkv2 firmware.  Is that really the easiest way to do it?

    The next problem was that it worked, repeatedly flashing onto the same device, but when I plugged in a new device to program, the usb programmers stopped responding.  I suspect because the firmware is so old.

    Workaround.  After trying a bunch of different ways to reset the usb device for each programmer before trying to use stm8flash, I found that this one worked pretty consistently.  The usbreset.c code compiled readily on both my main linux box and on the raspberry pi in my flashing apparatus.

    https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line/290519#290519

    resetting stlink devices
    Resetting USB device /dev/bus/usb/001/005
    Reset successful
    Resetting USB device /dev/bus/usb/001/006
    Reset successful

    It's not ideal, but it works.  Flashing devices resumes normally after the reset.

  • A little forth music...

    07/14/2020 at 01:05 0 comments

    This was too fun not to share.  Today I was chipping away at t problem that I've been at for a few days, and it finally came together.

    The start, was the need to have a way of assigning the channel for ADC on the STM8L in stm8ef.  This has been done by the stm8ef peripherals provided by eelkhorn.  And Thomas had a suggestion of which way to go with it.  Thanks to both of them.

    The original code:

    : setch ( ch -- )
        DUP 8 < IF
           1 ADC1_SQR4 ROT B!
        ELSE
           8 - DUP 8 < IF
               1 ADC1_SQR3 ROT B!
           ELSE
               8 - DUP 8 < IF
               1 ADC1_SQR2 ROT B!
               ELSE
                   8 - 1 ADC1_SQR1 ROT B!
               THEN
           THEN
        THEN
    ;
    

    The ch passed into setch in this case, is a raw numerical channel between 0 and 27.  The ADC1_SQRx registers store the bits (1 on, 0 off) for which ADC channels we're going to read.  This example is pretty easy to follow, and it took me only about a day to get it.  I still have trouble with forth's IF/THEN syntax, but I am getting better at it.

    Thomas suggested a totally different approach, which I got immediately.

    : setch ( ch -- )
      1 SWAP 8 /MOD SWAP ADC1_SQR1 + SWAP B!
    ;
    

    After recovering from my initial "mind-blown" moment in awe of how efficient it was, I groked it and tried it out.  If we figure that the raw number address 0 to 27 is encoded with the register number as an offset (0 to 3) and the bit within that register (0 to 7), it starts to work itself out and so I ran it.

    And I could not make it work.  And so I broke it down, and looked at it parts, with a real paper stack, a pen, and then I found it.

    ADC1_SQR1 = 0x534A
    ADC1_SQR2 = 0x534B
    ADC1_SQR3 = 0x534C
    ADC1_SQR4 = 0x534D
    

    The first thing is that the /MOD already outputs the remainder and quotient in the order we need so that SWAP is not needed.  I took it out.

        1 SWAP 8 /MOD ADC1_SQR1 + SWAP B!
    

    So I ran that, and it did not work.  And then I was really starting to wonder if I was gonna make this work or not.  Sometimes you have to make changes to your mind in the middle of making changes to a block of code.

    Second, the memory addresses are a little quirky, as the addresses increase as the x in ADC1_SQRx decreases.  Thanks ST.  So you need to do a little more to get it to work and reverse those.  So here's the final working function, with some explanations in the comments.  It only takes the single numeric channel (0 to 27) as an argument.  And I think you can use it to set vrefint and temp sensor as well (28 and 29).

      1 SWAP ( 1 n )
      8 /MOD ( 1 ch sqr_off )  \ /MOD returns rem quot, rem=chan quot=sqr_offset
      3 SWAP - ( reverse order )
      ADC1_SQR1 + ( 1 ch SQR# )
      SWAP ( 1 SQR# ch ) B!
    

     So there you have it.  Plan ahead when writing a forth routine.  Think about where you want to end up.  The 1 SWAP in the very beginning is there so you can use B! on the end, and have access to all that other stuff on the top of the stack in the interim.  

  • Forth on stm8 - Various Topics

    06/15/2020 at 00:12 0 comments

    Introduction

    I've been diving in to forth on and off for a while now.  It's a thing that takes over my whole brain, and I really welcome the distraction from time to time.  And it's for my work, so there's that.  I've been bouncing between writing code in C using SDCC, writing forth on linux, writing C in the Arduino IDE, and back to forth again.  It's all very enjoyably difficult context switching for me, and i'm good at context switching, or at least I once was.  So that's where this idea came from.  I thought, well, if it is difficult for me to context switch to forth after a few months of programming in C using SDCC on linux, then maybe it's difficult for others too.  Maybe someone will find this useful.

    My environment is linux.  The chip I started out with was the STM8S103F3, and if you're just trying to write some forth on a micro, this is awesome way to go.  The little $1 boards are great and cheap.  Check out the great write up on Breakout Boards from Thomas.  I used sduino bits added to the Arduino IDE to get started and really made my first go at the project I'm working on in under a week.  Then we needed to change it up and I could not get all that I needed from that, so I also started working with SDCC from the command line in the shell with a Makefile and built the patched STM8 SPL with SDCC and made some better results with control and speed there.  I also was bringing up my ability to use forth, with no small number of chat sessions, emails, forum reads and question posts, and a good old-fashioned mentoring from Thomas, who I owe a mountain of tasty beverages and a nice meal if I ever make it to Germany (or if he ever visits the US).

    Then we changed micros for the project, to get the 12bit ADC at the least, and for other reasons, and we went from STM8S103F3 to STM8L051.  The transition from STM8S to STM8L was a rough one, and I'm not sure I'd every wish upon anyone to have to make the context switch between them as often as I've had to do recently.  This cut away the sduino/IDE development entirely, as I did not yet think it was possible (for me a that time, mere months ago) to import the SPL STM8L into the Arduino IDE like in the fashion.  And, yet, now looking back, and with the ability to at least make an attempt at doing it successfully, I would probably not.  If I were going to do something major along those lines, I'd probably focus my energy on helping out the folks over at SDCC and The SDCC Wiki get more work done on their efforts.  I have received tons of good replies and comments and advice from them regarding SDCC, and it is well supported.

    Another current project uses yet another chip, the STM8S001J3, which is super cool because I don't have to solder tssop 20's and because it's just so cute.  It is tiny, itsy-bitsy, small, petite, and just plain not very big at all!  Yet, it packs some good functionality, and can be programmed using a few different methods.  Now let's go blink us some LED!

    So, without any further comment...

    An Example

    \res MCU: STM8S103
    \res export PA_ODR PA_DDR PA_CR1
    #require lib/]B!
    
    : init ( -- ) 
      [ 1 PA_DDR 3 ]B!
      [ 1 PA_CR1 3 ]B! 
    ;
    
    : OUT! ( f -- )
      PA_ODR 3 B!
    ;
    


    This was a really great moment for me.  I had already been able to do some basic forth programming, and really written quite a few actually productive, functional bits of code for the other two STM8 micros that I thought this would be fun to write about.  I got forth onto the chip and was able to connect immediately and start testing the parts of functionality that I knew I'd need.  For those who'd like to follow along with their own hardware, I'm using stm8ef running on the STM8S001J3, accessed via usb on linux, and using e4thcom to connect to a modified cheap CH341 serial dongle to program the chip mounted on a tsop-8 breakout board...

    Read more »