Toggling an LED on a Kinetis K70 board

by Crossware 23. March 2016 12:32

Toggling a pin is one of the first things to do on a new microcontroller board.

Our board has an LED on port B pin 18 and the C code for toggling that pin is shown below.

The program is built to run in the SRAM of the K70 microcontroller avoiding the need to over-write anything in the on-chip flash memory.

main()
{
    // disable the watchdog timer
    g_pWDOG->UNLOCK = 0XC520;
    g_pWDOG->UNLOCK = 0XD928;
    g_pWDOG->STCTRLH &= ~WDOG_WDOGEN;
    // enable the PORTB module
    g_pSIM->SCGC5 |= SCGC5_PORTB;
    // set PTB18 to ALT1 (GPIO)
    g_pPORTB->PCR18 &= ~(PORT_MUX0 | PORT_MUX1 | PORT_MUX2);
    g_pPORTB->PCR18 |= 1 << 8;
    // set PTB18 as an output
    g_pGPIOB->PDDR = 1 << 18;
    while (1)
    {
        // toggle the PTB18
        g_pGPIOB->PTOR = 1 << 18;
        for (int i = 0; i < 100000; i++);
    }
}

 

Tags: , ,

Blog

Simulating SPI Memory with Javascript - Part 1

by Crossware 4. March 2015 12:05

A program may store persistent data in on-chip flash and in a previous blog I showed you how to initialized the simulating on-chip flash from Javascript.

Programs that also or instead store data in SPI memory may want to simulate this off-chip memory too.  So in the next few blogs I will show you how to simulate SPI memory with Javascript.

My example program is using bit-bashing to control the SPI memory and it is writing the BSRR register of port B to do this (STM32Fxxx chip).  So my first step it to create an event handler which will be called whenever my simulating program writes to g_pGPIOB->BSRR. I can get the Embedded Development Studio to create the appropriate Javascript code for me.  To do this, I right mouse click on my Javascript source file and from the context menu that opens select jState Code Creation Wizards->GPIOB.

 

 

When I click on GPIOB, the code creation wizards opens:

This allows me to see all of the events and properties available for jState.gpiob.

I am interested in the first item and when I select it I see the source code (with comments) that the wizard will generate for me.  I click on Insert and this Javascript code it is placed into my Javascript file.

var writeGpiobBSRR = function(event) {
    // the Bit Set-Reset Register (BSRR) is being written
    // event.data contains the value being written to it
    // jState.gpiob.m_nODR has not yet been updated
    // add your javascript code here:
}
jState.gpiob.addEventListener("writeBSRR", writeGpiobBSRR, false);

This gives me both an event handler and the code that will register that event handler.

Now, whenever my simulating program writes to the BSRR register of port B, my event handler will be called.

You might want to put something like console.log("Event handler called\n") into this event handler for test purposes.

I am going to create a Javascript Object to encapsulate my SPI Memory simulation code:

var SPIMemory = function() {
}

var spiMemory = new SPIMemory();

 and into this object I can put a suitable function such as handlePortPin that I can call from the event handler:

var SPIMemory = function() {
    this.handlePortPin = function(portb, bsrr) {
    }
};

This function has two parameters. portb will contain the value of ODR (output data register) and the other is the value being written to BSRR.

Here is the modified event hander containing a call to this function:

var writeGpiobBSRR = function(event) {
    // the Bit Set-Reset Register (BSRR) is being written
    // event.data contains the value being written to it
    // jState.gpiob.m_nODR has not yet been updated
    // add your javascript code here:
    var nODR = jState.gpiob.ODR;
    spiMemory.handlePortPin(nODR, event.data);
}

With these two arguments I can determine the value of the output data register both before and after the write to BSRR. I do this in function updatePort below.  Then I will know the levels of each port B pin and whether or not they are rising or falling.

var SPIMemory = function() {
    this.updatePort = function(port, bsrr) {
        // portb has not yet been updated by the BSRR value
        // return the value that portb will become
        var newport = port;
        newport |= bsrr & 0XFFFF;
        newport &= ~(bsrr >> 16) & 0XFFFF;
        return newport;
    }
    this.handlePortPin = function(portb, bsrr) {
    }
};

In the next post I will add some code to send the chip Id to the simulating program in response to the 0X9F (ReadId) command.

Tags: , , , ,

