суботу, 24 квітня 2021 р.

Встановлення ModusToolbox та перший проект на CY8CKIT-149 PSoC® 4100S Plus Prototyping Kit

Передмова

На фоні різкого здорожчання чипів STM32, та їх дефіциту, на часі розглянути якісь альтернативи. Звісно, тієї ж вагової категорії. Це має бути 32 розрядний MCU, та архітектури ARM. Пропоную до вашої уваги дошку розробника KIT Prototyping CY8CKIT-149 PSoC4 від компанії Cypress + Infineon. Розписувати характеристики і опис дублюючи документацію - не бачу сенсу. Можете самі перейти за наданими ланками і ознайомитись більш детально. 

CY8CKIT-149 PSoC® 4100S Plus Prototyping Kit


Мета цієї статті:

  • показати як встановити засіб розробки Eclipse ModusToolBox IDE
  • створення проекту "Hello, World" для ознайомлення з процесом розробки

Встановлення ModusToolbox

Перейдіть за ланкою, щоб завантажити ModusToolbox, та оберіть вашу операційну систему. ModusToolBox доступний для Windows, Linux, macOS. Ну звісно, це ж Eclips :)
Після завантаження, встановіть ModusToolBox. 

Встановлення без особливостей, достатньо:

  1. тиснути "Next"
  2. погодитись з ліцензійною угодою
  3. залишити шлях встановлення за замовчуванням, або вказати свій шлях (шлях не має містити кирилічні символи)
  4. обрати тип інсталяції "Default installation"
  5. кнопкою "Finish" завершити інсталяцію та запускаємо ModusToolBox
Завершення встановлення

Оберіть свій WorkSpaces, тека де будуть зберігатись ваші проекти, або залиште як є:

Обираємо шлях workspaces

Тиснемо кнопку "Launch" і перейдемо до створення першого проекту "Hello World" надрукуємо текстовий рядок в серіал порт та поблимаємо світлодіодами. А світлодіодів на цій платі розробника дуже багато :)

Створення нового проекту

Створення нового проекту
Створення нового проекту:
  1. На панелі швидкого доступу "Quick panel"
  2. Тиснемо "New Application". Запуститься утіліта "Project Creator"
  3. Обираємо свою дошку розробника "CY8CKIT-149" з чипом CY8C4147AZI-S475
  4. Тиснемо кнопку "Next"
Обираємо приклад з репозиторію

    5. Переконаємось чи вірний шлях
    6. Оберемо приклад "Hello World"
    7. Та назвемо його "PSoC4_Hello_World"
    8. Ознайомимось з описом прикладу
    9. Підсумуємок, що створили
    10. Тиснемо кнопку "Create"

Структура проекту

Коли проект створиться, то в "Workspaces" створяться дві теки "mtb_shared" з бібліотеками, які будуть доступні всім проектам в цьому "Workspaces" та тека, власне, з самим проектом. В нашому випадку це "PSoC4_Hello_World":

Структура проекту

  1. mtb_shared - тека з бібліотеками, які доступні будь якому проекту в цьому workspaces
  2. pdl (peripheral driver library) та hal (high abstraction level) бібліотеки
  3. PSoC4_Hello_World - тека з проектом який ми створили
  4. COMPONENT_CUSTOM_DESING_MODUS - тека яка стосується утіліти Device Manager. Про це в наступних статтях.
  5. Файл main.c - тут і будемо дивитись/писати код
  6. Панель швидкого доступу. Ознайомимиось з нею нижче.

Панель швидкого доступу

Для кожного проекту в "workspaces" викликається своя панель швидкого доступу. Де можна  швидко знайти всі необхідні речі для роботи над цим проектом:

Панель швидкого доступу

  1. Побудувати і очистити проект
  2. Запустити відладку або просто залити прошивку за допомоги Jlink або KitProg3
  3. Викликати утіліти, наприклад Library Manager, Device Configurator, тощо
  4. Та швидкий доступ до документації на саму дошку розробника, всіх бібліотек, що дуже зручно

Приклад Hello World

Подвійним кліком на файлі main.c відкриємо файл на редагування, та перш за все, пропоную побудувати проект, натиснувши в панелі швидкого доступу "Quick panel" -> "Build PSoC4_Hello_World Application". Це для того щоб переконатись що з проектом все гаразд і всі файли створились як слід, та щоб всі інклюди, змінні, функції, дефайни і таке інше проіндесувались. Як приклад зібрався без помилок, тиснемо на панелі швидкого доступу "PSoC4_Hello_World program (KitProg3_MiniProg4)". Прошивка заллється до мікроконтролеру і почне працювати. В серіал порт один раз надішлеться текстове повідомлення "Hello World", та почне блимати набортний світлодіод.

Сам файл main.c виглядає так. Він, приклад, побудований на бібліотеці PDL, більш низького рівня чим HAL бібліотека.

