Showing posts with label Cortex. Show all posts
Showing posts with label Cortex. Show all posts

Saturday, October 10, 2015

DHT22 humidity and temperature published to dweet io with CC3200MOD from eBay

I see great potential in CC3200 for low power WiFi device. I mean battery powered and hibernating most of the time. TI promises years long operation this way. I wanted to test hibernation consumption on CC3200-LAUNCHXL eval board I played with before. Unfortunately LEDs and some other ICs stay powered on the board even if configured to be supplied with two AA batteries. TI did own low power tests without them. That meant unsoldering which I didn't want to do.
CC3200MOD seemed like a good alternative. I got one from eBay (even paid extra 2 bucks for faster shipping in hope that it will arrive sooner).

CC3200-LAUNCHXL

While waiting for CC3200MOD I wrote an application to read humidity and temperature data from DHT22 sensor wired to LAUNCHPAD with 3 wires.


It went smoothly. Results were instant. I decided to post data from sensor to dweet.io. dweet.io is a service to store small amounts of data (up to 2000 characters at the time of writing this) with http GET or POST requests. Data is then available (with up to 500 history entries at the time of writing this) to retrieve by other applications or just visualize on their page. JSON format is used for data.


CC3200MOD

Flat cable with 1.27mm spacing needed to be soldered to received CC3200MOD (it was a process I would rather not repeat - I like software more and more :) ). Additionally I crimped connector on the cable. I was worried that module schematics will be a mystery since I found no official document but it seems that schematics is like suggested by TI. I couldn't figure out the SPI FLASH device as marking seem custom.
[UDATE] According to SPI flash ID read out with command 0x9F returning EF 40 14 it should be W25Q80 8Mbit device from Winbond.


Photo below shows CC3200MOD with flat cable breakout, MM232R module from FTDI with FT232RQ USB to UART bridge for UNIFLASH software from TI to load firmware, iTAG50 debugger from iSYSTEM connected to debug pins, DHT22 and 2xAA battery pack for supply.



Code

I don't have nicely packed project to show the code (yet). Posting to dweet.io is shown below. Other than that it's DHT22 reading (you can get code for this everywhere on the web) and hibernation call in a loop.

#define SERVER_NAME "dweet.io"
void POST2dweet_io(float fTemp, float fHum)
{
  signed char g_Host[] = SERVER_NAME;
  unsigned int uiIP;
  long lRetVal = sl_NetAppDnsGetHostByName(g_Host, strlen((const char *)g_Host), (unsigned long*)&uiIP, SL_AF_INET);

  int iSockID = 0;
  iSockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);

  SlSockAddrIn_t    Addr;
  int    iAddrSize;
  Addr.sin_family = SL_AF_INET;
  Addr.sin_port = sl_Htons(80); // default port for http
  Addr.sin_addr.s_addr = sl_Htonl(uiIP);
  iAddrSize = sizeof(SlSockAddrIn_t);

  lRetVal = sl_Connect(iSockID, ( SlSockAddr_t *)&Addr, iAddrSize);

  const char *pPOSTHeaderFormat =
    "POST http://dweet.io/dweet/for/CC3200MODDHT22 HTTP/1.1\r\n"
    "Content-Type: application/json\r\n"
    "Content-Length: %d\r\n"
    "\r\n";
  const char *pPOSTBodyFormat =
    "{\"Hum\":%3.1f,\"Tmp\":%3.1f}";

  char acSendBuff[512] = { 0 };
  long lBodyLen = sprintf(acSendBuff, pPOSTBodyFormat, fHum, fTemp);
  lBodyLen = sprintf(acSendBuff, pPOSTHeaderFormat, lBodyLen);
  lBodyLen += sprintf(acSendBuff + lBodyLen, pPOSTBodyFormat, fHum, fTemp);
  acSendBuff[lBodyLen] = 0;
  int iTXStatus;
  iTXStatus = sl_Send(iSockID, acSendBuff, lBodyLen, 0);
}

Current usage

I couldn't measure hibernation consumption. It seems that my ampere meter has too much influence on supply rail. It looks like CC3200 is restarted on supply voltage drop in the moment of consumption change. Without ampere meter CC3200 works on lower voltages (tested with two rechargeable batteries at 2.4V).
Using active supply instead of AA batteries or proper shunt resistor for current measurement helped. I got cca. 5uA hibernation consumption and 25mA active mode consumption. I would agree that It takes around 5s for CC3200 to wake up, read DHT22 connect to WLAN and send data. From this one can evaluate how long a set of average AA with 2000mAh capacity will last. It's one year by waking up every 10 minutes.
Simplified calculation without taking into account all variables (e.g. battery self discharge) is as follows:
Charge used during active period:
Qap = Ia * Ta = 25mA * 5s = 125mAs
Charge used during idle period:
Qip = Ii * (Tp - Ta) = 5uA * (10min - 5s) = 2.975mAs
Sum of two makes up total charge used in one period:
Qpp = Qap + Qip = 127.975mAs (= 128mAs)
So the count of all periods per available charge in batteries is:
N = Qb / Qpp = 2000mAh / 128mAs = 56250
And total time:
T = N * Tp = 56250 * 10min = 390days

