Recent site activity

Welcome

Here are details of various projects I've worked on in the past, and updates of what I'm working on now. There's personal and contact details list on Facebook , Linked In and Google Profile if you want to contact me. 

Content here is posted with a 'Creative Commons' license, so sharing/linking and derivative works are encouraged. See Projects for details.

Chris Shucksmith

Upverter Schematic

posted 23 Sep 2011 01:08 by Chris Shucksmith   [ updated 23 Sep 2011 01:16 ]

Something I have wanted to do for a while is edit schematics and easily embed them without having to draw offline, export as PNG and then upload to Google Sites. Using the web-based EDA tool Upverter, it looks like this is possible, if not yet openly encouraged.

Here's a quick diagram I put together yesterday:

Upverter Schematic



E24 Resistors & ASCII

posted 5 Aug 2011 01:53 by Chris Shucksmith   [ updated 9 Aug 2011 11:08 ]

I use this graphic from http://www.diyaudioandvideo.com/Electronics/Color/ for picking resistors from an E24 set. As a reference guide, the table has a minor  problems: there's uniform padding between the value and the colour swatches either side, so it's easy to end up seeking right rather than left from a quantity and locating the wrong component. It could use a re-draw... here's the original:


Another handy document is my favourite ASCII table (oh dear). I use a paper copy at work a couple of times a week, printed from http://frank.harvard.edu/aoe/images/t10r3.pdf It was produced by Cambridge University Press, probably as an appendix to some unknown book, although the web copy is hosted by Harvard. It shows the symmetry (beauty?) in the code point assignment, and the split of hexades into printing and non-printing codes. 


I hope posting this qualifies as fair-use of a printed book, as it's 1-page and I think you can copy up to four pages or something similar.



OpenBench Logic Analyser

posted 15 Sep 2010 12:46 by Chris Shucksmith   [ updated 18 Jul 2011 05:30 ]

I'm hoping to use the 45$ OpenBench Logic Analyser to help debug the 1wire, I2C and LCD communications. The software is a Java GUI, and the hardware uses an FPGA chip to record and store samples, and evaluate trigger logic. The entire product (PCB, VHDL code, Java client) is all open source for tinkering!

Here you can see my Java 1-wire bus temperature controller driving the 1wire bus (pin 0) via. a DS2480B line driver. It's clear that the PC stack is holding back the communication speed - the 1-wire encoded bytes are separated (only) by the time to call back to the Java code to prepare the next byte. I might try sending multiple bytes down to RXTX together to see if that reduces the space/mark ratio.

The 1wire short/long pulse encoding is easily seen. There are transients (oddly staggered?) on pins 1-7, these are floating inputs :-(


Here's the stock picture of the hardware:


Test site build out

posted 28 Aug 2010 05:59 by Chris Shucksmith

Hopefully this weekend another couple of temperature sensors will be installed at the first test site.

We have chosen to install approximately one temperature sensor per room. Using a vented spacer place the temperature sensor will sit behind the light switches, and the Cat5 comms cable will run (at least for the vertical descent) alongside the mains lighting cable in trunking. I believe this is OK under the UK building regulations, but I'm sure the buildings inspector will let us know. 

The sensor is simply soldered on the end of the CAT5 cable and left loose inside the spacer plate. In the space between floors the cable will run to a punch-down comms junction box (BT type), then back to the control unit. I have yet to actually test a long cable run, so need to experiment with the slew-rate limited outputs. In the worst case the network might require some segmentation and dual transcievers, but I hope with cable runs less than 30m it should be OK on one.

The control unit is still veroboard, no chance of CE approval for a while yet then :-)


Eight DS1822

posted 31 Jan 2010 14:15 by Chris Shucksmith   [ updated 18 Jul 2011 05:27 ]

I took delivery of another batch of 2xDS1822+PAR and 2xDS1822+ temperature sensors in the week, bringing to total up to eight. The parts are probably around £2 a piece from a specialist supplier. Maxim only quote price per thousand. I've wired them to the test rig, in parallel with the previous sensors and completed a three day test to check operation.


The sensors offer good resolution, but the precision of the parts does not seem to be fantastic, variations of almost a degree over the set (see chart below). It seems that humans can detect a one-degree difference - I know a system that hunts with a half a degree dead-band around target.

