Страницы

Страницы

воскресенье, 6 августа 2017 г.

STM32F746 Memory Region

MPU_Region_InitTypeDef MPU_InitStruct_SDRAM;
 MPU_Region_InitTypeDef MPU_InitStruct_FPGAKBD;

В 746-м, сразу после настройки FMC, возможен только доступ по четным (выровненным на 4 байта адресам). Для доступа к нечетным адресам надо еще настраивать MPU на эти области адресов. Иначе проц выпадает в Hard Fault exception handler.

 /* Disable the MPU */
 HAL_MPU_Disable();

 /* Configure the MPU attributes as WT for SDRAM */
 MPU_InitStruct_SDRAM.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct_SDRAM.BaseAddress = 0xD0000000;
 MPU_InitStruct_SDRAM.Size = MPU_REGION_SIZE_8MB;

 MPU_InitStruct_SDRAM.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct_SDRAM.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct_SDRAM.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct_SDRAM.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct_SDRAM.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct_SDRAM.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct_SDRAM.SubRegionDisable = 0x00;
 MPU_InitStruct_SDRAM.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct_SDRAM);

 MPU_InitStruct_FPGAKBD.Number = MPU_REGION_NUMBER1;
 MPU_InitStruct_FPGAKBD.BaseAddress = 0x60000000;
 MPU_InitStruct_FPGAKBD.Size = MPU_REGION_SIZE_512MB;

 MPU_InitStruct_FPGAKBD.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct_FPGAKBD.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct_FPGAKBD.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct_FPGAKBD.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct_FPGAKBD.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct_FPGAKBD.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct_FPGAKBD.SubRegionDisable = 0x00;
 MPU_InitStruct_FPGAKBD.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct_FPGAKBD);
 /* Enable the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

Fault Handler processing

#define USART_FLAG_TC ((uint16_t)0x0040)
static __INLINE void ITM_SendChar_My (uint32_t ch)
{
 while( (USART1->ISR & USART_FLAG_TC ) == 0 )
 {
 ;
 }

 USART1->TDR = (ch & (uint16_t)0x01FF);
}

void printErrorMsg(const char * errMsg)
{
 while( *errMsg != 0 )
 {
 ITM_SendChar_My(*errMsg);
 ++errMsg;
 }
}

Restarting UART DMA

Restarting UART DMA using HAL

HAL_DMA_Abort
HAL_UART_DMAStop

and recalling the DMA initialisation routine but it still doesn't restart correctly
add

__HAL_USART_CLEAR_OREFLAG(&huart1);

====================================================

DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1, 3000);
DMA_Cmd(DMA1_Channel1, ENABLE);


1. выключить канал dma
2. записать в CNDTR размер буфера
3. включить dma

при отладке с остановами работаеттолько такой код:

1a. выключить uart
1. выключить канал dma
2. записать в CNDTR размер буфера
2.a записать CCR то что писалось при инициализации
3. включить dma
3a. включить uart

============================================================

void DMA1_Channel4_IRQHandler(void)
{
    DMA1->IFCR |= DMA_ISR_TCIF4;//очистить флаг окончания обмена.
}

========================================================

To start another DMA transaction you should program a transaction length. It can be programmed only when a DMA channel disabled. So in your case code might looks like this:

void DMA1_Channel5_IRQHandler(void) { 
    DMA_ClearITPendingBit(DMA1_IT_TC5);
    DMA_Cmd(DMA1_Channel5, DISABLE);
    DMA1_Channel5->CNDTR = UART_PACKET_SIZE; // <--- transaction length
    DMA_Cmd(DMA1_Channel5, ENABLE);
}
Or you can use your function uart_receive_dma(), but you should disable a DMA channel prior to calling it.

void DMA1_Channel5_IRQHandler(void) { 
    DMA_ClearITPendingBit(DMA1_IT_TC5);
    DMA_Cmd(DMA1_Channel5, DISABLE);
    uart_receive_dma();
}
Second variant will do same thing as first, but will take much more time.

пятница, 4 августа 2017 г.

EmWin skins for buttons.

#include "DIALOG.h"

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define ID_WINDOW_0    (GUI_ID_USER + 0x00)
#define ID_BUTTON_0    (GUI_ID_USER + 0x01)
#define ID_BUTTON_1    (GUI_ID_USER + 0x02)
#define ID_BUTTON_2    (GUI_ID_USER + 0x03)
#define ID_BUTTON_3    (GUI_ID_USER + 0x04)

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
/*********************************************************************
*
*       _aDialogCreate
*/
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  { WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 0, 320, 240, 0, 0x0, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 20, 10, 80, 20, 0, 0x0, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_1, 20, 40, 80, 20, 0, 0x0, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_2, 20, 70, 80, 20, 0, 0x0, 0 },
  { BUTTON_CreateIndirect, "Button", ID_BUTTON_3, 20, 100, 80, 20, 0, 0x0, 0 },
};