You can use function below in Google Sheets to test other combinations (provide values in SI units - s, A, As).

function BattDuration(BattCapacity, Iidle, Iactive, Tactive, Tperiod)
{
  var QperPeriod = Iidle * (Tperiod - Tactive) + Iactive * Tactive;
  var numCycles = BattCapacity / QperPeriod;
  var duration = numCycles * Tperiod;
  return duration;
}


Note: current in hibernation mode was measured with DHT22 disconnected!

CC3200 is awesome

With integrated FLASH it would be even better. But from what I understand it is difficult to mix silicon process for analog and FLASH. Maybe in next generation?
I don't get why ESP8266 is generating so much noise while CC3200 is getting so little coverage. I would agree that it depends on the usage scenario where for low power CC3200 wins as it was designed for it. But it also works without hibernation. And it offers more than twice as much with less than half hassle to get it to work for twice the price of a module compared to ESP8266. Is the $5 absolute price all we are going for? From what I read on the internet (and I could be wrong) ESP8266 doesn't have popular CPU with compilers and debuggers available - young open source solutions don't count. I didn't see HTTP server ready to use on ESP8266 nor out-of-the-box SSL support like CC3200 has. Not to mention peripherals, more RAM and bigger SPI FLASH support. I'm not saying CC3200 is better than ESP8266, except that it is :). Again, I might be biased because I never used ESP8266 and I don't want to start a war. However I did decide on CC3200 based on information I got from internet.

Wednesday, June 3, 2015

Before main()

I had a short presentation on build process and C program startup for embedded projects. Below are the slides from presentation with some additional info added for the purpose of this post.

In general I wanted to point out that most C compilers work in same fashion. Showcase examples below are based on GCC for Cortex M. Others compilers have equal functionality that only differs in syntax or naming and you can achieve same things with them.

Name "Compiler" for a toolset is a bit misleading. A toolset is a set of tools used for building a project and one of the steps is called compilation. It is done with compiler sub part. Image presents most vital parts of toolset (light green), again, badly marked as Compiler in lower left corner.

Overall the complete development environment is shown with emphasis that Editor, Compiler and Debugger are separate entities. They are usually sold as one IDE. But you can use each from different vendor if you wish. Write code in Visual Studio, compile with make and GCC and debug in Eclipse over GDB on OpenOCD. Executable file has the debug info (if not intentionally stripped in build process) so that debugger IDE can pick up source files specified in it. Such setups are complex to set and it's best to stick to simple all-in-one solutions. 

Compiler marks where address of external symbol is needed. Linker populates the address after all pieces are put together and absolute locations can be calculated.

Build process in example is made with two calls to compiler converting the source files to object files and one call to linker gluing them together. Well known 'make' also does this. It's just that it uses more complex/flexible syntax to describe with what parameters which utils are called and in what order. IDEs also do this internally. But the parameters are defined with clickable options in dialogs.

Few GCC info points as reference to sample:

Short comment to -ffunction-sections and --gc-sections option pair: size optimization with unused code deletion is not straight forward. Source files are not thrown at compiler executable all at once and processed together. They are processed one by one. Functions can't be just removed if not used inside single source file - they can be called from some other source files. So compiler can't do it. And linker knows nothing about functions. Trick here is to instruct compiler to tag each function and prepare it as separate chunk as input to linker. Linker can then figure out which chunks are not accessed and omit them from final image.

MEMORY layout tells the (GCC) linker where the memories are on target platform. This differs from device to device.

SECTIONS entries instruct linker where to put chunks of "program" generated by compiler. By default (GCC) compiler tags code (functions) with ".text", constants with ".rodata", initialized global variables with ".data" and uninitialized global variables with ".bss". Own tags can be used as shown. Tagged chunks are called 'compiler output sections' or 'linker input sections' and are not to be confused with 'linker output sections'.

