HardFault handler on supervisor call (SVC) when starting FreeRTOS kernel (CM-4)

During the initialization of FreeRTOS kernel, kernel calls the first task with function:

/*
 * FreeRTOS Kernel V10.4.1
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
*/

static void prvPortStartFirstTask( void )
{
    /* Start the first task.  This also clears the bit that indicates the FPU is
     * in use in case the FPU was used before the scheduler was started - which
     * would otherwise result in the unnecessary leaving of space in the SVC stack
     * for lazy saving of FPU registers. */
    __asm volatile (
        " ldr r0, =0xE000ED08 	\n"/* Use the NVIC offset register to locate the stack. */
        " ldr r0, [r0] 			\n"
        " ldr r0, [r0] 			\n"
        " msr msp, r0			\n"/* Set the msp back to the start of the stack. */
        " mov r0, #0			\n"/* Clear the bit that indicates the FPU is in use, see comment above. */
        " msr control, r0		\n"
        " cpsie i				\n"/* Globally enable interrupts. */
        " cpsie f				\n"
        " dsb					\n"
        " isb					\n"
        " svc 0					\n"/* System call to start first task. */
        " nop					\n"
        " .ltorg				\n"
        );
}

At the third instruction, counting from the bottom, svc is being called. It is a supervisor call, which calls an SVCall exception.

Figure 2-2 from “The Cortex-M4 Devices Generic User Guide”

If after that instruction HardFault happens it might be caused by non zero value of BASEPRI register.

Base Priority Mask Register (BASEPRI) is a register which defines the minimum priority for exception processing. If the value of the register not equals zero, than it prevents the activation of all exceptions when they have the same or lower priority level than the one set with BASEPRI.

Table 2-9 from “The Cortex-M4 Devices Generic User Guide”

Sometimes, it might be forgotten to look at that register when debugging HardFault exception during the FreeRTOS initialization.

Yet another BME280 single readout

I needed a simple readout of temperature in my garage, so I bought BME280 and connect it to RPi.
My language of choice is python, as I wanted to connect this with domoticz server.

Link to GitHub: master/BME280_simple.py

Python made – RIGOL DP832 GUI – Ethernet



As I had some free time, and we had recently got Programmable Power Supply RIGOL DP832, I have made python based GUI, to communicate with RIGOL.
It is based on:

PyVisa version: 1.8
PyQt version: 5.8.1
Qt version: 5.8.0
Matplotlib version: 2.0.0

and uses Ethernet to communicate with RIGOL.

pip install -U pyvisa
pip install -U pqt5



Link to GitHub: https://github.com/kudl4t4/RIGOL-DP832-GUI

Beaglebone PCF8574A simple driver

PCF8574A is 8-bit expander with I2C bus.
Driver will check presence of dev in device-tree, and will count from 0x00 to 0xff.
Device tree modifications(vs orginal TI device-trr for beaglebone)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
i2c1_pins: pinmux_i2c1_pins {
    pinctrl-single,pins = <
      AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2) /*spi0_d1.i2c1_sda*/
      AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2) /*spi0_cs0.i2c1_scl*/
    >;
  };
}
 
&i2c1 {
  pinctrl-names = "default";
  pinctrl-0 = <&i2c1_pins>;
  clock-frequency = <100000>;
  status = "ok";
 
  i2c_pcf: i2c_pcf@3f {
    compatible = "fei2c,pcfmodule";
    reg = <0x3f>;
  };
};

In driver we must create probe and remove functions, and “of” table to match driver with device-tree.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static void pcf_timCallback( unsigned long args )
{
  pr_info("PCF: timer callback\n");
}
 
int pcf_threadFunc( void *data )
{
  struct pcf_data *dev = data;
  while(1) {
    if(kthread_should_stop())
      return 0;
    if( 1 != i2c_master_send(dev->client,&dev->out_state,1) )
    {
      pr_info("Error writing to pcf device\n");
    }
    dev->out_state += 1;
    msleep(5);
  }
}
 
int pcf_probe(struct i2c_client *client, const struct i2c_device_id *dev)
{
  int ret;
  char buf = 0x02;
  pr_info("i2c:pcf -> probe. Addr: %x\n",client->addr);
 
  ret = i2c_master_send(client,&buf,1);
  if( ret < 0 )
  {
    pr_info("Error during communication with dev\n");
    return -ENOSYS;
  }
 
  dev_data = devm_kzalloc(&client->dev,sizeof(struct pcf_data),GFP_KERNEL);
  if( !dev_data )
  {
    pr_info("Memory alloc fail\n");
    return -ENOMEM;
  }
 
  dev_data->client = client;
  dev_data->out_state = 0x03;
  setup_timer(&dev_data->tick_timer,pcf_timCallback,0);
  mod_timer(&dev_data->tick_timer,jiffies+msecs_to_jiffies(10000));
 
  dev_data->blinkThread = kthread_run(pcf_threadFunc,dev_data,"pcf_thread");
  return 0;
}
 
int pcf_remove(struct i2c_client *client)
{
  pr_info("i2c:pcf -> remove\n");
  kthread_stop(dev_data->blinkThread);
  return 0;
}
 
static const struct i2c_device_id pcf_id[] = {
  {"pcf8574",0},
  {}
};
 
MODULE_DEVICE_TABLE(i2c,pcf_id);
 
static const struct of_device_id pcf_dt_ids[] = {
  { .compatible = "fei2c,pcfmodule",},
  {}
};
MODULE_DEVICE_TABLE(of,pcf_dt_ids);
 
static struct i2c_driver pcf_driver = {
  .probe = pcf_probe,
  .remove = pcf_remove,
  .id_table = pcf_id,
  .driver = {
    .name = "pcf8574_driver",
    .owner = THIS_MODULE,
    .of_match_table = of_match_ptr(pcf_dt_ids),
  },
};
module_i2c_driver(pcf_driver);

After insmod module, if compatible device will be found – probe function will create blinking thread.

Library for ATmega8A in C++

Have been trying to write a library for ATmega8A in c++.
The results are on GitHub:
GITHub libatm8a

AVR TOOLCHAIN based on: gcc 6.20, libc 2.0.0 & binutils 2.27

With the help from Zak’s Electronics Blog ~* and AVR LIBC user’s manual
I have compilied avr toolchain, for my personal use, with the newest edition of (as of today) gcc, libc and binutils. I have also changed avr-size a little by patching missing avr microcontrolers, which atmel adds to its toolchain.

 

./avr-gcc --versionavr-gcc (GCC) 6.2.0
Copyright (C) 2016 Free Software Foundation, Inc.
binutils 2.27
avr-libc2.0.0
./avr-gdb --versionGNU gdb (GDB) 7.12
Copyright (C) 2016 Free Software Foundation, Inc.

 

If you like, you can download it from Dropbox:
avr-linux-toolchain.tar.gz
avr-win32-toolchain.tar.gz
avr-win64-toolchain.tar.gz