Jump to content

Use gfxSleepMilliseconds() with ARM M3 Core (STM32F103)


Recommended Posts

Posted

I tested the gfxSleepMilliseconds function with the following code

int main(void)
{
GPIO_Configuration();

/* SystemCoreClock is 72000000Hz (72MHz) */
/* Set the HCLK Clock as SysTick clock source (72MHz) and Setup SysTick Timer for 1 msec interrupts */
SysTick_Config(SystemCoreClock / 1000);

// Initialize and clear the display
gfxInit();

while(TRUE)
{
LED1 = 1; // Turn on LED 1.
LED2 = 0; // Turn off LED 2.
gfxSleepMilliseconds(1000); // Wait 1 Sec;
LED1 = 0; // Turn off LED 1.
LED2 = 1; // Turn on LED 2.
gfxSleepMilliseconds(1000);
}
}

/**
* @brief Gets a "tick" time from the hardware.
* @param None
* @retval a "tick" time
*/
systemticks_t gfxSystemTicks(void)
{
return SysTick->VAL;
}

/**
* @brief Converts a number of milliseconds to a number of ticks.
* @param None
* @retval number of ticks
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms)
{
return ms;
}

No LED blinking

With this code LED blinking

int main(void)
{
GPIO_Configuration();

while(TRUE)
{
LED1 = 1; // Turn on LED 1.
LED2 = 0; // Turn off LED 2.
Delay(5000);
LED1 = 0; // Turn off LED 1.
LED2 = 1; // Turn on LED 2.
Delay(5000);
}
}

void Delay(uint16_t time)
{
uint16_t i,j;
for(i=time;i>0;i--)
{
for(j=500;j>0;j--);
}
}

Do you have an idea why the LEDs do not blink with the use of gfxSleepMilliseconds()?

Posted

Delay () won't work as part of the implementation of gfxsleepmilliseconds () because it doesn't allow anything else to happen while sleeping.

I suspect the tick timer has not been initialised correctly.

As a simple test write a loop that gets the tick value and when it has increased by 1000 then it toggles the leds.

Is the tick counter even updating?

Posted

inmarket, it seems that you are right when you say I suspect the tick timer has not been initialised correctly.

I took the code of gfxSleepMilliseconds() in the following way

void TestgfxSleepMilliseconds(delaytime_t ms)
{
systemticks_t currenttm, starttm, delay;

// Convert delay to ticks
delay = gfxMillisecondsToTicks(ms);
starttm = gfxSystemTicks();

do { currenttm = gfxSystemTicks(); }
while (currenttm - starttm < delay);
}

I do not know why the value in currenttm is always less than the value in starttm !

With this test that handle SysTick it's OK

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_conf.h"

// https://bitbucket.org/Tectu/ugfx/src/a61b4a71159f?at=master
#include "gfx.h"
#include "hardware.h"

/* Private function prototypes -----------------------------------------------*/
systemticks_t gfxSystemTicks(void);
systemticks_t gfxMillisecondsToTicks(delaytime_t ms);

// LED Definitions
#define LED1 PAout(2) // on the board corresponds to LED1
#define LED2 PAout(3) // on the board corresponds to LED2

void GPIO_Configuration(void);

void TestgfxSleepMilliseconds(delaytime_t ms);

void mygfxSleepMilliseconds(volatile uint32_t nTime);
void SysTick_Handler(void);

static volatile uint32_t TimingDelay;


/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
coord_t width, height;

/* SystemCoreClock is 72000000Hz (72MHz) */
/* Setup SysTick Timer for 1 msec interrupts */
while(SysTick_Config(SystemCoreClock / 1000));

GPIO_Configuration();

// Initialize and clear the display
//gfxInit();

// Get the screen size
//width = gdispGetWidth();
//height = gdispGetHeight();

//gdispClear(Green);

while(TRUE)
{
LED1 = 1; // Turn on LED 1.
LED2 = 0; // Turn off LED 2.
// Wait 1 Sec
mygfxSleepMilliseconds(1000); // OK
//TestgfxSleepMilliseconds(1000); // KO
LED1 = 0; // Turn off LED 1.
LED2 = 1; // Turn on LED 2.
mygfxSleepMilliseconds(1000);
}
}

void TestgfxSleepMilliseconds(delaytime_t ms)
{
systemticks_t currenttm, starttm, delay;

// Convert delay to ticks
delay = gfxMillisecondsToTicks(ms);
starttm = gfxSystemTicks();

do { currenttm = gfxSystemTicks(); }
while (currenttm - starttm < delay); // Sick ! currenttm is always < starttm, Why ?
}