There is a problem with not-loadable programs. Loadable programs like on PC where OS loads executable in memory and executes it have global variables initialized with loading, i.e. initial global variable values are written to variable locations when loading - the program is built that way. But nothing loads embedded programs. They are usually stored in nonvolatile (read only) memory and start executing at power on. So what about the initial values for global variables? They can't just appear in (RAM) memory out of thin air. RAM by definition holds random values at power on. But RAM is where variables are! The trick is to store initial values somewhere in nonvolatile memory and copy them to locations of global variables immediately after power on. GCC enables this with 'AT>' command in linker file. Global variables are linked to addresses in RAM but their initial values stored where 'AT>' points. Other compilers also do this, you just don't realize that they add this so called 'startup code' to your project and insert call to it somewhere soon after reset.

This is most minimal C project. It would be a single source file project if Some.h, SSomeStruct and SomeCall wouldn't be used.

Usually build process generates some summary of what was built. How it looks differs from compiler to compiler but in general information is what is present in final image, where it is and what is the size of it. It is commonly referred to as 'map' file.

Thursday, May 8, 2014

ARMv7 coprocessor access

Macros below generate little endian ARM (not THUMB) instructions for access to coprocessor. This for when instructions can't be compiled but rather stored in table as data.

// MCR<c> <coproc>, <opc1>, <rt>, <crn>, <crm>{, <opc2>}
// Read coprocessor register (no condition)
#define A_MRC(coproc, opc1, Rt, CRn, CRm, op2)  (0xEE100010 | (((opc1) & 0x7) << 21 ) | (((CRn) & 0xF) << 16 ) | (((Rt) & 0xF) << 12 ) | (((coproc) & 0xF) << 8) | (((op2) & 0x7) << 5)) | ((CRm) & 0xF)
// Write coprocessor register (no condition)
#define A_MCR(coproc, opc1, Rt, CRn, CRm, op2)  (0xEE000010 | (((opc1) & 0x7) << 21 ) | (((CRn) & 0xF) << 16 ) | (((Rt) & 0xF) << 12 ) | (((coproc) & 0xF) << 8) | (((op2) & 0x7) << 5)) | ((CRm) & 0xF)


Sunday, February 10, 2013

Free Cortex debugger

Emulator company iSystem offers free Cortex debugger. There are couple of options on how to get it. Most intriguing is the DIY option. The design is similar to STM32F4-Discovery board. I successfully managed to make it with the actual Discovery board. Following is how.

To supply the board from device USB port the connection from PA9 to 5V is needed (red wire). Further the BOOT0 needs to be connected to 3V (brown wire) to boot the device in DFU mode after power on. Also, I had onboard debugger disabled.

Needed connections


With these connections I followed the official guide on how to program the initial firmware (with iTAG_Public.exe) to STM simulating J2 (see documentation) with brown wire. There were some problems programming it from 32bit virtual machine. It worked on my 64bit W7 machine. Debugging was later possible in virtual machine.

Debugger works with free iTAG winIDEA IDE. Updating the firmware with winIDEA worked as described.

Output debug signals can be found in iTAG schematics (also available). I connected them to other STM32F4-Discovery board and downloaded the RTOS winIDEA sample to target on the other board for test. Supply for target was taken from debugger board.

Debugger - target connection (BOOT wire removed)


Target details

Debugger details

Debugging in winIDEA
Links:
Some points:
  • Schematics, utility, gerber files, iTAG winIDEA IDE available for free online
  • No registration required
  • No download size limit
  • GCC 4.7.0 compiler build for ARM/Cortex projects included with winIDEA
  • No trace functionality
There are two optional connectors on the official iTAG board. They seem like analog and digital extension ports like on some professional tools the company offers. However there are no options to configure them. Also, the SWO signal is connected to UART Rx pin on the debugger. This could mean that SWO trace option was planed. Hopefully the functionality will come with updates.

Tuesday, February 5, 2013

Cortex debug condition assertion

Used to popular ASSERT(condition) macro? Code below stops on faulty condition when debugging Cortex CPU. BE CAREFUL: use code build with _DEBUG or DEBUG define when debugging  BUT DON'T use same code without debugger.

#if defined ( _DEBUG ) || defined ( DEBUG )
  #define ASSERT(expr) { if ( !(expr) ) { __ASM__(" bkpt #0"); } }
#else
  #define ASSERT(...) { }
#endif

Usage:
void someFunc(int inputParam)
{
  ASSERT( inputParam < 5 );  ///< execution will stop here if inputParam >= 5
  ...
}

Friday, February 1, 2013

Stellaris LaunchPad with external debugger