A simple regression (over 86,856 points, approx 10,000 per part) should allow adequate calibration, i.e. determine a0 and a1 from tactual = a0 + a1*tsensor  for each sensor. For tactual I will use the mean, I have no other reference :-(  


Charting thanks to KDB Studio + kx Systems q evaluation.

Maxim 1-wire drivers

posted 17 Jan 2010 13:40 by Chris Shucksmith   [ updated 17 Jul 2011 10:32 ]

I've developed a Java library to communicate with Maxim-IC "1-wire bus" devices. The test rig uses a USB -> serial port adapter (FDI) to interface at logic level with the DS2480 line driver. A bus driver was selected due to the shortcomings of driving 100m+ buses directly with MCU pins. To minimise signal reflection (ringing) rising and falling edges need be slew-rate limited and input voltage thresholds need ideally outside those used for (high-speed) logic interconnects. Maxm has an interesting article on bus design considerations including some scope traces of the analogue behaviour of 1 wire buses under various conditions:



Once the bus hardware is selected, the devices connected need to be identified, and this is where the software comes in.

Each device on the 1-wire bus has a unique 64-bit (8 byte) address etched by the manufacturer, unknown to the purchaser! Enumerating the entire address space to search for devices would take a long time: perhaps 2 ^ 64 * 1ms = ~ 584.9 million years! The bus design incorporates a "host discovery" facility where a 64 bit address is broadcast serially and listening devices indicate if they are "still listening" after each bit with a chirp. A host can enumerate rapidly, starting from an initial address, and quickly discard sub-trees of the address space that contain no devices. The discovery protocol details are fairly complex and recommendations speicified in 1-wire search algorithm, and briefly paraphrased here.  

At the start of discovery, all devices initialise a boolean state {participating,idle} to active and keep a count of discovered address bits 0-63. Each of the 64 bits is enumerated over four time slices: master-chipslave-0sslave-1smaster-decision. The master broadcasts during the first and last slots, slaves during the second and third. The master-chirp initiates each cycle. Devices in the [active] state chirp a reply during either the slave0 or slave1 timeslot, depending on the value at the current position in the device unique address. It is quite usual on populated buses for for multiple devices to chip concurrently in these timeslots. In the fourth slot the master indicates if it is exploring the zero or 1 sub-tree, and this causes de-selected devices (if any) to move from [participating] -> [idle]. The key to this process is that the master knows before taking a branch decision which of the two possible address space branches are populated (with at least one device). No time is spent exhausting empty sub trees. After 63 bits are enumerated, chirps signal individual devices, provided of course that the manufacturer does not reuse addresses!

In Java, I keep a queue of enumerable routes. Each discovery pass determines exactly one device, and generates possibly multiple branch points at which the search must continue to find the remaining device(s), putting them in a Queue. A sample run with two devices is show below:

Enumerating bus devices
 bus reset performed, state: PRESENCE_PULSE
 search bus command
 exploring route 0000000000000000
 sent: 00000000000000000000000000000000
 recv: aa820000000000080028080202890880
 route 0000000000000000 device f900000206211a28  discrepancies 0000000000000100
   discrepancy bit 8, adding route 0000000000000100
 bus reset performed, state: PRESENCE_PULSE
 search bus command
 exploring route 0000000000000100
 sent: 00000000000000000000000000020000
 recv: a2200000000000080028022802170880
 route 0000000000000100 device d400000206161128  discrepancies 0000000000000700
   discrepancy bit 9, adding route 0000000000000300
   discrepancy bit 10, adding route 0000000000000500
 bus reset performed, state: PRESENCE_PULSE
 search bus command
 exploring route 0000000000000300
 sent: 000000000000000000000000000a0000
 recv: 8200000000000008200002a88a8f0880
 route 0000000000000300 device 90000002401ebb28  discrepancies 0000000000000300
 bus reset performed, state: PRESENCE_PULSE
 search bus command
 exploring route 0000000000000500
 sent: 00000000000000000000000000220000
 recv: aa2a0000000000080aaa88aa28370880
 route 0000000000000500 device f70000023faf6528  discrepancies 0000000000000700
Found devices: [f900000206211a28, d400000206161128, 90000002401ebb28, f70000023faf6528]
Requesting conversion for f900000206211a28
 bus reset performed, state: PRESENCE_PULSE
 bus reset performed, state: PRESENCE_PULSE
Reading temperature for f900000206211a28
 bus reset performed, state: PRESENCE_PULSE
 scatchpad d81003ff7f464b014d
 crc 'd8' OK
 bus reset performed, state: PRESENCE_PULSE
 Temperature  20.8125 deg-C
Requesting conversion for d400000206161128
 bus reset performed, state: PRESENCE_PULSE
 bus reset performed, state: PRESENCE_PULSE
Reading temperature for d400000206161128
 bus reset performed, state: PRESENCE_PULSE
 scatchpad ff100eff7f464b0152
 crc 'ff' OK
 bus reset performed, state: PRESENCE_PULSE
 Temperature  21.1250 deg-C
Requesting conversion for 90000002401ebb28
 bus reset performed, state: PRESENCE_PULSE
 bus reset performed, state: PRESENCE_PULSE
Reading temperature for 90000002401ebb28
 bus reset performed, state: PRESENCE_PULSE
 scatchpad 03100eff7f464b0162
 crc '03' OK
 bus reset performed, state: PRESENCE_PULSE
 Temperature  22.1250 deg-C
Requesting conversion for f70000023faf6528
 bus reset performed, state: PRESENCE_PULSE
 bus reset performed, state: PRESENCE_PULSE
Reading temperature for f70000023faf6528
 bus reset performed, state: PRESENCE_PULSE
 scatchpad a31006ff7f464b015a
 crc 'a3' OK
 bus reset performed, state: PRESENCE_PULSE
 Temperature  21.6250 deg-C

To-do list:
  • consider devices that disconnect during a search, and/or brown-out
  • driver needs code to switch the DS2480 into flexible driver mode and set recommended long-line parameters
  • validate CRCs

Ecolux progress

posted 26 Dec 2009 05:47 by Chris Shucksmith   [ updated 18 Jul 2011 05:27 ]

Time for an overview of the 'tinkering time' project, codename "Ecolux". This is a domestic/commercial heating controller prototype, and I'm looking to build exactly one unit and give it my father as a gift. The Ecolux is a 3-8 zone system, using a remote digital thermostat in each zone. There will be a bank of electrically operated 2-port vales near the boiler to direct heat to each zone. The plumbing is laid star rather than bus, so at the boiler are a flow/return pair for each switched zone. The radiators are a mixture of standard convection panels (sized per building reg.s) and one or two forced (fan-assisted) under-unit devices. There is wall mounted unit at the boiler which houses the microprocessor and valve drivers, and another small pannel housing LCD screen and joystick, hopefully to be mounted on a double-size UK domestic socket.

The prototype electronics are coming along, and the vero-board is now hopefully be the final layout. 




USB Round-trip latency

posted 29 Nov 2009 13:01 by Chris Shucksmith

The USB port on the STM32 is now working! I now have Java -> RXTX -> USB /dev/ttyACM0 -> USB cable -> STM32 USB Library -> C-code. Here's the Java stdout console showing the round trip time for a simple protocol. The device consumes a byte, shifts it and sends the result back.

Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
Opening /dev/ttyACM0
1259527875761 << sent 00000001 01
1259527875763 >> recv 00000010 02
1259527875763 << sent 00000001 01
1259527875766 >> recv 00000010 02
finished
Experimental:  JNI_OnLoad called.

A 3ms round trip seems reasonable, given the polling nature of USB IN endpoints and all the context switching/vm calls on the PC host. I'm sure the USB latency can be improved with other transfer modes than CONTROL, but that would require replacing RXTX with my own libusb (JNI) code.

Here's the result of dmesg when the device is inserted:

usb 4-1: USB disconnect, address 30
usb 4-1: new full speed USB device using uhci_hcd and address 31
usb 4-1: New USB device found, idVendor=0483, idProduct=5740
usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 4-1: Product: ShuckcByteshifter  
usb 4-1: Manufacturer: ShuckcMicroelectronics
usb 4-1: SerialNumber: 6
usb 4-1: configuration #1 chosen from 1 choice
cdc_acm 4-1:1.0: This device cannot do calls on its own. It is no modem.
cdc_acm 4-1:1.0: ttyACM0: USB ACM device

The code I've adapted presents itself as an ACM device to allow the host to send a lineconfig, i.e. port settings for a virtual com device, but I don't need that functionality.

HardFault and .thumb_func

posted 28 Nov 2009 08:57 by Chris Shucksmith   [ updated 17 Jul 2011 11:03 ]

Something isn't correct with the code I'm generating. The CPU quickly runs into a HardFault. Here's how I debugged the problem with OpenOCD.

> soft_reset_halt
requesting target halt and executing a soft reset
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 00000000 pc: 0x0000010c msp: 0x20000800
> stm32x mass_erase 0
stm32x mass erase complete
> flash write_bank 0 main.bin 0
wrote 23564 byte from file main.bin to flash bank 0 at offset 0x00000000 in 1.313711s (17.516576 kb/s)
> soft_reset_halt
requesting target halt and executing a soft reset
target state: halted
target halted due to breakpoint, current mode: Thread
xPSR: 00000000 pc: 0x0000010c msp: 0x20000800
> cortex_m3 disassemble 0x0010c 1
0x0000010c 0x2100 MOVS r1, #00
> step
target state: halted
target halted due to single-step, current mode: Handler HardFault
xPSR: 0x01000003 pc: 0x00000138 msp: 0x200007e0

Hmmm. crashed and ended up in the hard fault handler. Notice the msp (main stack pointer) has moved. The CPU dumps a load of state
on the stack before entering the handler. Let's view and decode from msp at 0x200007e0

> mdw 0x200007c0 24 0x200007c0: 25755485 a37a32e8 2d1af580 e55f3d49 6545d91c 0231a83a ae2e2af8 ca03fd92 0x200007e0: ffff3d6d f6ffdff4 21a13c08 0007c589 ffffcfbf ffffffff 0000010c 00000000 0x20000800: b7a2a2ba 317e1c50 2c4c5a0d 6cf67a8b 2988a1a5 6bc1f1dc 99a6d10d 98ef9b9e This forum post http://www.st.com/mcu/modules.php?mop=modload&name=Splatt_Forums&file=viewtopic&topic=6778&forum=23 gives the following ordering of data on the stack:
r0   ffff3d6d
r1 f6ffdff4
r2 21a13c08
r3 0007c589
r12 ffffcfbf
LR ffffffff
PC 0000010c
xPSR 00000000


We can also have a look at the Hard Fault Status register at 0xE000ED2C. This has the 30th bit set (0b0100 in the top nibble) indicating "hard fault  taken because of bus fault/memory management fault/usage fault" :
> mdw 0xE000ED2C 1     
0xe000ed2c: 40000000 
 See page 180 of the Cortex-M3 Technical Reference Manual http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf 
We can check the Memory Management Fault Status Register 0xE000ED28, Bus Fault Status Register 0xE000ED29, and Usage Fault Status Register 
0xE000ED2A for more information on the cause. Dumping 4 bytes from the base (together known as CSFR):

> mdb 0xE000ED28 1
0xe000ed28: 00020000
0x00    Memory Management Fault Status Register
0x00    Bus fault Status Register
0x0002  Usage Fault Status Register
Value 02 in the usage fault status register corresponds to bit 1 being set, ie.

[2] INVPC Attempt to load EXC_RETURN into PC illegally. Invalid instruction, invalid context, invalid
value. The return PC points to the instruction that tried to set the PC.
[1] INVSTATE Invalid combination of EPSR and instruction, for reasons other than UNDEFINED
instruction. Return PC points to faulting instruction, with the invalid state.
[0] UNDEFINSTR The UNDEFINSTR flag is set when the processor attempts to execute an undefined
instruction. This is an instruction that the processor cannot decode. The return PC points to
the undefined instruction.
 
How did the CPU end up in INVSTATE?

Looks like this is a common occurence! http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka12545.html
"Why does my Cortex-M3 Lock Up with a Hard Fault three cycles after reset?"
The vector table in Cortex-M3 (unlike older ARM processors) is a list of addresses (vectors). These vectors are defined
as interworking-capable, therefore all populated entries in the vector table must have bit[0] SET.

If the Reset vector is an even number, the processor will immediately call a Usage Fault of type INVSTATE due to the attempt to invoke the ARM instruction set for the Reset Handler. Because the Usage Fault is not enabled at Reset, the fault will escalate to Hard Fault. The Hard Fault vector itself will cause another Usage Fault due to its bit[0] being CLEAR. The occurrence of a fault inside the Hard Fault handler will result in the processor discontinuing fetching and execution, and asserting its LOCKUP output signal.

Vector table entries which are code entry point labels will be taken care of by the compilation toolset. For vector table entries which are written as literal constants in the code, the programmer must ensure that bit[0] is set to ‘1’.

Ah, that makes sense!

Determined this occurred because I'm missing a .thumb_func modifier for the assembly main function. Here's the correction to startup_stm32f10x_ld.s
.section .text
.weak Reset_Handler
.type Reset_Handler, %function
.thumb_func
Reset_Handler:

/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit

The listing file now shows the vector table, with the reset vector pointing to the code at 0000010c, adjusted to 10d with the LSB set:

main.out:     file format elf32-littlearm

Disassembly of section .text:

00000000 <g_pfnVectors>:
       0:    00 08 00 20 0d 01 00 00 39 01 00 00 39 01 00 00     ... ....9...9...
      10:    39 01 00 00 39 01 00 00 39 01 00 00 00 00 00 00     9...9...9.......
    ...
      2c:    39 01 00 00 39 01 00 00 00 00 00 00 39 01 00 00     9...9.......9...


It would help a lot if the .thumb_func modifier were set automatically when  -mcpu=cortex_m3 is passed to arm-elf-as/arm-elf-ld (maybe I could patch it?).

gcc: relocation truncated

posted 25 Nov 2009 14:46 by Chris Shucksmith   [ updated 18 Jul 2011 05:30 ]

I've been struggling with this message "relocation truncated to fit: R_ARM_THM_CALL" during a build with GCC binutils for arm-elf:

$ make

arm-elf-gcc -I. -Iinc -ISTM32_USB/inc -ISTM32F10x_StdPeriph/inc -ICMSIS/Core/CM3 -I/usr/include -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb src/main.c
arm-elf-as -ahls -mapcs-32  -o startup_stm32f10x_ld.o CMSIS/Core/CM3/startup_stm32f10x_ld.s > startup_stm32f10x_ld.lst
arm-elf-ld -v -Tstm_h103_linker -nostartfiles -o main.out startup_stm32f10x_ld.o main.o misc.o hw_config.o usb_init.o usb_istr.o usb_int.o usb_desc.o usb_mem.o usb_endp.o usb_prop.o usb_sil.o usb_core.o usb_pwr.o usb_regs.o stm32f10x_rcc.o stm32f10x_flash.o stm32f10x_gpio.o stm32f10x_usart.o
startup_stm32f10x_ld.o:(.text.Reset_Handler+0x26): relocation truncated to fit: R_ARM_THM_CALL against symbol `main' defined in .text section in main.o
make: *** [main.out] Error 1
GNU ld (GNU Binutils) 2.18 + coff-avr-patch (20050630)

Took me a long while to figure this one out!

In 
CMSIS/Core/CM3/startup_stm32f10x_ld.s  there is an assembler routine doing initialisation then calling the C main function. The code was set to output to a section not defined in my linker script (stm_h103_linker). It seems the default behaviour is to append the object code at the end of the last defined segment, which was an address in RAM starting at 2gb, far away from the rest of the code, starting at 0x0 in the .text section. This caused the error above when the linker tried to substitute the address of main into the following code:

/* Call the application's entry point.*/
  bl main
  bx lr

To figure this out I in-lined the "long-call veneer" i.e.. assembly to call a full 32bit address, rather than the bx thumb instruction above which is limited to calling +/- 4mb.

/* Call the application's entry point.*/
  ldr r0, =main
  bx r0
  bx  lr

This fudge allowed the linking to complete. I then went through the listing main.lst and noticed the bogus address. Interestingly, I think the resulting binary would initially work on the target hardware, only to fail badly at runtime after a reboot, as init code in RAM would be lost.

The following CrossWorks support post was helpful http://rowley.zendesk.com/forums/51134/entries/46203 as was the discussion on the binutils developers list http://sourceware.org/ml/binutils/2009-02/msg00224.html

Lessons learned? Know the hardware memory map, really understand what the toolchain is doing and watch out for undeclared sections!

1-10 of 13

Sign in  |  Recent Site Activity  |  Terms  |  Report Abuse  |  Print page  |  Powered by Google Sites