void mygfxSleepMilliseconds(volatile uint32_t nTime)
{
TimingDelay = nTime;

while(TimingDelay != 0);
}

/**
* @brief This function handles SysTick Handler.
* @param None
* @retval : None
*/
void SysTick_Handler(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}

/**
* @brief Configure IO port.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // enable port, it is important! ! !

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Configure LED1, LED2 pin functions
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // universal push-pull output
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // maximum output frequency is 50MHz
GPIO_Init (GPIOA, & GPIO_InitStructure); // initialization PA2, PA3
}

/**
* @brief Gets a "tick" time from the hardware.
* @param None
* @retval a "tick" time
*/
systemticks_t gfxSystemTicks(void)
{
return SysTick->VAL;
}

/**
* @brief Converts a number of milliseconds to a number of ticks.
* @param None
* @retval number of ticks
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms)
{
return ms;
}

Posted

Simple replacement method...

In your systick_Config handler function just increment a volatile uint32_t variable.

gfxSystemTicks should then just return that variable.

gfxsleepmilliseconds should then work.

Posted

I do this

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_conf.h"

// https://bitbucket.org/Tectu/ugfx/src/a61b4a71159f?at=master
#include "gfx.h"
#include "hardware.h"

/* Private function prototypes -----------------------------------------------*/
systemticks_t gfxSystemTicks(void);
systemticks_t gfxMillisecondsToTicks(delaytime_t ms);

// LED Definitions
#define LED1 PAout(2) // on the board corresponds to LED1
#define LED2 PAout(3) // on the board corresponds to LED2

void GPIO_Configuration(void);

void TestgfxSleepMilliseconds(delaytime_t ms);
void SysTick_Handler(void);

static volatile uint32_t TimingDelay = 0;


/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/* Setup STM32 system (clock, PLL and Flash configuration) */
SystemInit();

/* Enable port GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG
| RCC_APB2Periph_AFIO | RCC_APB2Periph_ADC1, ENABLE);

/* DMA1 and DMA2 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_DMA2, ENABLE);

/* SystemCoreClock is 72000000Hz (72MHz) */
/* Setup SysTick Timer for 1 msec interrupts */
while(SysTick_Config(SystemCoreClock / 1000));

GPIO_Configuration();

while(TRUE)
{
LED1 = 1; // Turn on LED 1.
LED2 = 0; // Turn off LED 2.
// Wait 1 Sec
TestgfxSleepMilliseconds(1000); // OK
gfxSleepMilliseconds(1000); // KO no Return

LED1 = !LED1; // Turn off LED 1.
LED2 = !LED2; // Turn on LED 2.
TestgfxSleepMilliseconds(1000);
}
}

void TestgfxSleepMilliseconds(delaytime_t ms)
{
systemticks_t currenttm, starttm, delay;

// Convert delay to ticks
delay = gfxMillisecondsToTicks(ms);
starttm = gfxSystemTicks();

do { currenttm = gfxSystemTicks(); }
while (currenttm - starttm < delay);
}

/**
* @brief This function handles SysTick Handler.
* @param None
* @retval : None
*/
void SysTick_Handler(void)
{
TimingDelay++;
}

/**
* @brief Configure IO port.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Configure LED1, LED2 pin functions
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // universal push-pull output
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // maximum output frequency is 50MHz
GPIO_Init (GPIOA, & GPIO_InitStructure); // initialization PA2, PA3
}

/**
* @brief Gets a "tick" time from the hardware.
* @param None
* @retval a "tick" time
*/
systemticks_t gfxSystemTicks(void)
{
return TimingDelay;
}

/**
* @brief Converts a number of milliseconds to a number of ticks.
* @param None
* @retval number of ticks
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms)
{
return ms;
}

It's OK with me test function TestgfxSleepMilliseconds() but KO with gfxSleepMilliseconds()

gfxSleepMilliseconds(...) can't return.

This seems to be in gfxYield() function in this line

void gfxYield(void) {
if (!_setjmp(current->cxt)) { .....

Rem : I use the bare metal port without any underlying OS.

Posted

You must still do the gfxinit () call as that initialises the code that gfxYield uses.

At least you now know you have valid gfxSystemTicks and gfxMillisecondsToTicks functions.

Posted

Yep with the gfxinit () call, It's OK 8-)

Thanks for your help.

Final source code :

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_conf.h"

// https://bitbucket.org/Tectu/ugfx/src/a61b4a71159f?at=master
#include "gfx.h"
#include "hardware.h"

/* Private function prototypes -----------------------------------------------*/
systemticks_t gfxSystemTicks(void);
systemticks_t gfxMillisecondsToTicks(delaytime_t ms);