Accessing on-chip memory from Javascript

by Crossware 27. February 2015 09:59

Today we updated the jState support within our Cortex-M3 and Cortex-M4 extensions to allow access to on-chip memory from Javascript.

The jState code creation wizard for the on-chip memory (accessible by right clicking on the Javascript file) will tell you what functions are available.

The image below shows code that it has created for us to set the on-chip memory read and write addresses to 0XE0000 and the increment on both read and write to 2.  (To increase the read or write address by 2 after each read or write.)

 

 

Clicking on Insert inserts this code into our Javascript file:

jState.onchipmemory.readaddress = 0X000E0000;
jState.onchipmemory.writeaddress = 0X000E0000;
jState.onchipmemory.readincrement = 2;
jState.onchipmemory.writeincrement = 2;


Our intension is to write a table of values into the on-chip flash memory sector at 0XE0000 - our simulating firmware is expecting this table to be in place at startup. So with a bit of manual editing we have the following Javascipt code:

console.clear();

PopulateTable()


function PopulateTable() {
    var TableData = [
        33, 38, 39, 44, 53, 55, 64, 69, 70, 75,
        156, 161, 162, 167, 176, 178, 187, 192, 193, 198,
        283, 288, 289, 294, 303, 305, 314, 319, 320, 325,
        411, 416, 417, 422, 431, 433, 442, 447, 448, 453,
        546, 551, 552, 557, 566, 568, 577, 582, 583, 589,
        661, 666, 667, 672, 681, 683, 692, 697, 698, 703]
    jState.onchipmemory.readaddress = 0X000E0000;
    jState.onchipmemory.writeaddress = 0X000E0000;
    jState.onchipmemory.readincrement = 2;
    jState.onchipmemory.writeincrement = 2;
    for (var i = 0; i < 60; i++) {
        jState.onchipmemory.value16 = TableData[i];
    }
    console.log("TableData written to flash:");
    for (var i = 0; i < 60; i++) {
        if ((i % 10) == 0) {
            console.log("\n");
        }
        console.log(jState.onchipmemory.value16 + ",");
    }
}

When step into the simulator we can see that the data has been written into the correct memory locations:

 

By the way, to create the initial Javascript file select File->New and in the Files tab select Javascript Source File.  The Embedded Development Studio will populate the file name field for you so just click OK.

Tags: , , , , ,

Development Suite for ARM Enhancements

by Crossware 20. February 2015 09:32

The GUI parts of our Development Suite for ARM have been rebuilt using Microsoft's Visual Studio 2013.  That's over 80 DLLs as well as the Embedded Development Studio executable itself and so it was not an insignificant task.

For the embedded developer, this brings two major benefits:

1. The simulator can be graphically extended using Microsoft's latest Visual Studio 2013, including the free Community edition

2. The Cortex-M3 and Cortex-M4 simulations can also be extended using state-of-the art Javascript (see jState)

Unforunately it does mean leaving behind operating systems prior to Windows XP - the minimum requirement for these latest editions of the Development Suite for ARM is Windows XP SP3.

Tags: , , , , , , ,

More on Soft Switches of the ADSP-CM408F EZ-KIT Lite Board

by Crossware 27. August 2014 10:07

Continuing with my theme of yesterday where I wrote to the U40 MSP23017 soft switch chip to enable SW4 and SW5, I will show you how to read the register values from this U40 chip.

I've created two subroutines - WriteRegisterValue() and ReadRegisterValue() to make the main function clearer.

You will see below that I am writing to register 0X15 which is the output latch OLATB register whereas yesterday I wrote to register 0X13 GPIOB. But if you read back the value of register 0X13 after you have written to it, you do not see the value that you have written.  Instead you have to read OLATB to see this value.  The MSP23017 data sheet explains that a write to GPIOB is actually a write to OLATB and a read of GPIOB reads the port pins.  So to avoid confusion, I write directly to OLATB instead.

#include "xstdsys.h"

unsigned char regValues[0X16];

