Can't access timer 4 pic32 with TMR4, T4CON etc - c

I've looked in the pic32ms.h file and it seems there are no definitions for timer 4. For timer 2 it has the following:
/*
* Timer2 registers
*/
#define T2CON PIC32_R (0x0800)
#define T2CONSET PIC32_R (0x0808)
#define TMR2 PIC32_R (0x0810)
#define PR2 PIC32_R (0x0820)
I've tried adding lines for timer 4 with the correct addresses but it does not solve the problem. So what I want to do instead (if there's no better sollution) is to be able to call the address without using predefined values. Timer 4 has the virtual address 0x0C00 to 0x0C20. How to access these addresses and setup the timer?

The solution was to set the address as a volatile unsigned int pointer which could then be used to access timer 4:
volatile unsigned int *T4CON = 0x****0C00;
However I ended up only using timer 2 by changing the way I handled overflow flags so that it could be detected by different components in the code.

Related

TM4C123G launchpad: How to modify one pin (e.g. PE1) without knowing its GPIO and its position in the byte

Please allow me to clarify the title:
I'm writing a function to connect 16x2 LCD pins to TM4C123G pins. Users should be able to select any TM4C123G pin they want. As the function writer, I need the user to pass the information of that pin to me so that I can connect the pins.
Now I know there are two ways to modify a pin:
Method 1: Reference the full register and AND/OR with a certain value:
// Want to set PE1 to high
#define GPIO_PORTE_DATA_R (*((volatile unsigned long *)0x400243FC))
GPIO_PORTE_DATA_R |= 0x02;
Method 2: Use bit-specific addressing and reference PE1:
// Want to set PE1 to high
#define PE1 (*((volatile unsigned long *)0x40024008))
PE1 = 0x02;
Now consider the function I need to write: the user has to pass two pieces of information to it -- 1) Which GPIO is used (Port E), and 2) Which bit is used (PE1 the second bit from low end).
My question: Is there a way for the user to just pass me a memory address and I can simply set it to 0x01 for high and 0x00 for low?
This is actually a generic question independent of its platform. The solution is also opinion-based. Anyway, below are my suggestions :)
As the user will only manage the GPIO, s/he doesn't need to be aware of the implementation details that cover the control of the underlying peripheral at a lower level. Hence, you may want to hide the implementation details by just providing some basic functions to the user as below
/* Header File */
int enableGpio(int gpioPort, int index);
int disableGpio(int gpioPort, int index);
You can also hide the macros that you use to handle the logic behind the operation by declaring them inside the source file.
/* Source File */
#define GPIO_PORTE_DATA_R (*((volatile unsigned long *)0x400243FC))
#define PE1 (*((volatile unsigned long *)0x40024008))
int enableGpio(int gpioPort, int index) { /* Implementation*/ }
int disableGpio(int gpioPort, int index) { /* Implementation*/ }
I would also recommend using enumerations for declaring GPIO ports instead of integers. By that, you can prevent making undefined calls to your functions.
That's all for now :)

freeRTOS doesn't work properly on atmega32A