// LED Definitions
#define LED1 PAout(2) // on the board corresponds to LED1
#define LED2 PAout(3) // on the board corresponds to LED2

void GPIO_Configuration(void);
void SysTick_Handler(void);

static volatile uint32_t TimingDelay = 0;


/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/* Setup STM32 system (clock, PLL and Flash configuration) */
SystemInit();

/* Enable port GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG
| RCC_APB2Periph_AFIO | RCC_APB2Periph_ADC1, ENABLE);

/* DMA1 and DMA2 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_DMA2, ENABLE);


/* SystemCoreClock is 72000000Hz (72MHz) */
/* Setup SysTick Timer for 1 msec interrupts */
while(SysTick_Config(SystemCoreClock / 1000));

GPIO_Configuration();

// Initialize UGfx
gfxInit();

while(TRUE)
{
LED1 = 1; // Turn on LED 1.
LED2 = 0; // Turn off LED 2.
gfxSleepMilliseconds(1000); // Wait 1 Sec;

LED1 = !LED1; // Turn off LED 1.
LED2 = !LED2; // Turn on LED 2.
gfxSleepMilliseconds(1000); // Wait 1 Sec;
}
}

/**
* @brief This function handles SysTick Handler.
* @param None
* @retval : None
*/
void SysTick_Handler(void)
{
TimingDelay++;
}

/**
* @brief Configure IO port.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Configure LED1, LED2 pin functions
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // universal push-pull output
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // maximum output frequency is 50MHz
GPIO_Init (GPIOA, & GPIO_InitStructure); // initialization PA2, PA3
}

/**
* @brief Gets a "tick" time from the hardware.
* @param None
* @retval a "tick" time
*/
systemticks_t gfxSystemTicks(void)
{
return TimingDelay;
}

/**
* @brief Converts a number of milliseconds to a number of ticks.
* @param None
* @retval number of ticks
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms)
{
return ms;
}

  • 1 year later...
Posted (edited)

Hello guys!)

Could somebody clearly explain what these two functions should do:

systemticks_t gfxSystemTicks(void){}

and

systemticks_t gfxMillisecondsToTicks(delaytime_t ms){}

 

/*

I'm using STM32 MCU with its awkward-to-handle HAL. And trying to build bare hardware)) project from this article:

https://wiki.ugfx.io/index.php/Using_Keil_µVision_5_MDK-ARM

*/

In HAL this function: HAL_GetTick() returns ticks, One tick == one millisecond.

It is obvious from this code - look file stm32fXxx_hal.c:

**
  * @brief This function provides accurate delay (in milliseconds) based 
  *        on variable incremented.
  * @note In the default implementation , SysTick timer is the source of time base.
  *       It is used to generate interrupts at regular time intervals where uwTick
  *       is incremented.
  * @note ThiS function is declared as __weak to be overwritten in case of other
  *       implementations in user file.
  * @param Delay: specifies the delay time length, in milliseconds.
  * @retval None
  */
__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}

It will be the same for any STM32 MCU.

So I try to implement it like this:

systemticks_t gfxSystemTicks(void){
        return ((systemticks_t)(HAL_GetTick()));
    }
        
    systemticks_t gfxMillisecondsToTicks(delaytime_t ms){
        return ((systemticks_t)ms);
    }

Because I suppose that 'gfxSystemTicks' provides system time for GUI library.

And 'gfxMillisecondsToTicks' converts some mysterious internal GUI ticks into millisecond.

I can compare this with emWin - there was just one variable 'extern volatile GUI_TIMER_TIME OS_TimeMS;'

that you should increment every millisecond. It serves for emWin like a command to refresh screen.

 

B.R. Constantine

 

 

Edited by Joel Bodenmann
Using CodeBox
Posted

What you have done is correct.

The problem with the emWin approach is that not all hardware can generate a millisecond counter. Eg Old x86 hardware uses a 18.2ms hardware tick. Using the emWin strategy prevents easy use on that type of hardware.

UGFX however overcomes that by not assuming that a tick is 1ms. It doesn't even need a regular hardware tick interrupt thereby enabling use on tickless hardware and operating systems eg Chibios in tickless mode. All it requires is the ability to measure time in some arbitrary manner through the use of a function call, and a way to translate between that arbitrary time measure and milliseconds.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...