void WriteRegisterValue(unsigned char address, unsigned char value)
{
    g_pTWI0->MSTRCTL &= ~(TWI_MSTRCTL_DCNT0 | TWI_MSTRCTL_DCNT1 | TWI_MSTRCTL_DCNT2 | TWI_MSTRCTL_DCNT3 | TWI_MSTRCTL_DCNT4 | TWI_MSTRCTL_DCNT5 | TWI_MSTRCTL_DCNT6 | TWI_MSTRCTL_DCNT7);
    g_pTWI0->MSTRCTL |= 0X02 << 6;    // transmit 2 bytes
    g_pTWI0->MSTRCTL &= ~TWI_MSTRCTL_DIR;    // transmit
    g_pTWI0->TXDATA8 = address;
    g_pTWI0->MSTRCTL |= TWI_MSTRCTL_EN;
    while (g_pTWI0->FIFOSTAT & (TWI_FIFOSTAT_TXSTAT0 | TWI_FIFOSTAT_TXSTAT1));
    while ((g_pTWI0->ISTAT & TWI_ISTAT_TXSERV) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_TXSERV;
    g_pTWI0->TXDATA8 = value;
    while ((g_pTWI0->ISTAT & TWI_ISTAT_MCOMP) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_TXSERV | TWI_ISTAT_MCOMP;
}

unsigned char ReadRegisterValue(unsigned char address)
{
    // send register address
    g_pTWI0->MSTRCTL &= ~(TWI_MSTRCTL_DCNT0 | TWI_MSTRCTL_DCNT1 | TWI_MSTRCTL_DCNT2 | TWI_MSTRCTL_DCNT3 | TWI_MSTRCTL_DCNT4 | TWI_MSTRCTL_DCNT5 | TWI_MSTRCTL_DCNT6 | TWI_MSTRCTL_DCNT7);
    g_pTWI0->MSTRCTL |= 0X01 << 6;    // 1 byte
    g_pTWI0->MSTRCTL &= ~TWI_MSTRCTL_DIR;    // transmit
    g_pTWI0->TXDATA8 = address;
    g_pTWI0->MSTRCTL |= TWI_MSTRCTL_EN;
    while (g_pTWI0->FIFOSTAT & (TWI_FIFOSTAT_TXSTAT0 | TWI_FIFOSTAT_TXSTAT1));
    while ((g_pTWI0->ISTAT & TWI_ISTAT_TXSERV) == 0);
    while ((g_pTWI0->ISTAT & TWI_ISTAT_MCOMP) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_TXSERV | TWI_ISTAT_MCOMP;

    // read value
    g_pTWI0->MSTRCTL &= ~(TWI_MSTRCTL_DCNT0 | TWI_MSTRCTL_DCNT1 | TWI_MSTRCTL_DCNT2 | TWI_MSTRCTL_DCNT3 | TWI_MSTRCTL_DCNT4 | TWI_MSTRCTL_DCNT5 | TWI_MSTRCTL_DCNT6 | TWI_MSTRCTL_DCNT7);
    g_pTWI0->MSTRCTL |= 0X01 << 6;    // 1 byte
    g_pTWI0->MSTRCTL |= TWI_MSTRCTL_DIR;    // receive
    g_pTWI0->MSTRCTL |= TWI_MSTRCTL_EN;
    while ((g_pTWI0->FIFOSTAT & TWI_FIFOSTAT_RXSTAT0) == 0);
    while ((g_pTWI0->ISTAT & TWI_ISTAT_MCOMP) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_RXSERV | TWI_ISTAT_MCOMP;
    return (unsigned char)g_pTWI0->RXDATA8;
}

main()
{
    g_pTWI0->CLKDIV = 0XFFFF;
    g_pTWI0->MSTRADDR = 0X0020; // U40
    g_pTWI0->CTL = TWI_CTL_EN;

    WriteRegisterValue(0X15, 0X3E);    // write OLATB (output latch B)

    for (unsigned char address = 0; address <= 0X15; address++)
    {
        regValues[address] = ReadRegisterValue(address);
    }


    while (1)                   
    {
    }
}

 

Tags: , , ,

Switches and LEDs on the ADSP-CM408F EZ-KIT Lite Board from 'No Boot - idle' mode

by Crossware 26. August 2014 18:32

We like examples to be as simple as possible and this is as simple as we can make it for controlling both the switches and the LEDs on the ADSP-CM408F EZ-KIT Lite Board.

The switches SW4 and SW5 are disabled by default and so from a 'No Boot - idle' mode, the soft switches must be configured.  This means sending commands to the U40 chip using the TWI interface.

The TWI clock and data pins are not multiplexed and so there is no need to configure the GPIO in order to use them.

Possibly we could get away with fewer while loops in the code below and we could also run the TWI at a faster speed.  But it works as written and that should get you started.

Pressing SW4 turns on LED1 and turns off LED2.  Pressing SW5 turns on LED3 and turns off LED4.

 

#include "xstdsys.h"

#define DELAY 100000

#define LED1PIN 7
#define LED2PIN 6
#define LED3PIN 5
#define LED4PIN 9

#define SW4PIN 10
#define SW5PIN 8

main()
{
    g_pTWI0->CLKDIV = 0XFFFF;
    g_pTWI0->MSTRADDR = 0X0020;    // U40
    g_pTWI0->CTL = TWI_CTL_EN;

    // set register 13 (gpiob) U40 to 0X3E
    // register 1 (iodirb) defaults to 0XFF and so need not be configured
    g_pTWI0->MSTRCTL &= ~(TWI_MSTRCTL_DCNT0 | TWI_MSTRCTL_DCNT1 | TWI_MSTRCTL_DCNT2 | TWI_MSTRCTL_DCNT3 | TWI_MSTRCTL_DCNT4 | TWI_MSTRCTL_DCNT5 | TWI_MSTRCTL_DCNT6 | TWI_MSTRCTL_DCNT7);
    g_pTWI0->MSTRCTL |= 0X02 << 6;    // transmit 2 bytes
    g_pTWI0->TXDATA8 = 0X13;    // GPIOB
    g_pTWI0->MSTRCTL |= TWI_MSTRCTL_EN;
    while (g_pTWI0->FIFOSTAT & (TWI_FIFOSTAT_TXSTAT0 | TWI_FIFOSTAT_TXSTAT1));
    while ((g_pTWI0->ISTAT & TWI_ISTAT_TXSERV) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_TXSERV;
    g_pTWI0->TXDATA8 = 0X3E;     // leds and switches enabled
    while ((g_pTWI0->ISTAT & TWI_ISTAT_MCOMP) == 0);
    g_pTWI0->ISTAT = TWI_ISTAT_TXSERV | TWI_ISTAT_MCOMP;


    g_pPORTF->INEN_SET = 1 << SW4PIN;    // enable input
    g_pPORTE->INEN_SET = 1 << SW5PIN;    // enable input
    g_pPORTE->DIR_SET = 1 << LED1PIN;     // set as output
    g_pPORTE->DIR_SET = 1 << LED2PIN;     // set as output
    g_pPORTE->DIR_SET = 1 << LED3PIN;     // set as output
    g_pPORTE->DIR_SET = 1 << LED4PIN;     // set as output

    while (1)                   
    {
        if (g_pPORTF->DATA & (1 << SW4PIN))
        {
            g_pPORTE->DATA_SET = 1 << LED1PIN;
            g_pPORTE->DATA_CLR = 1 << LED2PIN;
        }
        else
        {
            g_pPORTE->DATA_CLR = 1 << LED1PIN;
            g_pPORTE->DATA_SET = 1 << LED2PIN;
        }
        if (g_pPORTE->DATA & (1 << SW5PIN))
        {
            g_pPORTE->DATA_SET = 1 << LED3PIN;
            g_pPORTE->DATA_CLR = 1 << LED4PIN;
        }   
        else
        {
            g_pPORTE->DATA_CLR = 1 << LED3PIN;
            g_pPORTE->DATA_SET = 1 << LED4PIN;
        }
    }
}

Tags: , ,

Blog

Toggling LEDs on ADSP-CM408F EZ-KIT Lite Board

by Crossware 26. August 2014 18:12

Here is the simplest example C program we can devise for toggling the LEDs on the ADSP-CM408F EX-KIT Lite Board.

All LEDs are on Port E.  By default the LEDs are enabled and so the soft switched do not need to be configured.  Only the GPIO directions need to be set to make them outputs.

#include "xstdsys.h"

#define DELAY 100000

#define LED1PIN 7
#define LED2PIN 6
#define LED3PIN 5
#define LED4PIN 9

main()
{
    // the following four lines could be combined into one if desired
    g_pPORTE->DIR_SET = 1 << LED1PIN;    // set as output
    g_pPORTE->DIR_SET = 1 << LED2PIN;    // set as output
    g_pPORTE->DIR_SET = 1 << LED3PIN;    // set as output
    g_pPORTE->DIR_SET = 1 << LED4PIN;    // set as output

    while (1)                   
    {
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_SET = 1 << LED1PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_CLR = 1 << LED1PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_SET = 1 << LED2PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_CLR = 1 << LED2PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_SET = 1 << LED3PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_CLR = 1 << LED3PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_SET = 1 << LED4PIN;
        for (volatile int i = 0; i < DELAY; i++);
        g_pPORTE->DATA_CLR = 1 << LED4PIN;
    }
}

 

Tags: , ,

Blog

Switches and LEDs on the ADSP-CM408F EZ-KIT Lite Board

by Crossware 15. August 2014 16:11

We are developing support for Analog Device's ADSP-CM40x microcontrollers.

We received our ADSP-CM408F EZ-KIT Lite board on Monday and set about investigating the operation of the JTAG/SWD debugger interface.  Pretty soon we could download and run programs in SRAM.  (Lots of omissions and errors in ADI's reference manual though so it took a lot longer to get there than it should have!)

As usual during such developments we incrementally work our way though the peripherals adding register definitions, simple context menu wizards, simulation and so on, testing that things work along the way.

There are lots of examples for this board provided by ADI but we couldn't find anything remotely simple.  So here is how to read the input switches SW4 and SW5 and illiminate the LEDs LED1 and LED 2:

// Initial CPP Source File
#include "xstdsys.h"

main()
{
    // use the Wizards (see Wizards menu) to configure the on-chip peripherals
    g_pPORTF->INEN_SET = 1 << 10;
    g_pPORTE->INEN_SET = 1 << 8;
    g_pPORTE->DIR_SET = 1 << 7;
    g_pPORTE->DIR_SET = 1 << 6;

    while (1)                   
    {
        if (g_pPORTE->DATA & (1 << 8))
            g_pPORTE->DATA_SET = 1 << 7;
        else
            g_pPORTE->DATA_CLR = 1 << 7;
        if (g_pPORTF->DATA & (1 << 10))
            g_pPORTE->DATA_SET = 1 << 6;
        else
            g_pPORTE->DATA_CLR = 1 << 6;
    }
}

Pressing SW4 illuminates LED2 and pressing SW5 illuminates LED1.  That's all there is to it if the board boots in the factory configuration (SPI master boot mode with POST installed).

However, the installed POST program has already configured the Soft Configuration switches.  To use the switches and LEDs from 'No Boot - idle' mode, the Soft Configuration switches must be configured.

Tags: , ,

Blog

USB Debugger Drivers for Windows 8 and 8.1

by Crossware 28. April 2014 09:39

The Crossware USB drivers for the FireFly and Jaguar debug interfaces are now signed and so fully compatible with Windows 8 and 8.1.

Our experiments with Windows 8.1 indicate that it does not display a 'Found New Hardware' message when a new USB device is inserted into the PC.  In such cases it is necessary to open Device Manager to manual install the driver.

One approach is as follows:

To open Device Manager, press the Windows key to bring up the tiled desktop (if it is not already showing).  Press <space> and type 'drivers'. In the search list that is displayed, select 'Update Device Drivers'.  Device Manager should now open.

If you see 'Other Devices' listed in Device Manager, select it.  You should then see the FireFly or Jaguar device listed.  (If you don't see Other Devices, and you cannot see the entry for the FireFly or Jaguar device try unplugging and plugging the device back in to see which entry is removed and then added back into Device Manager.)

Right mouse click on the FireFly or Jaguar device entry and select 'Update Driver Software'  Then select 'Browse my Computer for Driver Software'.

Now you can browse to and select the folder containing the appropriate Crossware signed driver. Follow the instructions to install the driver.

How can you tell if the Crossware driver is signed?

We do not actually sign the driver DLLs, these are signed by Microsoft.  We sign the .INF file. The presence of a .CAT file matching the name of the .INF file indicates that the .INF file is signed. For the FireFly driver for 64-bit Windows you would see this:

Tags: , , , , ,

Support for NXP ARM9 LPC29xx Family

by Crossware 18. September 2013 11:50

We have just released support for NXP ARM9 LPC29xx family of microcontrollers.

See this page for more details of this support:

www.crossware.com/Arm/Lcp29xx

Tags:

Blog

About this blog

This is where you will find topical information that we think might be useful to you.

Month List