Finally a board with integrated debugger and an official option for external debugger. I'm talking about EK-LM4F120XL. To disable integrated debugger the EXT_DBG signal must be tied low. I'm doing extended debug connectivity options demonstrations. Find below photos for both standard JTAG and Cortex connectors in combination with JTAG and SWD debug protocol with parallel or serial trace and without it.

Cortex debug connector

JTAG debug protocol + parallel trace


JTAG debug protocol


SWD debug protocol + parallel trace


SWD debug protocol + serial trace


SWD debug protocol


Jtag debug connector

JTAG debug protocol


SWD debug protocol + serial trace


SWD debug protocol


Friday, January 25, 2013

Kinetis FRDM-KL25Z with external debugger

Here is how to attach external debugger to Kinetis CPU on FRDM-KL25Z board. Like we are used to by now the debug connector on the boards with an on-board debugger is used to connect the on-board debugger to board without it. Anyway the debug connector can be used as input when on-board debugger is put in reset. This is done with jumper on the other debug connector. I.e. on the debug connector for the on-board debugger (debugging a debugger - there's a thought for you :) ).



You might need to chip away a bit of debug connector housing due to C7.
Probably not if you are just using pinheader.

Monday, December 17, 2012

CortexM exception context

You can get exception context inside exception handler from memory. On Cortex M cores the context is pushed on stack. I have prepared the struct type with layout equal to the exception context. The context is available by assigning the address of context in memory to local pointer to variable of prepared struct type.

The example bellow was made for GCC compiler where you can easily specify local variable as register. This is unnecessary for local pointer variable but must be done for LR which holds information about exception context. Notice the naked attribute to handler function. It is needed so that the handler has no function prologue which could change SP. SP (main or process) actually holds the address of the exception context.

For easier debugging the software breakpoint is added at the end of handler and automatic handler catch functionality can be disabled so that CPU stops at breakpoint (not on handler entry).




typedef struct
{
  unsigned long m_dwExR0;
  unsigned long m_dwExR1;
  unsigned long m_dwExR2;
  unsigned long m_dwExR3;
  unsigned long m_dwExR12;
  unsigned long m_dwExLR;
  unsigned long m_dwExPC;
  unsigned long m_dwExPSR;
}SCortexM3ExContext;

__attribute__( ( naked ) )
void HardFaultHandler()
{
  register SCortexM3ExContext * psCortexM3ExContext __asm("r0");
  register unsigned long dwLR __asm("lr");

  if ( dwLR & 4 )
    asm(" mrs r0, psp");
  else
    asm(" mrs r0, msp");

  asm(" BKPT");
  while ( 1 );
}

Wednesday, December 12, 2012

Cortex exceptions entry and return

There is a difference in exception handling on CortexM and CortexR/A cores. You can find details in ARM Architecture Reference Manuals (2 documents - separate for M and R/A).

Exception entry

Cortex M

The addresses of exception (interrupt) handlers must be listed in vector table at address specified in VTOR register. Each exception (interrupt) has predefined offset location in vector table. Be sure to have LSB set in vector table entry values (denoting THUMB destination).

Cortex R and A

32 bit jump instructions with destination address of corresponding handler functions must be listed from address 0x00000000 or 0xFFFF0000 or VBAR or HVBAR  based on SCTLR.V bit, Security Extensions and Virtualization Extensions implementation and settings. Be sure to use correct branch instruction based on destination handler THUMB or ARM state.


Exception return

Cortex M

Exception  return is detected by writing a value with bits 31 .. 28 set (0xFxxxxxxx) to PC (R15). Conveniently the appropriate value is written to LR (R14) when the exception is taken. So basically no extra care is needed when returning from handler. Jump to LR as for return from subroutine is enough.

Cortex R and A

Exception return is done with special instruction based on architectue version and privilege level. Possible instructions are SUBS, MOVS, RFE, LDM and ERET.
With GCC the handler functions can be decorated with attribute denoting that it is an exception handler. GCC will then generate proper return instructions in function epilogue. Possible entries for GCC interrupt attribute are: IRQ, FIQ, SWI, ABORT and UNDEF.

Thursday, August 9, 2012

Kinetis TWR-K70 main board mod for external debugger with trace

When plugging TWR main board to USB the integrated debugger enumerates and wants to install drivers. This can be annoying when you use external debugger and don't have drivers for on-board debugger installed at all. This debugger can be disabled with jumper connecting pins 2 and 4 on BDM connector J14. But with this change only the power switch for the rest of the board is permanently switched off. It can be forced to on state with applying high level on pin 4 of U2. Supply voltage is available on BDM connector.



Trace clock signal for parallel trace needs to be connected to external debug connector via R137 which is not populated by default.


Tuesday, May 1, 2012

WinUSB communication with STM32 (Part 4: Software)


Time for some bulk communication. VS project that I added to sources shows steps which are needed for communication. Project uses the Setupapi for device enumeration and obtaining the handle to device. It further uses the winusb to communicate with device.

After obtaining the handle to device and initializing it there can be multiple communication cycles. The communication cycle has the following steps:

  1. reset the communication channel (control EP)
  2. send data (bulk EP)
  3. send end of data message (control EP)
  4. poll status until "READY" or "ERROR" (control EP)
  5. read data size of response (control EP)
  6. read response data (bulk EP).
The source is mostly copied from MSDN with some changes and additions. An improvement to the library would be an object type which would encapsulate all this functionality and expose nice interface to communicate with device. An alternative could be  libusb-win32 or libusbK or other USB libraries. I haven't checked these in detail. If interested check libwdi. There is some information on Windows 8 integrated support for devices like this (no driver needed for WCID devices!).

[Update - WinXP (SP2) and W7 support driver information descriptors; See my next project]

Test application output.

Check project wiki to get build instructions.

This is the forth post in this series (of total 4 posts). See 12, 3.

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]