/******************************************************************************
* File Name: main.c
*
* Description: This is the source code for the PSoC 4 MCU Hello World Example
*              for ModusToolbox.
*
* Related Document: See README.md
*
*******************************************************************************
* (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
*******************************************************************************
* This software, including source code, documentation and related materials
* ("Software"), is owned by Cypress Semiconductor Corporation or one of its
* subsidiaries ("Cypress") and is protected by and subject to worldwide patent
* protection (United States and foreign), United States copyright laws and
* international treaty provisions. Therefore, you may use this Software only
* as provided in the license agreement accompanying the software package from
* which you obtained this Software ("EULA").
*
* If no EULA applies, Cypress hereby grants you a personal, non-exclusive,
* non-transferable license to copy, modify, and compile the Software source
* code solely for use in connection with Cypress's integrated circuit products.
* Any reproduction, modification, translation, compilation, or representation
* of this Software except as specified above is prohibited without the express
* written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress
* reserves the right to make changes to the Software without notice. Cypress
* does not assume any liability arising out of the application or use of the
* Software or any product or circuit described in the Software. Cypress does
* not authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ("High Risk Product"). By
* including Cypress's product in a High Risk Product, the manufacturer of such
* system or application assumes all risk of such use and in doing so agrees to
* indemnify Cypress against all liability.
*******************************************************************************/


/*******************************************************************************
 * Include header files
 ******************************************************************************/
#include "cy_pdl.h"
#include "cybsp.h"


/*******************************************************************************
* Macros
*******************************************************************************/
#define LED_DELAY_MS              (500u)
#define CY_ASSERT_FAILED          (0u)


/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
*  System entrance point. This function performs
*  - initial setup of device
*  - configure the SCB block as UART interface
*  - prints out "Hello World" via UART interface
*  - Blinks an LED under firmware control at 1 Hz
*
* Parameters:
*  none
*
* Return:
*  int
*
*******************************************************************************/
int main(void)
{
    cy_rslt_t result;
    cy_stc_scb_uart_context_t CYBSP_UART_context;

    /* Initialize the device and board peripherals */
    result = cybsp_init();

    /* Board init failed. Stop program execution */
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(CY_ASSERT_FAILED);
    }

    /* Configure and enable the UART peripheral */
    Cy_SCB_UART_Init(CYBSP_UART_HW, &CYBSP_UART_config, &CYBSP_UART_context);
    Cy_SCB_UART_Enable(CYBSP_UART_HW);

    /* Enable global interrupts */
    __enable_irq();

    /* Send a string over serial terminal */
        Cy_SCB_UART_PutString(CYBSP_UART_HW, "Hello world\r\n");

    for(;;)
    {
        /* Toggle the user LED state */
        Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN);

        /* Wait for 0.5 seconds */
        Cy_SysLib_Delay(LED_DELAY_MS);
    }
}

/* [] END OF FILE */

Пропоную ознайомитись з задіяними в цьому прикладі функціями та структурами. Як побудоване налаштування пінів і периферії. Спробувати внести в приклад свої зміни. Ознайомитись з результатами, своїх внесків в код, шляхом заливки оновленої прошивки.

Ще я підготував відео в підтримку до цієї статті, де покажу як встановити "ModusToolBox", створю пустий проект, та напишу більш цікавий приклад мікроконтролерного "Hello World", за допомоги, вже, HAL бібліотек.

Відео версія статті





пʼятницю, 8 січня 2021 р.

Запускаємо FreeRTOS на ESP32. Створення задач. Видалення задач. Призупинення виконання задачі і її відновлення. Семафори MUTEX - справжня бійня за периферію

 Передмова


Оволодіння вмінням працювати з FreeRTOS надає великі переваги в проектах на мікроконтролерах. Двох-ядерний  мікроконтролер ESP32 дозволяє з легкістю спробувати цю операційну систему для мікроконтролерів. Складемо макет та напишемо невеличкий приклад коду. Де будемо надсилати дані для різних пристроїв по одному SPI з різних задач, використаємо семафор, створимо декілька задач, призупинимо/відновимо роботу задачі, видалимо задачу з пам'яті.

Приклад

Складіть макет схеми як на малюнку. Створімо новий проект в Platformio, дамо проекту назву "ESP32_HC595_MAX7219_FreeRTOS". Для роботи з драйвером "max7219" завантажте цю бібліотеку, та додайте її до свого проекту, який щойно створили. Тепер можемо додати демонстраційний код:

#include <Arduino.h>
#include <SPI.h>
#include "max7219.h"

#define CS_HC595    5
#define CS_MAX7219  15
#define KEY_PIN     0
#define LED_BLUE    2

#define CS_HC595_SET()  digitalWrite(CS_HC595, LOW)
#define CS_HC595_RESET()  digitalWrite(CS_HC595, HIGH)

void Task0(void* parameters);
void Task1(void* parameters);
void Task2(void* parameters);
void Task3(void* parameters);
void Task4(void* parameters);
void Task5(void* parameters);

bool keyFlag = false;
bool task4Active = true;

TaskHandle_t Task2Handle = NULL;