static BUTTON_SKINFLEX_PROPS _aProps[] = {
// BUTTON_SKINFLEX_PI_PRESSED
  {
    {GUI_RED, GUI_RED, GUI_DARKRED},
    {GUI_LIGHTRED, GUI_RED },
    {GUI_RED, GUI_DARKRED },
     3
  },
// BUTTON_SKINFLEX_PI_FOCUSSED
  {
    {GUI_DARKRED, GUI_RED, GUI_DARKGRAY},
    {GUI_LIGHTGRAY, GUI_GRAY },
    {GUI_GRAY, GUI_DARKGRAY },
     3
  },
// BUTTON_SKINFLEX_PI_ENABLED
  {
    {GUI_DARKRED, GUI_GRAY, GUI_DARKGRAY},
    {GUI_LIGHTGRAY, GUI_GRAY },
    {GUI_GRAY, GUI_DARKGRAY },
     3
  },
// BUTTON_SKINFLEX_PI_DISABLED
  {
    {0, 0, 0},
    {0, 0 },
    {0, 0 },
     3
  },
};

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _CustomSkin
*/
static int _CustomSkin(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo) {
  int       Id;
  GUI_POINT aPoints[3];
  GUI_COLOR Color;
  BUTTON_SKINFLEX_PROPS aPropsOld[4];
  int i;

  switch (pDrawItemInfo->Cmd) {
  case WIDGET_ITEM_DRAW_BACKGROUND:
    Id = WM_GetId(pDrawItemInfo->hWin);
    switch (Id) {
    case ID_BUTTON_0:
      //
      // Draw an elliptic button
      //
      if (BUTTON_IsPressed(pDrawItemInfo->hWin)) {
        Color = GUI_YELLOW;
      } else {
        Color = GUI_RED;
      }
      GUI_SetColor(Color);
      GUI_FillEllipse(pDrawItemInfo->x1 / 2, pDrawItemInfo->y1 / 2, pDrawItemInfo->x1 / 2 - 1, pDrawItemInfo->y1 / 2 - 1);
      break;
    case ID_BUTTON_1:
      //
      // Draw a triangle button
      //
      aPoints[0].x = pDrawItemInfo->x1 / 2;
      aPoints[0].y = pDrawItemInfo->y0;
      aPoints[1].x = pDrawItemInfo->x1;
      aPoints[1].y = pDrawItemInfo->y1;
      aPoints[2].x = pDrawItemInfo->x0;
      aPoints[2].y = pDrawItemInfo->y1;
      if (BUTTON_IsPressed(pDrawItemInfo->hWin)) {
        Color = GUI_GREEN;
      } else {
        Color = GUI_CYAN;
      }
      GUI_SetColor(Color);
      GUI_FillPolygon(aPoints, GUI_COUNTOF(aPoints), pDrawItemInfo->x0, pDrawItemInfo->y0);
      break;
    case ID_BUTTON_2:
      //
      // Draw a standard button with different colors
      //
      for (i = 0; i < 4; i++) {
        BUTTON_GetSkinFlexProps(&aPropsOld[i], i);  // Get default properties
        BUTTON_SetSkinFlexProps(&_aProps[i], i);    // Set new properties
      }
      BUTTON_DrawSkinFlex(pDrawItemInfo);           // Draw button with new properties
      for (i = 0; i < 4; i++) {
        BUTTON_SetSkinFlexProps(&aPropsOld[i], i);  // Restore old properties to avoid other buttons will be drawn with this properties
      }
      break;
    case ID_BUTTON_3:
      BUTTON_DrawSkinFlex(pDrawItemInfo);
      break;
    }
    return 0;
  default:
    return BUTTON_DrawSkinFlex(pDrawItemInfo);
  }
}