Tuesday, April 24, 2012

WinUSB communication with STM32 (Part 2: Firmware)

The sources are available at Google code project.

I decided to make a communication pipes implementation as library so that it can be used with other USB hardware. The library uses two bulk endpoints and control endpoint. One bulk endpoint is for receiving the data and the other for sending the data. The default control endpoint (EP0) is used for communication control.
User's code should repeatedly call single function in library which does nothing while no data is received and calls user's function when new packet arrives.

Larger communication buffers are better for faster communication. To improve it even more the USB implementation should use double buffered endpoints - not the case at the moment.

This is the second post in this series (of total 4 posts). See 134

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]

Wednesday, April 18, 2012

LPCXpresso upgrade for external debugger

I found long lost LPCXpresso under pile of paper when tidying the desk - you just have to do it every now and then :). Below are the images of modification for the board to work with external debugger. When added jumper is closed you can use external debugger with standard 10pin Cortex connector. If your debugger uses VCC pin (1) for target supply detection you should shorten the R29. My board came without R29 placed.

Added jumper holds integrated debugger in reset.

I soldered the pinhead on both sides for robustness.

Tuesday, April 17, 2012

WinUSB communication with STM32 (Part 1: Intro)

Aren't you fed up with putting a USB to serial converter in your embedded design while you have a USB capable device already in the design? Any other approach opens a can of worms though. Custom driver, certificate to sign it, USB vendor ID (2000$ at the moment), how to communicate with device on a layer above USB? But it is nice when OS pops up your name when your device is plugged in USB port. WinUSB is middle ground with tradeoffs one might consider.

I wanted to test the use of WinUSB with STM32F103 for some time now. When I finally got time I created a demo project. It shows basic request - response communication.
WinUSB kernel mode driver enables raw communication through USB pipes. In other words you can communicate with your USB device directly from application on the PC. So there is only code for application and code for firmware. Presuming you are not making standard USB class device like Mass Storage or HID. You might not even need custom PC side software in this case.
Furthermore the libraries to communicate are written for both ends to some extent. There SetupAPI and WinUSB on Windows side while ST has libraries for everything.
To get a taste check images below. I will post more about it in the future and probably publish the sources after I clean and organize them.

VS showing sent data.

winIDEA showing same received data on STM32.

This is the first post in this series (of total 4 posts). See  234.

[Update - I have a new WinUSB device project with STM32F407 without the need for Windows side driver info (.inf and .cat files) ]


Tuesday, March 6, 2012

STM32F4DISCOVERY Eval board with external debugger

I got the STM32F4DISCOVERY demo board at Embedded World last week. To my surprise the SWD  (single wire debug) connector is not meant for external debugger. In fact it is the other way around. The board can be used  as debugger to debug designs without on-board debugger.

I wanted to attach my debugger anyway. To disable the on-board debugger I hold it in reset by connecting it's reset signal to GND via SB10. To make it reversible I added jumper over SB10 solder jumper.



The external debugger can measure the VDD pin voltage for target detection. *
Single wire output (SWO) trace can be used when using the SWD. * NOTE: this is for trace only - not needed for (invasive) debug.


Even old style JTAG scan debugging is possible (it can be faster) if additional TDI signal is connected. It is at PA15. NOTE: SWO can't be used with JTAG.


Parallel trace on pins PE2 - PE6 is an option when JTAG is used * - not shown on photos.

* -  if supported by external debugger

[Update] See how STM32F4DISCOVERY can be used as free debugger.