SemaphoreHandle_t mutexSPI;
SemaphoreHandle_t mutexSerial;

Max7219 max7219 = Max7219(CS_MAX7219, 8, 9);

void setup() 
{
  Serial.begin(115200);
  Serial.println("Serial is OK!");
  SPI.begin(18, 21, 23);
  max7219.Begin();

  mutexSPI = xSemaphoreCreateMutex();
  mutexSerial = xSemaphoreCreateMutex();

  xTaskCreate(Task0, "Task0", 2048, NULL, 1, NULL);
  xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, 1, NULL, 0);
  xTaskCreatePinnedToCore(Task2, "Task2", 2048, NULL, 1, &Task2Handle, 1);
  xTaskCreate(Task3, "Task3", 2048, NULL, 2, NULL);
  xTaskCreate(Task4, "Task4", 2048, NULL, 1, NULL);
  xTaskCreate(Task5, "Task5", 2048, NULL, 1, NULL);
}

void loop() 
{
  
}

void Task0(void* parameters)
{
  xSemaphoreTake(mutexSerial, portMAX_DELAY);
  Serial.printf("[%8lu] Run Task0 only once: %d\r\n", millis(), xPortGetCoreID());
  xSemaphoreGive(mutexSerial);

  vTaskDelete(NULL);
}

void Task1(void* parameters)
{
  //TODO: код що виконується раз при запускі задачі
  pinMode(CS_HC595, OUTPUT);
  CS_HC595_RESET();
  
  while (1)
  {
    //TODO: код що виконується безкінечно
    for (size_t i = 0; i < 8; i++)
    {
      xSemaphoreTake(mutexSerial, portMAX_DELAY);
      Serial.printf("[%8lu] Run Task1 on Core: %d\r\n", millis(), xPortGetCoreID());
      xSemaphoreGive(mutexSerial);
      
      xSemaphoreTake(mutexSPI, portMAX_DELAY);
      CS_HC595_SET();
      SPI.transfer(1 << i);
      CS_HC595_RESET();
      xSemaphoreGive(mutexSPI);

      vTaskDelay(500 / portTICK_PERIOD_MS);
    }
  }
}

void Task2(void* parameters)
{
  while (1)
  {
    max7219.Clean();
    max7219.DecodeOn();

    xSemaphoreTake(mutexSerial, portMAX_DELAY);
    Serial.printf("[%8lu] Run Task2 on Core: %d\r\n", millis(), xPortGetCoreID());
    xSemaphoreGive(mutexSerial);
    
    xSemaphoreTake(mutexSPI, portMAX_DELAY);
    max7219.PrintNtos(8, millis(), 8);
    xSemaphoreGive(mutexSPI);

    vTaskDelay(973 / portTICK_PERIOD_MS);
  }  
}

void Task3(void* parameters)
{
  pinMode(KEY_PIN, INPUT);

  while (1)
  {
    if(!digitalRead(KEY_PIN) && !keyFlag)
    {
      keyFlag = true;

      xSemaphoreTake(mutexSerial, portMAX_DELAY);
      Serial.printf("[%8lu] KEY is pressed!\r\n", millis());
      xSemaphoreGive(mutexSerial);      
    }

    if (digitalRead(KEY_PIN) && keyFlag)
    {
      keyFlag = false;

      xSemaphoreTake(mutexSerial, portMAX_DELAY);
      Serial.printf("[%8lu] KEY is unpressed!\r\n", millis());
      xSemaphoreGive(mutexSerial);

      if (task4Active)
      {
        task4Active = false;
        vTaskSuspend(Task2Handle);
      }
      else
      {
        task4Active = true;        
        vTaskResume(Task2Handle);
      }           
    }

    vTaskDelay(50 / portTICK_PERIOD_MS);
  }
  
}

void Task4(void* parameters)
{ 
  uint8_t brightness[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 
                           0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
  
  while (1)
  {
      for (size_t i = 0; i < sizeof(brightness) / sizeof(brightness[0]); i++)
      {
        xSemaphoreTake(mutexSPI, portMAX_DELAY);
        max7219.SetIntensivity(brightness[i]);
        xSemaphoreGive(mutexSPI);

        vTaskDelay(150 / portTICK_PERIOD_MS); 
      }            
  }  
}

void Task5(void* parameters)
{
  ledcSetup(0, 5000, 8);
  ledcAttachPin(LED_BLUE, 0);

  uint8_t n = 0;
  bool direction = false;

  while (1)
  {  
    if (!direction && n == 255)    
    {
      direction = true;
    }
    
    if (direction && n == 0)
    {
      direction = false;
    }
    
    ledcWrite(0, n);

    if (!direction)
    {
      n++;
    }
    else
    {
      n--;
    }
    
    vTaskDelay(10 / portTICK_PERIOD_MS); 
  }
}

Компілюємо, заливаємо, відкриваємо Serial-monitor, спостерігаємо за роботою.

Файли

Файли прикладів можна завантажити з репозиторію GitHub

Відео-посібник