I'm trying to control an unknown stepper motor with the high-end timer (NHET) module of a Texas Instruments Hercules microcontroller I got a freebie from TI almost a year ago. An unknown stepper motor, a driver board and a Hercules RM57 LaunchPad. The code to run the motor was expected to arrive too (it was an assignment for an internal) but that never materialised. In this blog series I'm trying to program the NHET module so that it sends the right signals to make the stepper step.
In the 7th blog I create an Assembler program for the HET submodule. |
Hercules High-End Timer
Hercules microcontrollers have a particular type of timer on board. It's an autonomous sub-controller.
The difference with your typical timer is that you don't set registers to control it.
You write a program in the HET assembly language.
The asm commands are also different from those of a controller or a processor. Everything is related to timer, angular functions, tight control of timer loop.
Often they can do several things in parallel during a single click of the HET clock.
And the module can interact with the ARM controller(s) on the Hercules - memory access and interrupts.
Expert programmers can achieve amazing things.
It's possible to handle the whole server motor control (ramp up, constant speed and ramp down) in the HET module.
The ARM would just set the number of steps to take and go to deep sleep. I'd like to achieve that in this blog series.
I have another example published by TI where the whole i²c protocol is implemented in the HET assembly language.
HET Test Program
Today I just want to see if I can get a HET program assembled and linked into my code, and have a HET pin generate a PWM signal.
The program is a little more complex than it can be, because it allows for flexible period - something we can ignore here.
; PWM, 1 channel with buffer field to modulate PWM period L00 CNT { reg=A, irq=OFF, max= 3 } L01 BR { next= L03, cond_addr=L02, event= ZERO } L02 MOV64 { remote= L00, cntl_val= 4, data=0, hr_data=0 } ; CPU to write new period value to control field L03 MCMP { en_pin_action= ON, pin= 4, order= REG_GE_DATA, action= PULSELO, reg=A, data=2, hr_data=64} L04 BR { next= L00, cond_addr=L00, event= NOCOND }
Don't try to understand this unless you want to learn the assembler language. A manual is available from TI's Hercules product page.
The only thing that's interesting for this exercise is knowing that this code will generate a 234 kHz PWM with 50% duty cycle on HET pin 4.
I've chosen PIN 4 deliberately because that matches the stepper pin of the DRV8711 Stepper Driver BoosterPack.
There's a HET IDE that asists you when writing code (and can integrate with a simulator to pre-test your design on a PC).
You can also assemble the code from the IDE. This will generate a .c and a .h file. They will end up in your project in the next step:
Configure Hercules to Run the HET Code
Like the other modules, HET is configured in HALCoGen. First thing to do is enable the driver:
This will take care that HALCoGen creates the driver code for the timer. Then we set the PINMUX so that NHET1 pin 4 is active.
(not really really needed because it's the default assignment for the pin, but it helps finding conflicts later on)
On the NHET module itself, you define the frequency, and say that you want to use HET assembly.
(This module can also be configured as a straightforward PWM generator without programming)
The .h and .c files that we select here are the ones generated by the HET IDE when you pressed the assembler.
When you press the HALCoGen "Generate Code" button later on, thes files will be copied into your Hercules project code.
As a last step in this blog, I'll show how all of this can be scripted so that both the assembly and copy step are automatically done as part of a CCS build.
The last step in the HET configuration pages is to make HET1 pin 4 an output pin:
CCS Project Settings and Automating the Build
I prefer to minimise the number of manual steps when building a firmware binary. If at all possible, no manual steps, so that a build is repeatable.
In this case it is possible because the HET suite for the Hercules come with a command line assembler.
In CCS, you have the option to add commands before or after a build, so that's a perfect location to put these.
I have created my HET IDE project in the het subfolder of the CCS project.
For some reason, the build steps are executed from a folder one level in the project (too lazy to find out which one), so we have to prepend all folders with ..\.
The first line assembles the .het source into .c and .h files in the het folder:
${HET_COMPILER} -n0 -v2 -hc32 ..\het\het.het
The next two lines copy the .h and .c into the HALCoGen project source:
copy /Y ..\het\het.h ..\HALCoGen\include\het.h copy /Y ..\het\het.c ..\HALCoGen\source\het.c
That's all. A little bit of scripting automates the whole thing. The results can be found back in the console after build:
**** Build of configuration Debug for project RM57_Stepper **** "D:\\ti\\ccsv7\\utils\\bin\\gmake" -k -j 8 all -O "D:\Program Files (x86)\Texas Instruments\Hercules\HET IDE\03.05.01\bin\hetp.exe" -n0 -v2 -hc32 ..\het\het.het NHET Assembler Release 1.7 Texas Instruments Incorporated. PASS 1 PASS 2 No Errors, No Warnings copy /Y ..\het\het.h ..\HALCoGen\include\het.h 1 file(s) copied. copy /Y ..\het\het.c ..\HALCoGen\source\het.c 1 file(s) copied. ' ' 'Building file: ../HALCoGen/source/HL_gio.c' 'Invoking: ARM Compiler' ...
I've registered the HET command line tool in a project parameter, so that the script is PC independent:
A last point of attention: if the HET project is a subfolder of your CCS project, you'll have to exclude it from compiling. Else you have the het.c file twice in your build and it'll fail.
Running the HET code
The easiest part. It runs immediately when you initialise the HET module.
// ... #include "HL_het.h" // ... int main(void) { // ... hetInit(); // ...
The oscilloscope grab at the start of the blog is the actual result of running the code of this blog.
In a next blog we'll communicate with the HET sub-controller so that it only generates pulses when we want it, and how we want it.
The end-game is to get a signal like this out of the module, based on a ramp profile that we define.
Top Comments