I am new to Free RTOS, and I was following some tutorial line by line but things didn't sum up correctly, I used free RTOS to toggle 3 LEDS but it lights just 2 of them without toggling! random 2 LEDs, whatever I change the priorities or the delay time of toggling. random 2 LEDs just switch on and nothing more, I tried the code on proteus simulation and on real hardware and the same problem exists. can someone help me with this?
M/C: ATMEGA32A
RTOS: FreeRTOS
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
/* FreeRTOS files. */
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
#include "FreeRTOSConfig.h"
/* Define all the tasks */
static void ledBlinkingtask1(void* pvParameters);
static void ledBlinkingtask2(void* pvParameters);
static void ledBlinkingtask3(void* pvParameters);
int main(void) {
/* Call FreeRTOS APIs to create tasks, all tasks has the same priority "1" with the
same stack size*/
xTaskCreate( ledBlinkingtask1,"LED1",
configMINIMAL_STACK_SIZE, NULL, 1, NULL );
xTaskCreate( ledBlinkingtask2,"LED2",
configMINIMAL_STACK_SIZE, NULL,1, NULL );
xTaskCreate( ledBlinkingtask3,"LED3",
configMINIMAL_STACK_SIZE, NULL,1, NULL );
// Start the RTOS kernel
vTaskStartScheduler();
/* Do nothing here and just run infinte loop */
while(1){};
return 0;
}
static void ledBlinkingtask1(void* pvParameters){
/* Define all variables related to ledBlinkingtask1*/
const uint8_t blinkDelay = 100 ;
/* make PB0 work as output*/
DDRB |= (1<<0); //PB0
/* Start the infinte task 1 loop */
while (1)
{
PORTB ^= (1<<0); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
static void ledBlinkingtask2(void* pvParameters){
/* Define all variables related to ledBlinkingtask2*/
const uint8_t blinkDelay = 100;
/* make PB1 work as output*/
DDRB |= (1<<1);//PB0
/* Start the infinte task 2 loop */
while (1)
{
PORTB ^= (1<<1); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
static void ledBlinkingtask3(void* pvParameters){
/* Define all variables related to ledBlinkingtask3*/
const uint16_t blinkDelay = 100;
/* make PB2 work as output*/
DDRB |= (1<<2); //PB2
/* Start the infinte task 3 loop */
while (1)
{
PORTB ^= (1<<2); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
ps: every task works well alone but not together!
As already mentioned in comments - the major problem seems to be that access to the port register driving the LEDs is neither
PORTB ^= (1<<0); // in task 1
[...]
PORTB ^= (1<<1); // in task 2
[...]
PORTB ^= (1<<2); // in task 3
atomic
protected (by disabling interrupts during access, or by RTOS measures such as a mutex)
deployed to one unique task:
It may be misleading that the access to HW register is performed using a single instruction in the C code every time.
Still, this doesn't help because the compiler generates several assembler instructions (e.g., load previous port value to register, modify that register value, write it back to the port). This way, one task can interrupt another between those assembler/CPU instructions and modify the intermediate value.
Several tasks writing back "their" register value to the port in turn can revert what other task(s) may have just written to the port, so you miss a blinky event (or several, if this happens systematically).
The solution is therefore to protect the assignments against each other.
In the same order as numbered above, this may mean either of the following:
Check if the hardware offers a "set value" or "reset value" register beside the main PORTB port register. If so, writing a single bit to that port would be an atomic way to have the LED toggle.
I'm sorry that I don't know the hardware interface of Atmega. Maybe, this isn't possible, and you have to go on directly to 2. and 3.
a. Disable interrupts before changing the port register, reenable it afterwards. This way, the task scheduler won't run during that period (= critical section) and nobody disturbs the task that accesses the hardware.
b. Use taskENTER_CRITICAL()/taskEXIT_CRITICAL()
c. Use a mutex or similar.
Create a fourth task which waits (blocking) at a mailbox/queue.
Whenever it receives a value from the mailbox, it processes it (e.g., by XOR-ing it to the port register).
The three existing tasks don't access the LED port register themselves, but instead send such a value (= request message) to the new task.
Assign a higher priority to the new task in order to get a smooth blinking pattern.
If option 1. is possible on your controller, it is fastest (but it requires certain features in the hardware platform...). Otherwise, I agree with the hint from #Richard, option 2.b. are fastest (2.a. is as fast, but not as clean because you break the layering of the FreeRTOS lib).
Option 2.c. may introduce a notable overhead, and option 3. is very clean but a complete overkill in your situation: If your question is really only about blinking LEDs, please leave the bulldozer inside the garage and choose option 2.

ws2812b on ATTiny85

I have ATTiny with 1MHz clock. I'm trying to light up some ws2812b led strip. I conected everything without any resistors and capacitors. I think everything should works but it doesn't :)
I'm useing light_ws2812 library https://github.com/cpldcpu/light_ws2812.
Below is example code. I have hanged only F_CPU frequency, numper of output pin and reset time in config file. Could You help me find the problem and advice how can I fix it?
MAIN
#define F_CPU 1000000
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "ws2812_config.h"
#include "light_ws2812.h"
struct cRGB led[2];
int main(void)
{
uint8_t pos=0;
uint8_t direction=1;
uint8_t i;
#ifdef __AVR_ATtiny10__
CCP=0xD8; // configuration change protection, write signature
CLKPSR=0; // set cpu clock prescaler =1 (8Mhz) (attiny 4/5/9/10)
#endif
led[0].r=255;led[0].g=00;led[0].b=00; // LED 0 is red
led[1].r=255;led[1].g=16;led[1].b=16; // LED 1 is White
while(1)
{
for (i=0; i<pos; i++)
ws2812_sendarray((uint8_t *)&led[0],3); // Repeatedly send "red" to the led string.
// No more than 1-2µs should pass between calls
// to avoid issuing a reset condition.
for (i=0; i<(16-pos); i++)
ws2812_sendarray((uint8_t *)&led[1],3); // white
_delay_ms(50); // Issue reset and wait for 50 ms.
pos+=direction;
if ((pos==16)||(pos==0)) direction=-direction;
}
}
CONFIG
/*
* light_ws2812_config.h
*
* v2.4 - Nov 27, 2016
*
* User Configuration file for the light_ws2812_lib
*
*/
#ifndef WS2812_CONFIG_H_
#define WS2812_CONFIG_H_
///////////////////////////////////////////////////////////////////////
// Define Reset time in µs.
//
// This is the time the library spends waiting after writing the data.
//
// WS2813 needs 300 µs reset time
// WS2812 and clones only need 50 µs
//
///////////////////////////////////////////////////////////////////////
#define ws2812_resettime 50
///////////////////////////////////////////////////////////////////////
// Define I/O pin
///////////////////////////////////////////////////////////////////////
#define ws2812_port B // Data port
#define ws2812_pin 3 // Data out pin
#endif /* WS2812_CONFIG_H_ */
I think 1Mhz is just too slow to be able to generate the signals required by the WS2812B.
The most timing critical WS2812B signal - the TH0 pulse - must be less than 500ns wide, and at 1Mhz, each MCU cycle is 1000ns.
More info on the the WS2812B timing constraints here...
https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
Series resistors and parallel capacitors do help decrease noise that causes inexplicable behavior. But you're right, it should not stop the WS2812bs from working completely.
I suggest you try another pin on your attiny. Pin 3 is used for usb communication. If you are powering your attiny through a usb cable connected to your computer this will cause trouble. Try pins 5 and 6 for example.
You can try the Adafruit_NeoPixel library. I tried and it compiled for attiny85 without modification. I did not actually try to run it since I do not have an attiny lying around.
Also, some of the cheaper WS2812b ledstrips that are around on ebay got their Din and Dout labels switched. This means you have to connect the Dout pin to your attiny. This has actually happened to me once.
I don't know about pulse lenghts in WS2812bs but if that is not the issue I'm pretty sure it's one of the three I mentioned above.
Hope that helps.
[Solution]
According to README I've included config file before header in my MAIN source code file. It was a mistake because the two files are part of different compilation units and DEFINEs are not shared between them. It causes that my configuration settings was ignored and program used default (not correct in my case) ones.
To fix this bug You should include Your ws2812_config.h within light_ws2812.h
You should use the library FASTLED,you can download it on arduino ide .It's very easy to light WS2812 with ATTINY85 by using this library.

GameBoy compiler with system registers and interrupts

I have been spending a lot of time learning GameBoy programming, as I was already familiar with Z80 Assembly I wasn't afraid of jumping into using it. I would (of course) find it much more productive to program in C or C++ however cannot find a full compiler for the GameBoy, the compilers I can find manage everything themselves and do not give access to system registers to the programmer and also have some horrible drawbacks such as 100% CPU utilization and no interrupt support.
Would it be possible to address system registers much like Arduino's AVR compiler? being able to address a CPU or system register simply with its name such as DDRD = %10101011
What would I have to do to add interrupts and system registers into a compiler? All but one system register are only one byte memory addresses and interrupts vectors are of course memory locations, the only one system register that isn't a memory address can only be modified with two Assembly instructions EI and DI but that could be inline functions correct?
The usual tactic is to create your own pointers to system registers. I don't know the address of DDRD, but something like this should to the trick:
volatile unsigned char *reg_DDRD = (unsigned char *)0xE000;
*reg_DDRD = 0xAB;
Most C compilers don't support binary constants but you can use them with some macro hackery. And you can use macros to make slightly more intuitive syntax:
#define DDRD (*reg_DDRD)
DDRD = 0xAB;
There's no sense in modifying the compiler when vanilla C code can work just as well.
Handling interrupts comes down to solving 3 problems. The first is to have the interrupt vector address do a jump to a C function. As that is in ROM you'll need to modify the C runtime environment to initialize that. This gets pretty system dependent, but usually what you'll want to do is add an assembly language file that looks like this:
org 38h ; or wherever the gameboy CPU jumps to on interrupt
jp _intr_function
This should cause the CPU to go to intr_function() in your C program. You may or may not need the leading underscore. And you may not be able to set the destination address in the assembler file with org but instead have to fool around with the linker and sections.
The second problem is that the C function won't necessarily save all the registers it should. You can do this by adding in-line assembly to it, along these lines:
void intr_function()
{
asm(" push af");
asm(" push bc");
asm(" push de");
asm(" push hl");
// ... now do what you like here.
asm(" pop hl");
asm(" pop de");
asm(" pop bc");
asm(" pop af");
}
Finally, the interrupt may have to be acknowledged by manipulating a hardware register. But you can do that in the C code so nothing special about that.
I'm not clear about the issue with wait loops. Standard C compilers don't have such a feature built in. They call main() and if you want to loop it is up to you. It is true that the C-like language used in the Arduino SDK has its own built-in infinite loop that calls the functions you write, but that's not normal C.
First off, you can use GBDK, which is a C compiler and library for the Gameboy. It does provide access to the registers in gb/hardware.h (but that isn't listed in the doc file, since there's no comment for each individual register). It also supplies access to interrupts via methods in gb/gb.h: add_VBL, add_LCD, add_TIM, add_SIO, and add_JOY. (There's also remove methods named remove_).
For reference and/or your own use, here's the contents of gb/hardware.h:
#define __REG volatile UINT8 *
#define P1_REG (*(__REG)0xFF00) /* Joystick: 1.1.P15.P14.P13.P12.P11.P10 */
#define SB_REG (*(__REG)0xFF01) /* Serial IO data buffer */
#define SC_REG (*(__REG)0xFF02) /* Serial IO control register */
#define DIV_REG (*(__REG)0xFF04) /* Divider register */
#define TIMA_REG (*(__REG)0xFF05) /* Timer counter */
#define TMA_REG (*(__REG)0xFF06) /* Timer modulo */
#define TAC_REG (*(__REG)0xFF07) /* Timer control */
#define IF_REG (*(__REG)0xFF0F) /* Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL */
#define NR10_REG (*(__REG)0xFF10) /* Sound register */
#define NR11_REG (*(__REG)0xFF11) /* Sound register */
#define NR12_REG (*(__REG)0xFF12) /* Sound register */
#define NR13_REG (*(__REG)0xFF13) /* Sound register */
#define NR14_REG (*(__REG)0xFF14) /* Sound register */
#define NR21_REG (*(__REG)0xFF16) /* Sound register */
#define NR22_REG (*(__REG)0xFF17) /* Sound register */
#define NR23_REG (*(__REG)0xFF18) /* Sound register */
#define NR24_REG (*(__REG)0xFF19) /* Sound register */
#define NR30_REG (*(__REG)0xFF1A) /* Sound register */
#define NR31_REG (*(__REG)0xFF1B) /* Sound register */
#define NR32_REG (*(__REG)0xFF1C) /* Sound register */
#define NR33_REG (*(__REG)0xFF1D) /* Sound register */
#define NR34_REG (*(__REG)0xFF1E) /* Sound register */
#define NR41_REG (*(__REG)0xFF20) /* Sound register */
#define NR42_REG (*(__REG)0xFF21) /* Sound register */
#define NR43_REG (*(__REG)0xFF22) /* Sound register */
#define NR44_REG (*(__REG)0xFF23) /* Sound register */
#define NR50_REG (*(__REG)0xFF24) /* Sound register */
#define NR51_REG (*(__REG)0xFF25) /* Sound register */
#define NR52_REG (*(__REG)0xFF26) /* Sound register */
#define LCDC_REG (*(__REG)0xFF40) /* LCD control */
#define STAT_REG (*(__REG)0xFF41) /* LCD status */
#define SCY_REG (*(__REG)0xFF42) /* Scroll Y */
#define SCX_REG (*(__REG)0xFF43) /* Scroll X */
#define LY_REG (*(__REG)0xFF44) /* LCDC Y-coordinate */
#define LYC_REG (*(__REG)0xFF45) /* LY compare */
#define DMA_REG (*(__REG)0xFF46) /* DMA transfer */
#define BGP_REG (*(__REG)0xFF47) /* BG palette data */
#define OBP0_REG (*(__REG)0xFF48) /* OBJ palette 0 data */
#define OBP1_REG (*(__REG)0xFF49) /* OBJ palette 1 data */
#define WY_REG (*(__REG)0xFF4A) /* Window Y coordinate */
#define WX_REG (*(__REG)0xFF4B) /* Window X coordinate */
#define KEY1_REG (*(__REG)0xFF4D) /* CPU speed */
#define VBK_REG (*(__REG)0xFF4F) /* VRAM bank */
#define HDMA1_REG (*(__REG)0xFF51) /* DMA control 1 */
#define HDMA2_REG (*(__REG)0xFF52) /* DMA control 2 */
#define HDMA3_REG (*(__REG)0xFF53) /* DMA control 3 */
#define HDMA4_REG (*(__REG)0xFF54) /* DMA control 4 */
#define HDMA5_REG (*(__REG)0xFF55) /* DMA control 5 */
#define RP_REG (*(__REG)0xFF56) /* IR port */
#define BCPS_REG (*(__REG)0xFF68) /* BG color palette specification */
#define BCPD_REG (*(__REG)0xFF69) /* BG color palette data */
#define OCPS_REG (*(__REG)0xFF6A) /* OBJ color palette specification */
#define OCPD_REG (*(__REG)0xFF6B) /* OBJ color palette data */
#define SVBK_REG (*(__REG)0xFF70) /* WRAM bank */
#define IE_REG (*(__REG)0xFFFF) /* Interrupt enable */
These are done in the same way as George Phillips's answer, and thus can be used like normal variables.
The code that is used by GBDK to add and remove interrupts is found in libc\gb\crt0.s, but I don't know enough of assembly to include the relevant sections in this post.
I'm not sure about how to avoid the busy loop either.

USB Interrupt Masks not loading STM32L151CC

I'm currently encountering a strange issue with the STM USB libraries. I am able to successfully load firmware onto the STM32L152D-EVAL board (which uses an STM32L152ZD), however, I am unable to modify the same code to work on my form-factor board, which uses the aforementioned STM32L151CC.
After stepping through the code with the debugger (a ULINK2, using the KEIL uVision4 IDE), I noticed that the code would crash while setting the interrupt mask in the function USB_SIL_Init()
uint32_t USB_SIL_Init(void)
{
/* USB interrupts initialization */
/* clear pending interrupts */
_SetISTR(0);
wInterrupt_Mask = IMR_MSK;
/* set interrupts mask */
_SetCNTR(wInterrupt_Mask);
return 0;
}
More specifically, _SetCNTR(wInterrupt_Mask); is what gives me the error. I haven't changed the value of IMR_MSK between either board. It's value is given as
#define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM | CNTR_SOFM \
| CNTR_ESOFM | CNTR_RESETM )
which is 0xBF00
_SetCNTR is defined as follows
#define _SetCNTR(wRegValue) (*CNTR = (uint16_t)wRegValue)
With CNTR being defined as
/* Control register */
#define CNTR ((__IO unsigned *)(RegBase + 0x40))
And RegBase is
#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */
I'm currently looking through STM's documentation on this, but I can't seem to find anything specifically relating to the default states for the two different chips. I'm guessing it has something to do with the base address, however the Datasheet shows that this is the correct address.
Can anyone help me out on this?
Thanks!

Resources