/*********************************************************************
*
*       _cbDialog
*/
static void _cbDialog(WM_MESSAGE * pMsg) {
  WM_HWIN hItem;
  int     NCode;
  int     Id;

  switch (pMsg->MsgId) {
  case WM_INIT_DIALOG:
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
    BUTTON_SetSkin(hItem, _CustomSkin);
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
    BUTTON_SetSkin(hItem, _CustomSkin);
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_2);
    BUTTON_SetSkin(hItem, _CustomSkin);
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_3);
    BUTTON_SetSkin(hItem, _CustomSkin);
    break;
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

WM_HWIN CreateWindow(void);
WM_HWIN CreateWindow(void) {
  WM_HWIN hWin;

  hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
  return hWin;
}

/*********************************************************************
*
*       MainTask
*/
//////////void MainTask(void) {
//////////  //
//////////  // Set flag for automatic use of memory devices. Calling before GUI_Init() makes sure the desktop window uses them, too.
//////////  //
//////////  WM_SetCreateFlags(WM_CF_MEMDEV);
//////////  //
//////////  // Initialize GUI
//////////  //
//////////  GUI_Init();
//////////  GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
//////////  while (1) {
//////////    GUI_Delay(100);
//////////  }
//////////}

четверг, 3 августа 2017 г.

Add CMSIS-RTOS RTX & CubeMX adapt generated files


This section explains how to add the CMSIS-RTOS RTX real-time operating system.

Setup in STM32CubeMX

In STM32CubeMX ensure that the System Tick Interrupt is set to the lowest priority (which is the highest number).

Configuration tab

  • Under System open NVIC Configuration.
  • Click on System tick timer and set Preemption Priority to 15 (highest possible value).
  • Click OK to close the NVIC Configuration dialog.

Setup in MDK

In MDK, the steps to add the CMSIS-RTOS RTX real-time operating system to a project that is configured with STM32CubeMX are:

Step 1: Add CMSIS-RTOS RTX

  • Open the Manage Run-Time Environment window and add CMSIS:RTOS (API):Keil RTX.

rte_bsp_rtx.png

Step 2: Configure CMSIS-RTOS RTX parameters

  • Open the configuration file RTX_Conf_CM.c from the project window, component group CMSIS.
  • Optionally you may change to the Configuration Wizard tab.
  • Change the following settings:
    • Main Thread stack size [bytes] 1024
    • RTOS Kernel Timer input clock frequency [Hz] set to core clock frequency
  • Save the file.

Step 3: Add code for CMSIS-RTOS RTX in 'main.c'

  • Open the source file main.c from the project window, source group STM32CubeMX:Common Sources and add code lines in the sections USER CODE BEGIN / USER CODE END as shown below:
:
/* USER CODE BEGIN Includes */
#include "cmsis_os.h" // ARM::CMSIS:RTOS:Keil RTX
/* USER CODE END Includes */
:
/* USER CODE BEGIN 0 */
extern uint32_t os_time;
uint32_t HAL_GetTick(void) { // Add HAL_GetTick function for STM32Cube HAL
return os_time;
}
/* USER CODE END 0 */
:
int main(void)
{
:
/* USER CODE BEGIN 1 */
osKernelInitialize (); // Initialize RTOS Kernel for setup
/* USER CODE END 1 */
:
/* USER CODE BEGIN 2 */
osKernelStart (); // Begin thread switching
/* USER CODE END 2 */
:

Step 4: Remove SysTick_Handler in stm32f7xx_it.c

  • STM32CubeMX generates a SysTick_Handler that is in-compatible with CMSIS-RTOS RTX. Remove the code for the SysTick_Handler in the source file stm32f7xx_it.c as shown below.
#if 0
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
#endif

Step 5: Build Project in MDK

  • Use Project - Build Target to generate the application code.


The source file generated by STM32CubeMX can be accessed in the MDK project window, source group STM32CubeMX:Common Sources. These file require the following modifications.

Changes to 'stm32fxxx_it.c'

CMSIS-Driver and CMSIS-RTOS RTX implement their own interrupt handlers.
  • For using CMSIS-RTOS RTX remove the code of the SysTick_Handler.
  • For using CMSIS-Driver remove the code of the related Interruption Handler.
Note
STM32CubeMX re-generates this file and it is required to remove the interrupt handlers after using Generate Code.

Changes to 'main.c'

  • CMSIS-Driver initialize peripherals using dedicated functions that are called by middleware. Initialization code in 'main.c' for the related peripherals is therefore not required and may be removed.
  • CMSIS-RTOS RTX requires initialization code. Refer to Add CMSIS-RTOS RTX for detailed information.