Compare commits
9 Commits
c2dca42be6
...
dallas_lib
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cc733f4d2 | ||
|
|
fad8b2551a | ||
|
|
fa32d653e8 | ||
| 175bcd539f | |||
| 2e1b08b11b | |||
| dbbf9f8f62 | |||
|
|
72767cece9 | ||
|
|
36339503eb | ||
|
|
7ef076e289 |
@@ -2,12 +2,75 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @file dallas_tools.c
|
* @file dallas_tools.c
|
||||||
* @brief Драйвер для работы с датчиками температуры DS18B20
|
* @brief Драйвер для работы с датчиками температуры DS18B20
|
||||||
* @author MicroTechnics (microtechnics.ru)
|
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
@details
|
@details
|
||||||
Этот файл содержит реализацию функций для работы с датчиком DS18B20
|
Библиотека предназначена для работы с цифровыми датчиками температуры DS18B20
|
||||||
через интерфейс 1-Wire. Он предоставляет функции для чтения и записи
|
по однопроводному интерфейсу 1-Wire. Реализована поддержка инициализации, поиска,
|
||||||
конфигурации, выполнения измерений и обработки полученных данных.
|
добавления и работы с несколькими датчиками.
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
## Основные задачи библиотеки ##
|
||||||
|
==============================================================================
|
||||||
|
Эта библиотека предоставляет следующие основные функции:
|
||||||
|
(+) Инициализация шины 1-Wire и обнаружение подключённых датчиков
|
||||||
|
(+) Инициализация структуры датчика по:
|
||||||
|
- ROM-адресу
|
||||||
|
- пользовательским байтам (TH, TL, UserByte3, UserByte4)
|
||||||
|
- порядковому номеру в списке найденных устройств
|
||||||
|
(+) Конфигурация разрешения измерения
|
||||||
|
(+) Чтение температуры
|
||||||
|
(+) Замена «потерянного» датчика
|
||||||
|
(+) Деинициализация структуры датчика
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
## Быстрый старт ##
|
||||||
|
==============================================================================
|
||||||
|
Пример последовательности инициализации и использования:
|
||||||
|
|
||||||
|
1. Определение пина и таймера для OneWire в ow_port.h:
|
||||||
|
#define OW_GPIO_Port GPIOB
|
||||||
|
#define OW_Pin_Numb 0
|
||||||
|
#define OW_Pin (1<<OW_Pin_Numb)
|
||||||
|
#define OW_TIM TIM3
|
||||||
|
#define OW_TIM_1US_PERIOD 24
|
||||||
|
|
||||||
|
2. Подключение библиотеки и настройка таймеров:
|
||||||
|
#include "dallas_tools.h"
|
||||||
|
MX_TIM_Init();
|
||||||
|
|
||||||
|
3. Инициализация шины и поиск датчиков:
|
||||||
|
Dallas_BusFirstInit(&htim);
|
||||||
|
|
||||||
|
4. Инициализация датчика Dallas_SensorHandleTypeDef по одному из методов:
|
||||||
|
sens1.Init.init_func = &Dallas_SensorInitByInd; // по индексу
|
||||||
|
sens1.Init.InitParam.Ind = 0; // порядковый номер найденного датика для инициализации
|
||||||
|
|
||||||
|
sens2.Init.init_func = &Dallas_SensorInitByROM; // по ROM-адресу
|
||||||
|
sens2.Init.InitParam.ROM = 0; // ROM датика для инициализации
|
||||||
|
|
||||||
|
sens3.Init.init_func = &Dallas_SensorInitByUserBytes; // по пользовательским байтам
|
||||||
|
sens3.Init.InitParam.UserBytes.UserByte1 = 1; // UseBytes датика для инициализации
|
||||||
|
sens3.Init.InitParam.UserBytes.UserByte2 = 2; // UseBytes датика для инициализации
|
||||||
|
sens3.Init.InitParam.UserBytes.UserByte3 = 3; // UseBytes датика для инициализации
|
||||||
|
sens3.Init.InitParam.UserBytes.UserByte4 = 4; // UseBytes датика для инициализации
|
||||||
|
|
||||||
|
5. Инициализация структуруы датчика:
|
||||||
|
Dallas_AddNewSensors(&hdallas, &sens);
|
||||||
|
|
||||||
|
6. Работа с датчиком:
|
||||||
|
Dallas_StartConvertTAll(hdallas, DALLAS_WAIT_BUS, 0);
|
||||||
|
Dallas_ReadTemperature(&sens);
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
## Требуемые зависимости ##
|
||||||
|
==============================================================================
|
||||||
|
Для работы библиотеки требуется:
|
||||||
|
- Драйвер OneWire (файлы onewire.c/h и ow_port.c/.h)
|
||||||
|
- Драйвер DS18B20 (файлы ds18b20.c/h)
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
==============================================================================
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -23,29 +86,68 @@ DALLAS_HandleTypeDef hdallas;
|
|||||||
/* Functions ---------------------------------------------------------------*/
|
/* Functions ---------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Функция для иниицализации шины OW для датчиков
|
* @brief Функция для иниицализации структуры dallas и шины OW для датчиков
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @param OW Указатель на структуру OneWire (если NULL — используется по умолчанию)
|
||||||
|
* @param DS Указатель на структуру драйвера DS18B20 (если NULL — используется по умолчанию)
|
||||||
* @retval HAL Status
|
* @retval HAL Status
|
||||||
*/
|
*/
|
||||||
HAL_StatusTypeDef Dallas_BusFirstInit(TIM_HandleTypeDef *htim)
|
#ifndef UART_Driver
|
||||||
|
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||||
|
#else
|
||||||
|
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, UART_HandleTypeDef *huart)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
HAL_StatusTypeDef result;
|
if(hdallas == NULL)
|
||||||
|
|
||||||
|
|
||||||
if(HAL_TIM_Base_Start(htim))
|
|
||||||
return HAL_ERROR;
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
#ifndef UART_Driver
|
||||||
hdallas.onewire = &OW;
|
OW_TIM->CR1 |= TIM_CR1_CEN;
|
||||||
hdallas.ds_devices = &DS;
|
if(GPIOx == NULL)
|
||||||
OW.DataPin = DS_Pin;
|
{
|
||||||
OW.DataPort = DS_GPIO_Port;
|
hdallas->onewire.DataPin = OW_Pin;
|
||||||
|
hdallas->onewire.DataPort = OW_GPIO_Port;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hdallas->onewire.DataPin = GPIO_Pin;
|
||||||
|
hdallas->onewire.DataPort = GPIOx;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (hdallas->onewire.DataPin & (1 << i))
|
||||||
|
{
|
||||||
|
hdallas->onewire.DataPinNumb = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(huart == NULL)
|
||||||
|
hdallas->onewire.huart = &OW_UART_Handle;
|
||||||
|
else
|
||||||
|
hdallas->onewire.huart = huart;
|
||||||
|
#endif
|
||||||
/* Инициализация onewire и поиск датчиков*/
|
/* Инициализация onewire и поиск датчиков*/
|
||||||
OneWire_Init(&OW);
|
OneWire_Init(&hdallas->onewire);
|
||||||
|
|
||||||
|
|
||||||
return DS18B20_Search(&DS, &OW) != HAL_OK;
|
return Dallas_Search(hdallas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Поиск датчиков на шине onewire
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @retval HAL Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_Search(DALLAS_HandleTypeDef *hdallas)
|
||||||
|
{
|
||||||
|
if(hdallas == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
return DS18B20_Search(&hdallas->ds_devices, &hdallas->onewire) != HAL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Функция для иниицализации нового датчика в структуре
|
* @brief Функция для иниицализации нового датчика в структуре
|
||||||
@@ -71,225 +173,7 @@ HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_Sen
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Инициализирует структуру датчика по ROM
|
|
||||||
* @param hdallas Указатель на хендл для общения с датчиками
|
|
||||||
* @param sensor Указатель на структуру датчика
|
|
||||||
* @retval HAL Status
|
|
||||||
*/
|
|
||||||
HAL_StatusTypeDef Dallas_SensorInitByROM(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
|
||||||
{
|
|
||||||
HAL_StatusTypeDef result;
|
|
||||||
|
|
||||||
if(hdallas == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
if(sensor == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
uint8_t ROM[8] = {0};
|
|
||||||
ROM[0] = (sensor->Init.InitParam >> (7*8)) & 0xFF;
|
|
||||||
ROM[1] = (sensor->Init.InitParam >> (6*8)) & 0xFF;
|
|
||||||
ROM[2] = (sensor->Init.InitParam >> (5*8)) & 0xFF;
|
|
||||||
ROM[3] = (sensor->Init.InitParam >> (4*8)) & 0xFF;
|
|
||||||
ROM[4] = (sensor->Init.InitParam >> (3*8)) & 0xFF;
|
|
||||||
ROM[5] = (sensor->Init.InitParam >> (2*8)) & 0xFF;
|
|
||||||
ROM[6] = (sensor->Init.InitParam >> (1*8)) & 0xFF;
|
|
||||||
ROM[7] = (sensor->Init.InitParam >> (0*8)) & 0xFF;
|
|
||||||
|
|
||||||
if(DS18B20_IsValidAddress(ROM) != HAL_OK)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
uint8_t comparebytes = DALLAS_ROM_SIZE;
|
|
||||||
int ROM_ind = 0;
|
|
||||||
for(int i = 0; i < hdallas->onewire->RomCnt; i++)
|
|
||||||
{
|
|
||||||
comparebytes = DALLAS_ROM_SIZE;
|
|
||||||
for(int rom_byte = 0; rom_byte < DALLAS_ROM_SIZE; rom_byte++)
|
|
||||||
{
|
|
||||||
if(hdallas->ds_devices->DevAddr[i][rom_byte] == ROM[rom_byte])
|
|
||||||
comparebytes--;
|
|
||||||
}
|
|
||||||
if(comparebytes == 0)
|
|
||||||
{
|
|
||||||
ROM_ind = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Проверка присутствует ли выбранный датчик на линии */
|
|
||||||
if(comparebytes == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[ROM_ind]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return HAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Инициализирует структуру датчика по пользовательским байтам
|
|
||||||
* @param hdallas Указатель на хендл для общения с датчиками
|
|
||||||
* @param sensor Указатель на структуру датчика
|
|
||||||
* @retval HAL Status
|
|
||||||
*/
|
|
||||||
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
|
||||||
{
|
|
||||||
HAL_StatusTypeDef result;
|
|
||||||
|
|
||||||
if(hdallas == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
if(sensor == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
uint8_t UserByte1 = sensor->Init.InitParam & 0xFF;
|
|
||||||
uint8_t UserByte2 = sensor->Init.InitParam >> 8;
|
|
||||||
uint8_t UserByte3 = (sensor->Init.InitParam >> 16) & 0xFF;
|
|
||||||
uint8_t UserByte4 = (sensor->Init.InitParam >> 16) >> 8;
|
|
||||||
uint8_t UserByte12Cmp = 0;
|
|
||||||
uint8_t UserByte34Cmp = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < hdallas->onewire->RomCnt; i++)
|
|
||||||
{
|
|
||||||
/* Проверка присутствует ли выбранный датчик на линии */
|
|
||||||
result = DS18B20_ReadScratchpad(hdallas->onewire, (uint8_t *)&hdallas->ds_devices->DevAddr[i], (uint8_t *)&hdallas->scratchpad);
|
|
||||||
if (result != HAL_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/* Сравнение UserByte1 и UserByte2, если они не равны нулю */
|
|
||||||
if((sensor->Init.InitParam & 0xFFFF) != NULL)
|
|
||||||
{
|
|
||||||
if( (hdallas->scratchpad.tHighRegister == UserByte1) &&
|
|
||||||
(hdallas->scratchpad.tLowRegister == UserByte2))
|
|
||||||
{
|
|
||||||
UserByte12Cmp = 1;
|
|
||||||
}
|
|
||||||
}/* Если сравнение UserByte1 и UserByte2 не выбрано, то считаем что они совпадают */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UserByte12Cmp = 1;
|
|
||||||
}
|
|
||||||
/* Сравнение UserByte3 и UserByte4, если они не равны нулю */
|
|
||||||
if((sensor->Init.InitParam & 0xFFFF0000) != NULL)
|
|
||||||
{
|
|
||||||
if( (hdallas->scratchpad.UserByte3 == UserByte3) &&
|
|
||||||
(hdallas->scratchpad.UserByte4 == UserByte4))
|
|
||||||
{
|
|
||||||
UserByte34Cmp = 1;
|
|
||||||
}
|
|
||||||
}/* Если сравнение UserByte3 и UserByte4 не выбрано, то считаем что они одинаковые */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UserByte34Cmp = 1;
|
|
||||||
}
|
|
||||||
/* Если нашли нужный датчик - завершаем поиск */
|
|
||||||
if(UserByte12Cmp && UserByte34Cmp)
|
|
||||||
{
|
|
||||||
// sensor->isInitialized = 1;
|
|
||||||
// sensor->Init.init_func = (HAL_StatusTypeDef (*)())Dallas_SensorInitByUserBytes;
|
|
||||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[i]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sensor->sensROM = 0;
|
|
||||||
/* Возвращаем ошибку если не нашли */
|
|
||||||
return HAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Инициализирует структуру датчика по порядковому номеру
|
|
||||||
* @param hdallas Указатель на хендл для общения с датчиками
|
|
||||||
* @param sensor Указатель на структуру датчика
|
|
||||||
* @retval HAL Status
|
|
||||||
* @details Порядковый номер датчика в списке найденных.
|
|
||||||
* Т.е. каким по счету этот датчик был найден
|
|
||||||
*/
|
|
||||||
HAL_StatusTypeDef Dallas_SensorInitByInd(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
|
||||||
{
|
|
||||||
HAL_StatusTypeDef result;
|
|
||||||
|
|
||||||
if(hdallas == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
if(sensor == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[sensor->Init.InitParam]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Инициализирует датчик для работы
|
|
||||||
* @param hdallas Указатель на хендл для общения с датчиками
|
|
||||||
* @param sensor Указатель на структуру датчика
|
|
||||||
* @param ROM ROM датчика, который надо инициализировать
|
|
||||||
* @retval HAL Status
|
|
||||||
*/
|
|
||||||
HAL_StatusTypeDef Dallas_SensorInit(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor, uint8_t (*ROM)[DALLAS_ROM_SIZE])
|
|
||||||
{
|
|
||||||
HAL_StatusTypeDef result;
|
|
||||||
|
|
||||||
if(sensor == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
if(hdallas == 0)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
sensor->hdallas = hdallas;
|
|
||||||
sensor->sensROM = 0;
|
|
||||||
sensor->sensROM = *(uint64_t *)(ROM);
|
|
||||||
// for(int i = 0; i < DALLAS_ROM_SIZE; i++)
|
|
||||||
// sensor->sensROM |= ((uint64_t)(*ROM)[i] << (56 - 8*i));
|
|
||||||
|
|
||||||
/* Проверка присутствует ли выбранный датчик на линии */
|
|
||||||
result = Dallas_ReadScratchpad(sensor);
|
|
||||||
if (result == HAL_OK)
|
|
||||||
{
|
|
||||||
/* Установка разрешения */
|
|
||||||
result = DS18B20_SetResolution(hdallas->onewire, (uint8_t *)ROM, sensor->Init.Resolution);
|
|
||||||
if (result == HAL_OK)
|
|
||||||
{
|
|
||||||
sensor->isInitialized = 1;
|
|
||||||
return HAL_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sensor->isInitialized = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sensor->isInitialized = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Деинициализирует структуру датчика
|
|
||||||
* @param sensor Указатель на структуру датчика
|
|
||||||
* @retval HAL Status
|
|
||||||
*/
|
|
||||||
HAL_StatusTypeDef Dallas_SensorDeInit(DALLAS_SensorHandleTypeDef *sensor)
|
|
||||||
{
|
|
||||||
if(sensor == NULL)
|
|
||||||
return HAL_ERROR;
|
|
||||||
|
|
||||||
memset(&sensor->f, 0, sizeof(sensor->f));
|
|
||||||
sensor->isConnected = 0;
|
|
||||||
sensor->isInitialized = 0;
|
|
||||||
sensor->isLost = 0;
|
|
||||||
sensor->temperature = 0;
|
|
||||||
sensor->sensROM = 0;
|
|
||||||
|
|
||||||
return HAL_OK;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @brief Функция для нахождения нового датчика на место потерянного
|
* @brief Функция для нахождения нового датчика на место потерянного
|
||||||
* @param sensor Указатель на структуру датчика
|
* @param sensor Указатель на структуру датчика
|
||||||
@@ -307,7 +191,7 @@ HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor)
|
|||||||
|
|
||||||
if(sensor->isLost)
|
if(sensor->isLost)
|
||||||
{
|
{
|
||||||
if(DS18B20_Search(sensor->hdallas->ds_devices, sensor->hdallas->onewire) != HAL_OK)
|
if(Dallas_Search(sensor->hdallas) != HAL_OK)
|
||||||
return HAL_ERROR;
|
return HAL_ERROR;
|
||||||
|
|
||||||
if(sensor->Init.init_func(sensor->hdallas, sensor) != HAL_OK)
|
if(sensor->Init.init_func(sensor->hdallas, sensor) != HAL_OK)
|
||||||
@@ -338,7 +222,7 @@ HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_
|
|||||||
return HAL_ERROR;
|
return HAL_ERROR;
|
||||||
|
|
||||||
// Отправка команды начала преобразования температуры
|
// Отправка команды начала преобразования температуры
|
||||||
result = DS18B20_StartConvTAll(hdallas->onewire);
|
result = DS18B20_StartConvTAll(&hdallas->onewire);
|
||||||
if(result != HAL_OK)
|
if(result != HAL_OK)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -350,7 +234,7 @@ HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_
|
|||||||
// Ожидание завершения преобразования, путем проверки шины
|
// Ожидание завершения преобразования, путем проверки шины
|
||||||
if (waitCondition == DALLAS_WAIT_BUS)
|
if (waitCondition == DALLAS_WAIT_BUS)
|
||||||
{
|
{
|
||||||
result = DS18B20_WaitForEndConvertion(hdallas->onewire);
|
result = DS18B20_WaitForEndConvertion(&hdallas->onewire);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +293,7 @@ HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_Wai
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
// Отправка команды начала преобразования температуры
|
// Отправка команды начала преобразования температуры
|
||||||
result = DS18B20_StartConvT(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM);
|
result = DS18B20_StartConvT(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM);
|
||||||
if(result != HAL_OK)
|
if(result != HAL_OK)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -418,7 +302,7 @@ HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_Wai
|
|||||||
// Ожидание завершения преобразования, путем проверки шины
|
// Ожидание завершения преобразования, путем проверки шины
|
||||||
if (waitCondition == DALLAS_WAIT_BUS)
|
if (waitCondition == DALLAS_WAIT_BUS)
|
||||||
{
|
{
|
||||||
result = DS18B20_WaitForEndConvertion(sensor->hdallas->onewire);
|
result = DS18B20_WaitForEndConvertion(&sensor->hdallas->onewire);
|
||||||
if(result == HAL_TIMEOUT)
|
if(result == HAL_TIMEOUT)
|
||||||
{
|
{
|
||||||
sensor->f.timeout_convertion_cnt++;
|
sensor->f.timeout_convertion_cnt++;
|
||||||
@@ -488,7 +372,7 @@ HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_SensorHandleTypeDef *sensor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result = DS18B20_CalcTemperature(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad, &sensor->temperature);
|
result = DS18B20_CalcTemperature(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad, &sensor->temperature);
|
||||||
|
|
||||||
if (result != HAL_OK)
|
if (result != HAL_OK)
|
||||||
{
|
{
|
||||||
@@ -556,7 +440,7 @@ HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_SensorHandleTypeDef *sensor, uint
|
|||||||
if (result != HAL_OK)
|
if (result != HAL_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = DS18B20_WriteUserBytes(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
|
result = DS18B20_WriteUserBytes(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
|
||||||
if (result != HAL_OK)
|
if (result != HAL_OK)
|
||||||
{
|
{
|
||||||
sensor->f.write_err_cnt++;
|
sensor->f.write_err_cnt++;
|
||||||
@@ -576,5 +460,225 @@ HAL_StatusTypeDef Dallas_ReadScratchpad(DALLAS_SensorHandleTypeDef *sensor)
|
|||||||
{
|
{
|
||||||
if(sensor == NULL)
|
if(sensor == NULL)
|
||||||
return HAL_ERROR;
|
return HAL_ERROR;
|
||||||
return DS18B20_ReadScratchpad(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad);
|
return DS18B20_ReadScratchpad(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует структуру датчика по ROM
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @param sensor Указатель на структуру датчика
|
||||||
|
* @retval HAL Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_SensorInitByROM(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef result;
|
||||||
|
|
||||||
|
if(hdallas == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
if(sensor == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
uint8_t ROM[8] = {0};
|
||||||
|
ROM[0] = (sensor->Init.InitParam.ROM >> (7*8)) & 0xFF;
|
||||||
|
ROM[1] = (sensor->Init.InitParam.ROM >> (6*8)) & 0xFF;
|
||||||
|
ROM[2] = (sensor->Init.InitParam.ROM >> (5*8)) & 0xFF;
|
||||||
|
ROM[3] = (sensor->Init.InitParam.ROM >> (4*8)) & 0xFF;
|
||||||
|
ROM[4] = (sensor->Init.InitParam.ROM >> (3*8)) & 0xFF;
|
||||||
|
ROM[5] = (sensor->Init.InitParam.ROM >> (2*8)) & 0xFF;
|
||||||
|
ROM[6] = (sensor->Init.InitParam.ROM >> (1*8)) & 0xFF;
|
||||||
|
ROM[7] = (sensor->Init.InitParam.ROM >> (0*8)) & 0xFF;
|
||||||
|
|
||||||
|
if(DS18B20_IsValidAddress(ROM) != HAL_OK)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
uint8_t comparebytes = DALLAS_ROM_SIZE;
|
||||||
|
int ROM_ind = 0;
|
||||||
|
for(int i = 0; i < hdallas->onewire.RomCnt; i++)
|
||||||
|
{
|
||||||
|
comparebytes = DALLAS_ROM_SIZE;
|
||||||
|
for(int rom_byte = 0; rom_byte < DALLAS_ROM_SIZE; rom_byte++)
|
||||||
|
{
|
||||||
|
if(hdallas->ds_devices.DevAddr[i][rom_byte] == ROM[rom_byte])
|
||||||
|
comparebytes--;
|
||||||
|
}
|
||||||
|
if(comparebytes == 0)
|
||||||
|
{
|
||||||
|
ROM_ind = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Проверка присутствует ли выбранный датчик на линии */
|
||||||
|
if(comparebytes == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices.DevAddr[ROM_ind]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует структуру датчика по пользовательским байтам
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @param sensor Указатель на структуру датчика
|
||||||
|
* @retval HAL Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef result;
|
||||||
|
|
||||||
|
if(hdallas == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
if(sensor == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
uint8_t UserByte1 = sensor->Init.InitParam.UserBytes.UserByte1;
|
||||||
|
uint8_t UserByte2 = sensor->Init.InitParam.UserBytes.UserByte2;
|
||||||
|
uint8_t UserByte3 = sensor->Init.InitParam.UserBytes.UserByte3;
|
||||||
|
uint8_t UserByte4 = sensor->Init.InitParam.UserBytes.UserByte4;
|
||||||
|
uint8_t UserByte12Cmp = 0;
|
||||||
|
uint8_t UserByte34Cmp = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < hdallas->onewire.RomCnt; i++)
|
||||||
|
{
|
||||||
|
/* Проверка присутствует ли выбранный датчик на линии */
|
||||||
|
result = DS18B20_ReadScratchpad(&hdallas->onewire, (uint8_t *)&hdallas->ds_devices.DevAddr[i], (uint8_t *)&hdallas->scratchpad);
|
||||||
|
if (result != HAL_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* Сравнение UserByte1 и UserByte2, если они не равны нулю */
|
||||||
|
if(UserByte1 | UserByte2)
|
||||||
|
{
|
||||||
|
if( (hdallas->scratchpad.tHighRegister == UserByte1) &&
|
||||||
|
(hdallas->scratchpad.tLowRegister == UserByte2))
|
||||||
|
{
|
||||||
|
UserByte12Cmp = 1;
|
||||||
|
}
|
||||||
|
}/* Если сравнение UserByte1 и UserByte2 не выбрано, то считаем что они совпадают */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserByte12Cmp = 1;
|
||||||
|
}
|
||||||
|
/* Сравнение UserByte3 и UserByte4, если они не равны нулю */
|
||||||
|
if(UserByte3 | UserByte4)
|
||||||
|
{
|
||||||
|
if( (hdallas->scratchpad.UserByte3 == UserByte3) &&
|
||||||
|
(hdallas->scratchpad.UserByte4 == UserByte4))
|
||||||
|
{
|
||||||
|
UserByte34Cmp = 1;
|
||||||
|
}
|
||||||
|
}/* Если сравнение UserByte3 и UserByte4 не выбрано, то считаем что они одинаковые */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserByte34Cmp = 1;
|
||||||
|
}
|
||||||
|
/* Если нашли нужный датчик - завершаем поиск */
|
||||||
|
if(UserByte12Cmp && UserByte34Cmp)
|
||||||
|
{
|
||||||
|
// sensor->isInitialized = 1;
|
||||||
|
// sensor->Init.init_func = (HAL_StatusTypeDef (*)())Dallas_SensorInitByUserBytes;
|
||||||
|
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices.DevAddr[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor->sensROM = 0;
|
||||||
|
/* Возвращаем ошибку если не нашли */
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует структуру датчика по порядковому номеру
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @param sensor Указатель на структуру датчика
|
||||||
|
* @retval HAL Status
|
||||||
|
* @details Порядковый номер датчика в списке найденных.
|
||||||
|
* Т.е. каким по счету этот датчик был найден
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_SensorInitByInd(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef result;
|
||||||
|
|
||||||
|
if(hdallas == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
if(sensor == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices.DevAddr[sensor->Init.InitParam.Ind]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует датчик для работы
|
||||||
|
* @param hdallas Указатель на хендл для общения с датчиками
|
||||||
|
* @param sensor Указатель на структуру датчика
|
||||||
|
* @param ROM ROM датчика, который надо инициализировать
|
||||||
|
* @retval HAL Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_SensorInit(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor, uint8_t (*ROM)[DALLAS_ROM_SIZE])
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef result;
|
||||||
|
|
||||||
|
if(sensor == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
if(hdallas == 0)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
sensor->hdallas = hdallas;
|
||||||
|
sensor->sensROM = 0;
|
||||||
|
sensor->sensROM = *(uint64_t *)(ROM);
|
||||||
|
// for(int i = 0; i < DALLAS_ROM_SIZE; i++)
|
||||||
|
// sensor->sensROM |= ((uint64_t)(*ROM)[i] << (56 - 8*i));
|
||||||
|
|
||||||
|
/* Проверка присутствует ли выбранный датчик на линии */
|
||||||
|
result = Dallas_ReadScratchpad(sensor);
|
||||||
|
if (result == HAL_OK)
|
||||||
|
{
|
||||||
|
/* Установка разрешения */
|
||||||
|
result = DS18B20_SetResolution(&hdallas->onewire, (uint8_t *)ROM, sensor->Init.Resolution);
|
||||||
|
if (result == HAL_OK)
|
||||||
|
{
|
||||||
|
sensor->isInitialized = 1;
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sensor->isInitialized = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sensor->isInitialized = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Деинициализирует структуру датчика
|
||||||
|
* @param sensor Указатель на структуру датчика
|
||||||
|
* @retval HAL Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef Dallas_SensorDeInit(DALLAS_SensorHandleTypeDef *sensor)
|
||||||
|
{
|
||||||
|
if(sensor == NULL)
|
||||||
|
return HAL_ERROR;
|
||||||
|
|
||||||
|
memset(&sensor->f, 0, sizeof(sensor->f));
|
||||||
|
sensor->isConnected = 0;
|
||||||
|
sensor->isInitialized = 0;
|
||||||
|
sensor->isLost = 0;
|
||||||
|
sensor->temperature = 0;
|
||||||
|
sensor->sensROM = 0;
|
||||||
|
|
||||||
|
return HAL_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@
|
|||||||
#define DALLAS_DELAY_MS_12_BITS 750
|
#define DALLAS_DELAY_MS_12_BITS 750
|
||||||
#define DALLAS_DELAY_MS_MAX DALLAS_DELAY_MS_12_BITS
|
#define DALLAS_DELAY_MS_MAX DALLAS_DELAY_MS_12_BITS
|
||||||
|
|
||||||
|
typedef struct _SensorHandleStruct DALLAS_SensorHandleTypeDef;
|
||||||
|
typedef struct _DallasHandleStruct DALLAS_HandleTypeDef;
|
||||||
|
|
||||||
/** @brief Структура Scratchpad датчика DALLAS */
|
/** @brief Структура Scratchpad датчика DALLAS */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -70,24 +73,36 @@ typedef struct
|
|||||||
/** @brief Структура инициализации датчика DALLAS */
|
/** @brief Структура инициализации датчика DALLAS */
|
||||||
typedef struct __packed
|
typedef struct __packed
|
||||||
{
|
{
|
||||||
uint64_t InitParam; ///< Параметр для инициализации: ROM/UserBytes/Индекс
|
union
|
||||||
|
{
|
||||||
|
uint64_t Ind; ///< порядковый номер датчика
|
||||||
|
uint64_t ROM; ///< ROM датчика
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t UserByte1; ///< Младший байт (бит 0–7)
|
||||||
|
uint8_t UserByte2; ///< Следующий байт (бит 8–15)
|
||||||
|
uint8_t UserByte3; ///< Байт (бит 16–23)
|
||||||
|
uint8_t UserByte4; ///< Байт (бит 24–31)
|
||||||
|
uint8_t Reserved[4]; ///< Остальные байты (бит 32–63, если нужно)
|
||||||
|
} UserBytes; ///< UserBytes датчика
|
||||||
|
}InitParam; ///< Параметр для инициализации: ROM/UserBytes/Индекс
|
||||||
uint8_t Resolution; ///< Разрешение датчика
|
uint8_t Resolution; ///< Разрешение датчика
|
||||||
HAL_StatusTypeDef (*init_func)(); ///< Функция инициализации
|
HAL_StatusTypeDef (*init_func)(DALLAS_HandleTypeDef *, DALLAS_SensorHandleTypeDef *); ///< Функция инициализации
|
||||||
} DALLAS_InitStructTypeDef;
|
} DALLAS_InitStructTypeDef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @brief Cтруктура обработчика DALLAS для общения с датчиком*/
|
/** @brief Cтруктура обработчика DALLAS для общения с датчиком*/
|
||||||
typedef struct
|
struct _DallasHandleStruct
|
||||||
{
|
{
|
||||||
OneWire_t *onewire;
|
OneWire_t onewire;
|
||||||
DS18B20_Drv_t *ds_devices;
|
DS18B20_Drv_t ds_devices;
|
||||||
DALLAS_ScratchpadTypeDef scratchpad;
|
DALLAS_ScratchpadTypeDef scratchpad;
|
||||||
}DALLAS_HandleTypeDef;
|
};
|
||||||
extern DALLAS_HandleTypeDef hdallas;
|
extern DALLAS_HandleTypeDef hdallas;
|
||||||
|
|
||||||
/** @brief Основная структура обработчика датчика DALLAS */
|
/** @brief Основная структура обработчика датчика DALLAS */
|
||||||
typedef struct
|
struct _SensorHandleStruct
|
||||||
{
|
{
|
||||||
unsigned isConnected:1; ///< Флаг соединения
|
unsigned isConnected:1; ///< Флаг соединения
|
||||||
unsigned isInitialized:1; ///< Флаг инициализации
|
unsigned isInitialized:1; ///< Флаг инициализации
|
||||||
@@ -100,7 +115,7 @@ typedef struct
|
|||||||
|
|
||||||
DALLAS_InitStructTypeDef Init; ///< Структура инициализации
|
DALLAS_InitStructTypeDef Init; ///< Структура инициализации
|
||||||
DALLAS_FlagsTypeDef f; ///< Флаги
|
DALLAS_FlagsTypeDef f; ///< Флаги
|
||||||
} DALLAS_SensorHandleTypeDef;
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -115,8 +130,14 @@ typedef enum
|
|||||||
|
|
||||||
|
|
||||||
/* Functions ---------------------------------------------------------------*/
|
/* Functions ---------------------------------------------------------------*/
|
||||||
|
/* Функция для иниицализации структуры dallas и шины OW для датчиков */
|
||||||
HAL_StatusTypeDef Dallas_BusFirstInit(TIM_HandleTypeDef *htim);
|
#ifndef UART_Driver
|
||||||
|
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
|
||||||
|
#else
|
||||||
|
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, UART_HandleTypeDef *huart);
|
||||||
|
#endif
|
||||||
|
/* Поиск датчиков на шине onewire */
|
||||||
|
HAL_StatusTypeDef Dallas_Search(DALLAS_HandleTypeDef *hdallas);
|
||||||
/* Функция для иниицализации нового датчика в структуре */
|
/* Функция для иниицализации нового датчика в структуре */
|
||||||
HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||||
/* Инициализирует структуру датчика по ROM */
|
/* Инициализирует структуру датчика по ROM */
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "ds18b20_driver.h"
|
#include "ds18b20_driver.h"
|
||||||
|
|
||||||
DS18B20_Drv_t DS;
|
|
||||||
OneWire_t OW;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The function is used to check valid DS18B20 ROM
|
* @brief The function is used to check valid DS18B20 ROM
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
|||||||
OneWire_Pin_Mode(OW, Output);
|
OneWire_Pin_Mode(OW, Output);
|
||||||
|
|
||||||
/* Forming pulse */
|
/* Forming pulse */
|
||||||
OneWire_Delay_uw(ONEWIRE_WRITE_1_US);
|
OneWire_Delay_us(ONEWIRE_WRITE_1_US);
|
||||||
|
|
||||||
/* Release line (pull up line) */
|
/* Release line (pull up line) */
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
|
|
||||||
/* Wait for 55 us and release the line */
|
/* Wait for 55 us and release the line */
|
||||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
}else{
|
}else{
|
||||||
/* Set line low */
|
/* Set line low */
|
||||||
@@ -38,18 +38,18 @@ void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
|||||||
OneWire_Pin_Mode(OW, Output);
|
OneWire_Pin_Mode(OW, Output);
|
||||||
|
|
||||||
/* Forming pulse */
|
/* Forming pulse */
|
||||||
OneWire_Delay_uw(ONEWIRE_WRITE_0_US);
|
OneWire_Delay_us(ONEWIRE_WRITE_0_US);
|
||||||
|
|
||||||
/* Release line (pull up line) */
|
/* Release line (pull up line) */
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
|
|
||||||
/* Wait for 5 us and release the line */
|
/* Wait for 5 us and release the line */
|
||||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
}
|
}
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
#else
|
#else
|
||||||
OneWireUART_ProcessBit(onewire_uart, bit);
|
OneWireUART_ProcessBit(OW->huart, bit);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,20 +69,20 @@ uint8_t OneWire_ReadBit(OneWire_t* OW)
|
|||||||
/* Line low */
|
/* Line low */
|
||||||
OneWire_Pin_Level(OW, 0);
|
OneWire_Pin_Level(OW, 0);
|
||||||
OneWire_Pin_Mode(OW, Output);
|
OneWire_Pin_Mode(OW, Output);
|
||||||
OneWire_Delay_uw(ONEWIRE_READ_CMD_US);
|
OneWire_Delay_us(ONEWIRE_READ_CMD_US);
|
||||||
|
|
||||||
/* Release line */
|
/* Release line */
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
OneWire_Delay_uw(ONEWIRE_READ_DELAY_US);
|
OneWire_Delay_us(ONEWIRE_READ_DELAY_US);
|
||||||
|
|
||||||
/* Read line value */
|
/* Read line value */
|
||||||
bit = OneWire_Pin_Read(OW);
|
bit = OneWire_Pin_Read(OW);
|
||||||
|
|
||||||
/* Wait 50us to complete 60us period */
|
/* Wait 50us to complete 60us period */
|
||||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
#else
|
#else
|
||||||
bit = OneWireUART_ProcessBit(onewire_uart, 1);
|
bit = OneWireUART_ProcessBit(OW->huart, 1);
|
||||||
#endif
|
#endif
|
||||||
/* Return bit value */
|
/* Return bit value */
|
||||||
return bit;
|
return bit;
|
||||||
@@ -107,7 +107,7 @@ void OneWire_WriteByte(OneWire_t* OW, uint8_t byte)
|
|||||||
byte >>= 1;
|
byte >>= 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
OneWireUART_ProcessByte(onewire_uart, byte);
|
OneWireUART_ProcessByte(OW->huart, byte);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ uint8_t OneWire_ReadByte(OneWire_t* OW)
|
|||||||
byte |= (OneWire_ReadBit(OW) << 7);
|
byte |= (OneWire_ReadBit(OW) << 7);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
byte = OneWireUART_ProcessByte(onewire_uart, 0xFF);
|
byte = OneWireUART_ProcessByte(OW->huart, 0xFF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return byte;
|
return byte;
|
||||||
@@ -149,21 +149,21 @@ uint8_t OneWire_Reset(OneWire_t* OW)
|
|||||||
/* Line low, and wait 480us */
|
/* Line low, and wait 480us */
|
||||||
OneWire_Pin_Level(OW, 0);
|
OneWire_Pin_Level(OW, 0);
|
||||||
OneWire_Pin_Mode(OW, Output);
|
OneWire_Pin_Mode(OW, Output);
|
||||||
OneWire_Delay_uw(ONEWIRE_RESET_PULSE_US);
|
OneWire_Delay_us(ONEWIRE_RESET_PULSE_US);
|
||||||
|
|
||||||
/* Release line and wait for 70us */
|
/* Release line and wait for 70us */
|
||||||
OneWire_Pin_Mode(OW, Input);
|
OneWire_Pin_Mode(OW, Input);
|
||||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_WAIT_US);
|
OneWire_Delay_us(ONEWIRE_PRESENCE_WAIT_US);
|
||||||
|
|
||||||
/* Check bit value */
|
/* Check bit value */
|
||||||
uint8_t rslt = OneWire_Pin_Read(OW);
|
uint8_t rslt = OneWire_Pin_Read(OW);
|
||||||
|
|
||||||
/* Delay for 410 us */
|
/* Delay for 410 us */
|
||||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_DURATION_US);
|
OneWire_Delay_us(ONEWIRE_PRESENCE_DURATION_US);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
uint8_t rslt = 0;
|
uint8_t rslt = 0;
|
||||||
if(OneWireUART_Reset(onewire_uart) == HAL_OK)
|
if(OneWireUART_Reset(OW->huart) == HAL_OK)
|
||||||
rslt = 0;
|
rslt = 0;
|
||||||
else
|
else
|
||||||
rslt = 1;
|
rslt = 1;
|
||||||
@@ -314,14 +314,15 @@ void OneWire_GetDevRom(OneWire_t* OW, uint8_t *ROM)
|
|||||||
*/
|
*/
|
||||||
void OneWire_Init(OneWire_t* OW)
|
void OneWire_Init(OneWire_t* OW)
|
||||||
{
|
{
|
||||||
|
#ifndef UART_Driver
|
||||||
OneWire_Pin_Mode(OW, Output);
|
OneWire_Pin_Mode(OW, Output);
|
||||||
OneWire_Pin_Level(OW, 1);
|
OneWire_Pin_Level(OW, 1);
|
||||||
OneWire_Delay_uw(1000);
|
OneWire_Delay_us(1000);
|
||||||
OneWire_Pin_Level(OW, 0);
|
OneWire_Pin_Level(OW, 0);
|
||||||
OneWire_Delay_uw(1000);
|
OneWire_Delay_us(1000);
|
||||||
OneWire_Pin_Level(OW, 1);
|
OneWire_Pin_Level(OW, 1);
|
||||||
OneWire_Delay_uw(2000);
|
OneWire_Delay_us(2000);
|
||||||
|
#endif
|
||||||
/* Reset the search state */
|
/* Reset the search state */
|
||||||
OW->LastDiscrepancy = 0;
|
OW->LastDiscrepancy = 0;
|
||||||
OW->LastDeviceFlag = 0;
|
OW->LastDeviceFlag = 0;
|
||||||
|
|||||||
@@ -14,10 +14,8 @@
|
|||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
#include "ow_port.h"
|
#include "ow_port.h"
|
||||||
|
|
||||||
/* Driver Selection ----------------------------------------------------------*/
|
/* Driver Selection ----------------------------------------------------------*/
|
||||||
//#define LL_Driver
|
|
||||||
//#define CMSIS_Driver
|
|
||||||
/* OneWire Timings -----------------------------------------------------------*/
|
/* OneWire Timings -----------------------------------------------------------*/
|
||||||
#define ONEWIRE_RESET_PULSE_US 480 // Длительность импульса сброса
|
#define ONEWIRE_RESET_PULSE_US 480 // Длительность импульса сброса
|
||||||
#define ONEWIRE_PRESENCE_WAIT_US 70 // Ожидание ответа от датчика
|
#define ONEWIRE_PRESENCE_WAIT_US 70 // Ожидание ответа от датчика
|
||||||
@@ -49,8 +47,13 @@ typedef struct
|
|||||||
uint8_t LastDeviceFlag;
|
uint8_t LastDeviceFlag;
|
||||||
uint8_t RomByte[8];
|
uint8_t RomByte[8];
|
||||||
uint8_t RomCnt;
|
uint8_t RomCnt;
|
||||||
|
#if defined(UART_Driver)
|
||||||
|
UART_HandleTypeDef *huart;
|
||||||
|
#else
|
||||||
|
uint16_t DataPinNumb;
|
||||||
uint16_t DataPin;
|
uint16_t DataPin;
|
||||||
GPIO_TypeDef *DataPort;
|
GPIO_TypeDef *DataPort;
|
||||||
|
#endif
|
||||||
} OneWire_t;
|
} OneWire_t;
|
||||||
|
|
||||||
/* External Function ---------------------------------------------------------*/
|
/* External Function ---------------------------------------------------------*/
|
||||||
|
|||||||
158
DS18B20/onewire_uart.c
Normal file
158
DS18B20/onewire_uart.c
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file : onewire_uart.c
|
||||||
|
* @brief : Драйвер для работы с шиной 1-Wire через UART
|
||||||
|
* @author : MicroTechnics (microtechnics.ru)
|
||||||
|
******************************************************************************
|
||||||
|
@details
|
||||||
|
Этот файл реализует базовые функции для работы с 1-Wire через UART.
|
||||||
|
Он включает в себя методы для передачи и приёма битов и байтов, а также
|
||||||
|
выполнение reset-команды для устройств 1-Wire.
|
||||||
|
|
||||||
|
UART передает специально сформированные импульсы, эмулируя 1-Wire.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* Includes ----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "onewire_uart.h"
|
||||||
|
|
||||||
|
/* Declarations and definitions --------------------------------------------*/
|
||||||
|
|
||||||
|
/* Functions ---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает скорость передачи данных для UART.
|
||||||
|
* @param huart Указатель на структуру UART
|
||||||
|
* @param baudrate Требуемая скорость передачи (бит/с)
|
||||||
|
* @details Функция изменяет скорость передачи UART в зависимости от используемой шины
|
||||||
|
* (PCLK1 или PCLK2). Это важно для эмуляции временных параметров 1-Wire.
|
||||||
|
*/
|
||||||
|
static void UARTSetBaudrate(UART_HandleTypeDef *huart, uint32_t baudrate)
|
||||||
|
{
|
||||||
|
uint32_t pclk = 0;
|
||||||
|
huart->Init.BaudRate = baudrate;
|
||||||
|
|
||||||
|
#if defined(USART6) && defined(UART9) && defined(UART10)
|
||||||
|
if ((huart->Instance == USART1) || (huart->Instance == USART6) ||
|
||||||
|
(huart->Instance == UART9) || (huart->Instance == UART10))
|
||||||
|
{
|
||||||
|
pclk = HAL_RCC_GetPCLK2Freq();
|
||||||
|
}
|
||||||
|
#elif defined(USART6)
|
||||||
|
if ((huart->Instance == USART1) || (huart->Instance == USART6))
|
||||||
|
{
|
||||||
|
pclk = HAL_RCC_GetPCLK2Freq();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (huart->Instance == USART1)
|
||||||
|
{
|
||||||
|
pclk = HAL_RCC_GetPCLK2Freq();
|
||||||
|
}
|
||||||
|
#endif /* USART6 */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pclk = HAL_RCC_GetPCLK1Freq();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USART_CR1_OVER8)
|
||||||
|
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
|
||||||
|
{
|
||||||
|
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||||
|
#endif /* USART_CR1_OVER8 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Передает и принимает один бит через 1-Wire.
|
||||||
|
* @param huart Указатель на структуру UART
|
||||||
|
* @param bit Бит для передачи (0 или 1)
|
||||||
|
* @return Полученный бит (0 или 1)
|
||||||
|
* @details Передача осуществляется отправкой специального импульса, длина которого определяет передаваемый бит.
|
||||||
|
* Ответное значение читается сразу после передачи.
|
||||||
|
*/
|
||||||
|
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
|
||||||
|
{
|
||||||
|
uint8_t txData;
|
||||||
|
uint8_t rxData = 0x00;
|
||||||
|
|
||||||
|
if (bit == 1)
|
||||||
|
{
|
||||||
|
txData = ONEWIRE_PULSE_SHORT; // Короткий импульс для передачи '1'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txData = ONEWIRE_PULSE_LONG; // Длинный импульс для передачи '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
HAL_UART_Transmit(huart, &txData, 1, ONEWIRE_UART_TIMEOUT);
|
||||||
|
HAL_UART_Receive(huart, &rxData, 1, ONEWIRE_UART_TIMEOUT);
|
||||||
|
|
||||||
|
if (rxData == 0xFF)
|
||||||
|
{
|
||||||
|
bit = 1; // Короткий импульс для передачи '1'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit = 0; // Длинный импульс для передачи '0'
|
||||||
|
}
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Передает и принимает байт через 1-Wire.
|
||||||
|
* @param huart Указатель на структуру UART
|
||||||
|
* @param byte Отправляемый байт
|
||||||
|
* @return Принятый байт
|
||||||
|
* @details Отправляет 8 бит последовательно, используя @ref OneWire_ProcessBit.
|
||||||
|
* Каждый полученный бит собирается в байт и возвращается.
|
||||||
|
*/
|
||||||
|
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)
|
||||||
|
{
|
||||||
|
uint8_t rxByte = 0x00;
|
||||||
|
uint8_t txBit = 0;
|
||||||
|
uint8_t rxBit = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
txBit = (byte >> i) & 0x01; // Извлекаем очередной бит для отправки
|
||||||
|
rxBit = OneWireUART_ProcessBit(huart, txBit);
|
||||||
|
|
||||||
|
rxByte |= (rxBit << i); // Собираем принятые биты в байт
|
||||||
|
}
|
||||||
|
|
||||||
|
return rxByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Выполняет 1-Wire Reset и проверяет наличие устройств на шине.
|
||||||
|
* @param huart Указатель на структуру UART
|
||||||
|
* @return HAL Status
|
||||||
|
* @details Процедура Reset требует изменения скорости UART, чтобы сформировать
|
||||||
|
* большой по длительности импульс сброса. Если устройство ответило, шина в рабочем состоянии.
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef status = HAL_OK;
|
||||||
|
uint8_t txByte = ONEWIRE_RESET;
|
||||||
|
uint8_t rxByte = 0x00;
|
||||||
|
|
||||||
|
UARTSetBaudrate(huart, ONEWIRE_RESET_BAUDRATE); // Устанавливаем низкую скорость для Reset-импульса
|
||||||
|
|
||||||
|
HAL_UART_Transmit(huart, &txByte, 1, ONEWIRE_UART_TIMEOUT);
|
||||||
|
HAL_UART_Receive(huart, &rxByte, 1, ONEWIRE_UART_TIMEOUT);
|
||||||
|
|
||||||
|
UARTSetBaudrate(huart, ONEWIRE_BAUDRATE); // Возвращаем стандартную скорость
|
||||||
|
|
||||||
|
if (rxByte == txByte)
|
||||||
|
{
|
||||||
|
status = HAL_ERROR; // Если ответ совпадает с отправленным байтом, значит, устройств нет
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
57
DS18B20/onewire_uart.h
Normal file
57
DS18B20/onewire_uart.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file : onewire_uart.h
|
||||||
|
* @brief : 1-Wire driver
|
||||||
|
* @author : MicroTechnics (microtechnics.ru)
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ONEWIRE_UART_H
|
||||||
|
#define ONEWIRE_UART_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Includes ----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations and definitions --------------------------------------------*/
|
||||||
|
#define ONEWIRE_BAUDRATE 115200
|
||||||
|
#define ONEWIRE_RESET_BAUDRATE 9600
|
||||||
|
#define ONEWIRE_UART_TIMEOUT 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Комманды OneWire
|
||||||
|
* @details Определяет байты для uart, которые будут
|
||||||
|
* формировать необходимую длину импульса для разных комманд
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ONEWIRE_RESET = 0xF0, /*!< @brief Импульс длиной 520мкс для команды Reset (9600bod)
|
||||||
|
@details 1-Wire требует импульс длительностью >480мкс */
|
||||||
|
|
||||||
|
ONEWIRE_PULSE_SHORT = 0xFF, /*!< @brief Импульс длиной 8.7 мкс для записи "1"/чтения бита (115200bod)
|
||||||
|
@details 1-Wire требует импульс длительностью 1-15мкс */
|
||||||
|
|
||||||
|
|
||||||
|
ONEWIRE_PULSE_LONG = 0x00, /*!< @brief импульс длиной 78.3 мкс для записи "0" (115200bod)
|
||||||
|
@details 1-Wire требует импульс длительностью 60-120мкс */
|
||||||
|
|
||||||
|
// ONEWIRE_PULSE_1_15US = 0xFF,
|
||||||
|
// ONEWIRE_PULSE_60_120US = 0x00,
|
||||||
|
}ONEWIRE_Commands;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Functions ---------------------------------------------------------------*/
|
||||||
|
/* Выполняет 1-Wire Reset и проверяет наличие устройств на шине */
|
||||||
|
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart);
|
||||||
|
/* Передает и принимает байт через 1-Wire */
|
||||||
|
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte);
|
||||||
|
/* Передает и принимает один бит через 1-Wire */
|
||||||
|
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifndef ONEWIRE_UART_H
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "ow_port.h"
|
#include "ow_port.h"
|
||||||
#include "onewire.h"
|
#include "onewire.h"
|
||||||
#include "tim.h"
|
#include "tim.h"
|
||||||
uint32_t pin_pos = (DS_Pin_Numb < 8) ? (DS_Pin_Numb * 4) : ((DS_Pin_Numb - 8) * 4);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The internal function is used as gpio pin mode
|
* @brief The internal function is used as gpio pin mode
|
||||||
@@ -16,25 +15,26 @@ uint32_t pin_pos = (DS_Pin_Numb < 8) ? (DS_Pin_Numb * 4) : ((DS_Pin_Numb - 8) *
|
|||||||
*/
|
*/
|
||||||
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
||||||
{
|
{
|
||||||
#ifdef CMSIS_Driver
|
#if defined(UART_Driver)
|
||||||
volatile uint32_t *config_reg = (DS_Pin_Numb < 8) ? &(OW->DataPort->CRL) : &(OW->DataPort->CRH);
|
#elif defined(CMSIS_Driver)
|
||||||
// Ñáðîñ òåêóùèõ 4 áèò (CNF + MODE)
|
volatile uint32_t *config_reg = (OW->DataPinNumb < 8) ? &(OW->DataPort->CRL) : &(OW->DataPort->CRH);
|
||||||
|
uint32_t pin_pos = (OW->DataPinNumb < 8) ? (OW->DataPinNumb * 4) : ((OW->DataPinNumb - 8) * 4);
|
||||||
|
// —брос текущих 4 бит (CNF + MODE)
|
||||||
*config_reg &= ~(0xF << pin_pos);
|
*config_reg &= ~(0xF << pin_pos);
|
||||||
|
|
||||||
if (Mode == Input)
|
if (Mode == Input)
|
||||||
{
|
{
|
||||||
// Âõîä ñ ïîäòÿæêîé èëè áåç – íàïðèìåð, CNF = 0b01, MODE = 0b00
|
// ¬ход с подт¤жкой или без Ц например, CNF = 0b01, MODE = 0b00
|
||||||
// Çäåñü óñòàíàâëèâàåì âõîä ñ ïîäòÿæêîé:
|
// «десь устанавливаем вход с подт¤жкой:
|
||||||
*config_reg |= (0x8 << pin_pos); // CNF=10, MODE=00 (âõîä ñ ïîäòÿæêîé)
|
*config_reg |= (0x8 << pin_pos); // CNF=10, MODE=00 (вход с подт¤жкой)
|
||||||
OW->DataPort->ODR |= (1 << DS_Pin_Numb); // Âêëþ÷èòü ïîäòÿæêó ââåðõ
|
OW->DataPort->ODR |= (1 << OW->DataPinNumb); // ¬ключить подт¤жку вверх
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Âûõîä push-pull, 2 ÌÃö – MODE = 0b10, CNF = 0b00
|
// ¬ыход push-pull, 2 ћ√ц Ц MODE = 0b10, CNF = 0b00
|
||||||
*config_reg |= (0x2 << pin_pos);
|
*config_reg |= (0x2 << pin_pos);
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(LL_Driver)
|
||||||
#ifdef LL_Driver
|
|
||||||
if(Mode == Input)
|
if(Mode == Input)
|
||||||
{
|
{
|
||||||
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
|
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
|
||||||
@@ -53,7 +53,6 @@ volatile uint32_t *config_reg = (DS_Pin_Numb < 8) ? &(OW->DataPort->CRL) : &(OW-
|
|||||||
}
|
}
|
||||||
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +62,8 @@ volatile uint32_t *config_reg = (DS_Pin_Numb < 8) ? &(OW->DataPort->CRL) : &(OW-
|
|||||||
*/
|
*/
|
||||||
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||||
{
|
{
|
||||||
#ifdef CMSIS_Driver
|
#if defined(UART_Driver)
|
||||||
|
#elif defined(CMSIS_Driver)
|
||||||
if (Level != GPIO_PIN_RESET)
|
if (Level != GPIO_PIN_RESET)
|
||||||
{
|
{
|
||||||
OW->DataPort->BSRR = OW->DataPin;
|
OW->DataPort->BSRR = OW->DataPin;
|
||||||
@@ -72,8 +72,7 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
|||||||
{
|
{
|
||||||
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
|
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(LL_Driver)
|
||||||
#ifdef LL_Driver
|
|
||||||
if(Level == 1)
|
if(Level == 1)
|
||||||
{
|
{
|
||||||
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
|
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
|
||||||
@@ -83,7 +82,6 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
|||||||
#else
|
#else
|
||||||
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
|
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,19 +91,19 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
|||||||
*/
|
*/
|
||||||
uint8_t OneWire_Pin_Read(OneWire_t* OW)
|
uint8_t OneWire_Pin_Read(OneWire_t* OW)
|
||||||
{
|
{
|
||||||
#ifdef CMSIS_Driver
|
#if defined(UART_Driver)
|
||||||
|
return 0;
|
||||||
|
#elif defined(CMSIS_Driver)
|
||||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||||
#else
|
#elif defined(LL_Driver)
|
||||||
#ifdef LL_Driver
|
|
||||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||||
#else
|
#else
|
||||||
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
|
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tim_1us_period = OW_TIM_1US_PERIOD;
|
uint32_t tim_1us_period = OW_TIM_1US_PERIOD;
|
||||||
void OneWire_Delay_uw(uint32_t us)
|
void OneWire_Delay_us(uint32_t us)
|
||||||
{
|
{
|
||||||
uint32_t ticks = us * tim_1us_period;
|
uint32_t ticks = us * tim_1us_period;
|
||||||
uint16_t start = OW_TIM->CNT;
|
uint16_t start = OW_TIM->CNT;
|
||||||
@@ -115,8 +113,9 @@ void OneWire_Delay_uw(uint32_t us)
|
|||||||
while (elapsed < ticks)
|
while (elapsed < ticks)
|
||||||
{
|
{
|
||||||
uint16_t curr = OW_TIM->CNT;
|
uint16_t curr = OW_TIM->CNT;
|
||||||
uint16_t delta = (uint16_t)(curr - prev); // ó÷¸ò ïåðåïîëíåíèÿ
|
uint16_t delta = (uint16_t)(curr - prev); // учЄт переполнени¤
|
||||||
elapsed += delta;
|
elapsed += delta;
|
||||||
prev = curr;
|
prev = curr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,60 @@
|
|||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
/* I/O Port ------------------------------------------------------------------*/
|
/* I/O Port ------------------------------------------------------------------*/
|
||||||
//#define LL_Driver
|
#define UART_Driver ///< использовтаь UART (onewire_uart.c/.h)
|
||||||
#define CMSIS_Driver
|
//#define LL_Driver ///< использовать CMSIS для управления ножкой
|
||||||
|
#define CMSIS_Driver ///< использовать CMSIS для управления ножкой
|
||||||
|
// если ничего не выбрано - используется HAL
|
||||||
|
|
||||||
|
|
||||||
#define DS_GPIO_Port GPIOB
|
/**
|
||||||
#define DS_Pin_Numb 0
|
* @defgroup DEFAULT_SETTINGS Дефолтные параметры для OW
|
||||||
#define DS_Pin (1<<DS_Pin_Numb)
|
* @details Определены дефолтные параметры для OW, применятся если передать NULL в Dallas_BusFirstInit.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Порт вывода для шины 1-Wire.
|
||||||
|
* @details Указывает порт GPIO, к которому подключена линия данных 1-Wire (например, для DS18B20).
|
||||||
|
*/
|
||||||
|
#define OW_UART_Handle huart1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Порт вывода для шины 1-Wire.
|
||||||
|
* @details Указывает порт GPIO, к которому подключена линия данных 1-Wire (например, для DS18B20).
|
||||||
|
*/
|
||||||
|
#define OW_GPIO_Port GPIOA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Маска пина, соответствующая номеру OW_Pin_Numb.
|
||||||
|
* @details Используется при доступе к регистрам порта для управления состоянием линии 1-Wire.
|
||||||
|
*/
|
||||||
|
#define OW_Pin (GPIO_PIN_9)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Аппаратный таймер для формирования временных интервалов протокола 1-Wire.
|
||||||
|
* @details Применяется для создания точных задержек при обмене данными по шине 1-Wire.
|
||||||
|
*/
|
||||||
#define OW_TIM TIM3
|
#define OW_TIM TIM3
|
||||||
#define OW_TIM_1US_PERIOD 24
|
|
||||||
|
/**
|
||||||
|
* @brief Количество тактов таймера OW_TIM, соответствующее 1 микросекунде.
|
||||||
|
* @details Вычисляется на основе частоты таймера. Например, для таймера с частотой 24 МГц значение будет равно 24.
|
||||||
|
*/
|
||||||
|
#define OW_TIM_1US_PERIOD 72
|
||||||
|
|
||||||
|
|
||||||
|
/** DEFAULT_SETTINGS
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
/* OneWire Timings -----------------------------------------------------------*/
|
/* OneWire Timings -----------------------------------------------------------*/
|
||||||
void OneWire_Delay_uw(uint32_t us);
|
void OneWire_Delay_us(uint32_t us);
|
||||||
/* Common Register -----------------------------------------------------------*/
|
/* Common Register -----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(UART_Driver)
|
||||||
|
#include "onewire_uart.h"
|
||||||
|
#include "usart.h"
|
||||||
|
#endif
|
||||||
#endif /* ONEWIRE_PORT_H */
|
#endif /* ONEWIRE_PORT_H */
|
||||||
|
|||||||
102
README.md
102
README.md
@@ -1,3 +1,101 @@
|
|||||||
# DS18B20_Library
|
# Библиотека для работы с датчиками температуры DS18B20 по 1-Wire
|
||||||
|
|
||||||
Библиотека для работы с датчиками температуры Dallas DS18B20 по 1-Wire
|
---
|
||||||
|
|
||||||
|
## Описание
|
||||||
|
|
||||||
|
Данная библиотека предоставляет драйвер для работы с цифровыми температурными датчиками DS18B20, подключёнными по однопроводному интерфейсу 1-Wire. Библиотека поддерживает:
|
||||||
|
- Инициализация шины 1-Wire и обнаружение всех датчиков на шине
|
||||||
|
- Инициализация датчика по:
|
||||||
|
- ROM-адресу
|
||||||
|
- Пользовательским байтам (TH, TL, UserByte3, UserByte4)
|
||||||
|
- Индексу (порядковому номеру) найденного устройства
|
||||||
|
- Запуск преобразования температуры у всех или отдельных датчиков с выбором метода ожидания окончания преобразования (по шине или задержкой)
|
||||||
|
- Чтение температуры и проверка статуса подключения датчика
|
||||||
|
- Возможность замены потерянного датчика в структуре
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Быстрый старт
|
||||||
|
|
||||||
|
### 1. Настройка порта и таймера для 1-Wire (файл `ow_port.h`):
|
||||||
|
```c
|
||||||
|
#define OW_GPIO_Port GPIOB
|
||||||
|
#define OW_Pin_Numb 0
|
||||||
|
#define OW_Pin (1 << OW_Pin_Numb)
|
||||||
|
#define OW_TIM TIM3
|
||||||
|
#define OW_TIM_1US_PERIOD 24
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Подключение библиотеки и инициализация таймера:
|
||||||
|
```c
|
||||||
|
#include "dallas_tools.h"
|
||||||
|
|
||||||
|
MX_TIM_Init(); // Инициализация таймера (например, TIM3)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Инициализация шины и поиск датчиков:
|
||||||
|
```c
|
||||||
|
Dallas_BusFirstInit(&htim);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Инициализация структуры датчика по одному из методов:
|
||||||
|
```c
|
||||||
|
// Объявление хендлов датчиков
|
||||||
|
DALLAS_SensorHandleTypeDef sens;
|
||||||
|
|
||||||
|
// Инициализация по индексу (порядковому номеру найденного датчика)
|
||||||
|
sens1.Init.init_func = &Dallas_SensorInitByInd;
|
||||||
|
sens1.Init.InitParam.Ind = 0;
|
||||||
|
|
||||||
|
// Инициализация по ROM-адресу
|
||||||
|
sens.Init.init_func = &Dallas_SensorInitByROM;
|
||||||
|
sens.Init.InitParam.ROM = rom_address;
|
||||||
|
|
||||||
|
// Инициализация по пользовательским байтам
|
||||||
|
sens.Init.init_func = &Dallas_SensorInitByUserBytes;
|
||||||
|
sens.Init.InitParam.UserBytes.UserByte1 = 1;
|
||||||
|
sens.Init.InitParam.UserBytes.UserByte2 = 2;
|
||||||
|
sens.Init.InitParam.UserBytes.UserByte3 = 3;
|
||||||
|
sens.Init.InitParam.UserBytes.UserByte4 = 4;
|
||||||
|
|
||||||
|
// добавление датчика в структуру sens
|
||||||
|
Dallas_AddNewSensors(&hdallas, &sens);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Запуск измерения и чтение температуры:
|
||||||
|
```c
|
||||||
|
Dallas_StartConvertTAll(&hdallas, DALLAS_WAIT_BUS, 0);
|
||||||
|
Dallas_ReadTemperature(&sens);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Функции
|
||||||
|
|
||||||
|
| Функция | Описание |
|
||||||
|
| -------------------------------------------------------- | ---------------------------------------------------------- |
|
||||||
|
| `Dallas_BusFirstInit(&htim)` | Инициализация шины 1-Wire, запуск таймера и поиск датчиков |
|
||||||
|
| `Dallas_AddNewSensors(&hdallas, &sensor)` | Инициализация структуры датчика и добавление в работу |
|
||||||
|
| `Dallas_ReplaceLostedSensor(&sensor)` | Замена потерянного датчика на новый, если доступен |
|
||||||
|
| `Dallas_StartConvertTAll(&hdallas, waitCondition, delay)` | Запуск преобразования температуры на всех датчиках |
|
||||||
|
| `Dallas_ConvertT(&sensor, waitCondition)` | Запуск преобразования температуры на одном датчике |
|
||||||
|
| `Dallas_ReadTemperature(&sensor)` | Чтение температуры с датчика |
|
||||||
|
| `Dallas_IsConnected(&sensor)` | Проверка подключения датчика (чтение scratchpad) |
|
||||||
|
| `Dallas_WriteUserBytes(&sensor, bytes12, bytes34, mask)` | Запись пользовательских байт в датчик |
|
||||||
|
|
||||||
|
|
||||||
|
## Требуемые зависимости
|
||||||
|
|
||||||
|
- Драйвер 1-Wire (`onewire.c/h`, `ow_port.c/h`)
|
||||||
|
- Драйвер DS18B20 (`ds18b20_driver.c/h`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Примечания
|
||||||
|
- Функции работы с датчиками возвращают статус в формате `HAL_StatusTypeDef`.
|
||||||
|
- Ожидание окончания преобразования температуры настраивается через `DALLAS_WaitConvertionTypeDef`:
|
||||||
|
- `DALLAS_WAIT_BUS` — ожидание по состоянию линии 1-Wire.
|
||||||
|
- `DALLAS_WAIT_DELAY` — фиксированная задержка, зависящая от выбранного разрешения.
|
||||||
|
- `DALLAS_WAIT_NONE` — без ожидания (асинхронный режим).
|
||||||
|
- При потере связи с датчиком функция `Dallas_IsConnected` помечает датчик как потерянный. Для восстановления работы можно вызвать `Dallas_ReplaceLostedSensor`, она будет искать датчик и пытаться его инициализировать по заданной функции инициализации.
|
||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -36,6 +36,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
/* Exported types ------------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN ET */
|
/* USER CODE BEGIN ET */
|
||||||
|
|
||||||
/* USER CODE END ET */
|
/* USER CODE END ET */
|
||||||
|
|
||||||
/* Exported constants --------------------------------------------------------*/
|
/* Exported constants --------------------------------------------------------*/
|
||||||
@@ -55,7 +55,6 @@ void SVC_Handler(void);
|
|||||||
void DebugMon_Handler(void);
|
void DebugMon_Handler(void);
|
||||||
void PendSV_Handler(void);
|
void PendSV_Handler(void);
|
||||||
void SysTick_Handler(void);
|
void SysTick_Handler(void);
|
||||||
void TIM3_IRQHandler(void);
|
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
/* USER CODE END EFP */
|
/* USER CODE END EFP */
|
||||||
@@ -54,7 +54,7 @@ void MX_GPIO_Init(void)
|
|||||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
|
||||||
|
|
||||||
/*Configure GPIO pin Output Level */
|
/*Configure GPIO pin Output Level */
|
||||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
|
||||||
|
|
||||||
/*Configure GPIO pin : PC13 */
|
/*Configure GPIO pin : PC13 */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_13;
|
GPIO_InitStruct.Pin = GPIO_PIN_13;
|
||||||
@@ -63,8 +63,8 @@ void MX_GPIO_Init(void)
|
|||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pin : PB10 */
|
/*Configure GPIO pin : PB0 */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_10;
|
GPIO_InitStruct.Pin = GPIO_PIN_0;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN Includes */
|
/* USER CODE BEGIN Includes */
|
||||||
#include "pch_sensors.h"
|
#include "dallas_tools.h"
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
@@ -56,6 +56,7 @@ void SystemClock_Config(void);
|
|||||||
|
|
||||||
/* Private user code ---------------------------------------------------------*/
|
/* Private user code ---------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN 0 */
|
/* USER CODE BEGIN 0 */
|
||||||
|
DALLAS_SensorHandleTypeDef sens;
|
||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,31 +88,28 @@ int main(void)
|
|||||||
|
|
||||||
/* Initialize all configured peripherals */
|
/* Initialize all configured peripherals */
|
||||||
MX_GPIO_Init();
|
MX_GPIO_Init();
|
||||||
MX_USART1_UART_Init();
|
|
||||||
MX_TIM3_Init();
|
MX_TIM3_Init();
|
||||||
|
MX_USART1_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
#ifndef UART_Driver
|
||||||
/* Initialize DWT Delay */
|
Dallas_BusFirstInit(&hdallas, OW_GPIO_Port, OW_Pin);
|
||||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
#else
|
||||||
DwtInit();
|
Dallas_BusFirstInit(&hdallas, &huart1);
|
||||||
/* Set parameter and initialize DS18B20 */
|
#endif
|
||||||
/* Initialize OneWire and reset all data */
|
sens.Init.InitParam.Ind = 0;
|
||||||
PCHSens_FirstInit();
|
sens.Init.init_func = &Dallas_SensorInitByInd;
|
||||||
|
sens.Init.Resolution = DALLAS_CONFIG_12_BITS;
|
||||||
|
Dallas_AddNewSensors(&hdallas, &sens);
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
/* USER CODE BEGIN WHILE */
|
/* USER CODE BEGIN WHILE */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
PCHSens_ModuleReadTemperature(&module1);
|
Dallas_StartConvertTAll(&hdallas, DALLAS_WAIT_BUS, 0);
|
||||||
// Dallas_ReadAll();
|
Dallas_ReadTemperature(&sens);
|
||||||
/* Start temperature conversion on all devices on one bus */
|
|
||||||
// DS18B20_StartConvTAll(&OW);
|
|
||||||
// DS18B20_WaitForEndConvertion(&OW);
|
|
||||||
|
|
||||||
|
GPIOC->ODR ^= (1<<13);
|
||||||
/* Search Alarm triggered and store in DS data structure */
|
|
||||||
// DS18B20_AlarmSearch(&DS, &OW);
|
|
||||||
/* USER CODE END WHILE */
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
/* USER CODE BEGIN 3 */
|
/* USER CODE BEGIN 3 */
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
|
|
||||||
/* External variables --------------------------------------------------------*/
|
/* External variables --------------------------------------------------------*/
|
||||||
extern TIM_HandleTypeDef htim3;
|
|
||||||
/* USER CODE BEGIN EV */
|
/* USER CODE BEGIN EV */
|
||||||
|
|
||||||
/* USER CODE END EV */
|
/* USER CODE END EV */
|
||||||
@@ -198,20 +198,6 @@ void SysTick_Handler(void)
|
|||||||
/* please refer to the startup file (startup_stm32f1xx.s). */
|
/* please refer to the startup file (startup_stm32f1xx.s). */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function handles TIM3 global interrupt.
|
|
||||||
*/
|
|
||||||
void TIM3_IRQHandler(void)
|
|
||||||
{
|
|
||||||
/* USER CODE BEGIN TIM3_IRQn 0 */
|
|
||||||
|
|
||||||
/* USER CODE END TIM3_IRQn 0 */
|
|
||||||
HAL_TIM_IRQHandler(&htim3);
|
|
||||||
/* USER CODE BEGIN TIM3_IRQn 1 */
|
|
||||||
|
|
||||||
/* USER CODE END TIM3_IRQn 1 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* USER CODE BEGIN 1 */
|
/* USER CODE BEGIN 1 */
|
||||||
|
|
||||||
/* USER CODE END 1 */
|
/* USER CODE END 1 */
|
||||||
@@ -43,7 +43,7 @@ void MX_TIM3_Init(void)
|
|||||||
htim3.Instance = TIM3;
|
htim3.Instance = TIM3;
|
||||||
htim3.Init.Prescaler = 0;
|
htim3.Init.Prescaler = 0;
|
||||||
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
|
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||||
htim3.Init.Period = 72-1;
|
htim3.Init.Period = 65535;
|
||||||
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
|
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
|
||||||
@@ -77,10 +77,6 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
|
|||||||
/* USER CODE END TIM3_MspInit 0 */
|
/* USER CODE END TIM3_MspInit 0 */
|
||||||
/* TIM3 clock enable */
|
/* TIM3 clock enable */
|
||||||
__HAL_RCC_TIM3_CLK_ENABLE();
|
__HAL_RCC_TIM3_CLK_ENABLE();
|
||||||
|
|
||||||
/* TIM3 interrupt Init */
|
|
||||||
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
|
|
||||||
HAL_NVIC_EnableIRQ(TIM3_IRQn);
|
|
||||||
/* USER CODE BEGIN TIM3_MspInit 1 */
|
/* USER CODE BEGIN TIM3_MspInit 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM3_MspInit 1 */
|
/* USER CODE END TIM3_MspInit 1 */
|
||||||
@@ -97,9 +93,6 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
|
|||||||
/* USER CODE END TIM3_MspDeInit 0 */
|
/* USER CODE END TIM3_MspDeInit 0 */
|
||||||
/* Peripheral clock disable */
|
/* Peripheral clock disable */
|
||||||
__HAL_RCC_TIM3_CLK_DISABLE();
|
__HAL_RCC_TIM3_CLK_DISABLE();
|
||||||
|
|
||||||
/* TIM3 interrupt Deinit */
|
|
||||||
HAL_NVIC_DisableIRQ(TIM3_IRQn);
|
|
||||||
/* USER CODE BEGIN TIM3_MspDeInit 1 */
|
/* USER CODE BEGIN TIM3_MspDeInit 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM3_MspDeInit 1 */
|
/* USER CODE END TIM3_MspDeInit 1 */
|
||||||
@@ -74,7 +74,6 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
|
|||||||
*/
|
*/
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_9;
|
GPIO_InitStruct.Pin = GPIO_PIN_9;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
58
test/Drivers/CMSIS/Core/Template/ARMv8-M/main_s.c
Normal file
58
test/Drivers/CMSIS/Core/Template/ARMv8-M/main_s.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file main_s.c
|
||||||
|
* @brief Code template for secure main function
|
||||||
|
* @version V1.1.1
|
||||||
|
* @date 10. January 2018
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Use CMSE intrinsics */
|
||||||
|
#include <arm_cmse.h>
|
||||||
|
|
||||||
|
#include "RTE_Components.h"
|
||||||
|
#include CMSIS_device_header
|
||||||
|
|
||||||
|
/* TZ_START_NS: Start address of non-secure application */
|
||||||
|
#ifndef TZ_START_NS
|
||||||
|
#define TZ_START_NS (0x200000U)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* typedef for non-secure callback functions */
|
||||||
|
typedef void (*funcptr_void) (void) __attribute__((cmse_nonsecure_call));
|
||||||
|
|
||||||
|
/* Secure main() */
|
||||||
|
int main(void) {
|
||||||
|
funcptr_void NonSecure_ResetHandler;
|
||||||
|
|
||||||
|
/* Add user setup code for secure part here*/
|
||||||
|
|
||||||
|
/* Set non-secure main stack (MSP_NS) */
|
||||||
|
__TZ_set_MSP_NS(*((uint32_t *)(TZ_START_NS)));
|
||||||
|
|
||||||
|
/* Get non-secure reset handler */
|
||||||
|
NonSecure_ResetHandler = (funcptr_void)(*((uint32_t *)((TZ_START_NS) + 4U)));
|
||||||
|
|
||||||
|
/* Start non-secure state software application */
|
||||||
|
NonSecure_ResetHandler();
|
||||||
|
|
||||||
|
/* Non-secure software does not return, this code is not executed */
|
||||||
|
while (1) {
|
||||||
|
__NOP();
|
||||||
|
}
|
||||||
|
}
|
||||||
200
test/Drivers/CMSIS/Core/Template/ARMv8-M/tz_context.c
Normal file
200
test/Drivers/CMSIS/Core/Template/ARMv8-M/tz_context.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file tz_context.c
|
||||||
|
* @brief Context Management for Armv8-M TrustZone - Sample implementation
|
||||||
|
* @version V1.1.1
|
||||||
|
* @date 10. January 2018
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2018 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RTE_Components.h"
|
||||||
|
#include CMSIS_device_header
|
||||||
|
#include "tz_context.h"
|
||||||
|
|
||||||
|
/// Number of process slots (threads may call secure library code)
|
||||||
|
#ifndef TZ_PROCESS_STACK_SLOTS
|
||||||
|
#define TZ_PROCESS_STACK_SLOTS 8U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Stack size of the secure library code
|
||||||
|
#ifndef TZ_PROCESS_STACK_SIZE
|
||||||
|
#define TZ_PROCESS_STACK_SIZE 256U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sp_top; // stack space top
|
||||||
|
uint32_t sp_limit; // stack space limit
|
||||||
|
uint32_t sp; // current stack pointer
|
||||||
|
} stack_info_t;
|
||||||
|
|
||||||
|
static stack_info_t ProcessStackInfo [TZ_PROCESS_STACK_SLOTS];
|
||||||
|
static uint64_t ProcessStackMemory[TZ_PROCESS_STACK_SLOTS][TZ_PROCESS_STACK_SIZE/8U];
|
||||||
|
static uint32_t ProcessStackFreeSlot = 0xFFFFFFFFU;
|
||||||
|
|
||||||
|
|
||||||
|
/// Initialize secure context memory system
|
||||||
|
/// \return execution status (1: success, 0: error)
|
||||||
|
__attribute__((cmse_nonsecure_entry))
|
||||||
|
uint32_t TZ_InitContextSystem_S (void) {
|
||||||
|
uint32_t n;
|
||||||
|
|
||||||
|
if (__get_IPSR() == 0U) {
|
||||||
|
return 0U; // Thread Mode
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0U; n < TZ_PROCESS_STACK_SLOTS; n++) {
|
||||||
|
ProcessStackInfo[n].sp = 0U;
|
||||||
|
ProcessStackInfo[n].sp_limit = (uint32_t)&ProcessStackMemory[n];
|
||||||
|
ProcessStackInfo[n].sp_top = (uint32_t)&ProcessStackMemory[n] + TZ_PROCESS_STACK_SIZE;
|
||||||
|
*((uint32_t *)ProcessStackMemory[n]) = n + 1U;
|
||||||
|
}
|
||||||
|
*((uint32_t *)ProcessStackMemory[--n]) = 0xFFFFFFFFU;
|
||||||
|
|
||||||
|
ProcessStackFreeSlot = 0U;
|
||||||
|
|
||||||
|
// Default process stack pointer and stack limit
|
||||||
|
__set_PSPLIM((uint32_t)ProcessStackMemory);
|
||||||
|
__set_PSP ((uint32_t)ProcessStackMemory);
|
||||||
|
|
||||||
|
// Privileged Thread Mode using PSP
|
||||||
|
__set_CONTROL(0x02U);
|
||||||
|
|
||||||
|
return 1U; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Allocate context memory for calling secure software modules in TrustZone
|
||||||
|
/// \param[in] module identifies software modules called from non-secure mode
|
||||||
|
/// \return value != 0 id TrustZone memory slot identifier
|
||||||
|
/// \return value 0 no memory available or internal error
|
||||||
|
__attribute__((cmse_nonsecure_entry))
|
||||||
|
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module) {
|
||||||
|
uint32_t slot;
|
||||||
|
|
||||||
|
(void)module; // Ignore (fixed Stack size)
|
||||||
|
|
||||||
|
if (__get_IPSR() == 0U) {
|
||||||
|
return 0U; // Thread Mode
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProcessStackFreeSlot == 0xFFFFFFFFU) {
|
||||||
|
return 0U; // No slot available
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = ProcessStackFreeSlot;
|
||||||
|
ProcessStackFreeSlot = *((uint32_t *)ProcessStackMemory[slot]);
|
||||||
|
|
||||||
|
ProcessStackInfo[slot].sp = ProcessStackInfo[slot].sp_top;
|
||||||
|
|
||||||
|
return (slot + 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
|
||||||
|
/// \param[in] id TrustZone memory slot identifier
|
||||||
|
/// \return execution status (1: success, 0: error)
|
||||||
|
__attribute__((cmse_nonsecure_entry))
|
||||||
|
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id) {
|
||||||
|
uint32_t slot;
|
||||||
|
|
||||||
|
if (__get_IPSR() == 0U) {
|
||||||
|
return 0U; // Thread Mode
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
|
||||||
|
return 0U; // Invalid ID
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = id - 1U;
|
||||||
|
|
||||||
|
if (ProcessStackInfo[slot].sp == 0U) {
|
||||||
|
return 0U; // Inactive slot
|
||||||
|
}
|
||||||
|
ProcessStackInfo[slot].sp = 0U;
|
||||||
|
|
||||||
|
*((uint32_t *)ProcessStackMemory[slot]) = ProcessStackFreeSlot;
|
||||||
|
ProcessStackFreeSlot = slot;
|
||||||
|
|
||||||
|
return 1U; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Load secure context (called on RTOS thread context switch)
|
||||||
|
/// \param[in] id TrustZone memory slot identifier
|
||||||
|
/// \return execution status (1: success, 0: error)
|
||||||
|
__attribute__((cmse_nonsecure_entry))
|
||||||
|
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id) {
|
||||||
|
uint32_t slot;
|
||||||
|
|
||||||
|
if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
|
||||||
|
return 0U; // Thread Mode or using Main Stack for threads
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
|
||||||
|
return 0U; // Invalid ID
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = id - 1U;
|
||||||
|
|
||||||
|
if (ProcessStackInfo[slot].sp == 0U) {
|
||||||
|
return 0U; // Inactive slot
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup process stack pointer and stack limit
|
||||||
|
__set_PSPLIM(ProcessStackInfo[slot].sp_limit);
|
||||||
|
__set_PSP (ProcessStackInfo[slot].sp);
|
||||||
|
|
||||||
|
return 1U; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Store secure context (called on RTOS thread context switch)
|
||||||
|
/// \param[in] id TrustZone memory slot identifier
|
||||||
|
/// \return execution status (1: success, 0: error)
|
||||||
|
__attribute__((cmse_nonsecure_entry))
|
||||||
|
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) {
|
||||||
|
uint32_t slot;
|
||||||
|
uint32_t sp;
|
||||||
|
|
||||||
|
if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
|
||||||
|
return 0U; // Thread Mode or using Main Stack for threads
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
|
||||||
|
return 0U; // Invalid ID
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = id - 1U;
|
||||||
|
|
||||||
|
if (ProcessStackInfo[slot].sp == 0U) {
|
||||||
|
return 0U; // Inactive slot
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = __get_PSP();
|
||||||
|
if ((sp < ProcessStackInfo[slot].sp_limit) ||
|
||||||
|
(sp > ProcessStackInfo[slot].sp_top)) {
|
||||||
|
return 0U; // SP out of range
|
||||||
|
}
|
||||||
|
ProcessStackInfo[slot].sp = sp;
|
||||||
|
|
||||||
|
// Default process stack pointer and stack limit
|
||||||
|
__set_PSPLIM((uint32_t)ProcessStackMemory);
|
||||||
|
__set_PSP ((uint32_t)ProcessStackMemory);
|
||||||
|
|
||||||
|
return 1U; // Success
|
||||||
|
}
|
||||||
544
test/Drivers/CMSIS/Core_A/Include/cmsis_armcc.h
Normal file
544
test/Drivers/CMSIS/Core_A/Include/cmsis_armcc.h
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_armcc.h
|
||||||
|
* @brief CMSIS compiler specific macros, functions, instructions
|
||||||
|
* @version V1.0.2
|
||||||
|
* @date 10. January 2018
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CMSIS_ARMCC_H
|
||||||
|
#define __CMSIS_ARMCC_H
|
||||||
|
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
|
||||||
|
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CMSIS compiler control architecture macros */
|
||||||
|
#if (defined (__TARGET_ARCH_7_A ) && (__TARGET_ARCH_7_A == 1))
|
||||||
|
#define __ARM_ARCH_7A__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CMSIS compiler specific defines */
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __FORCEINLINE
|
||||||
|
#define __FORCEINLINE __forceinline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE static __forceinline
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#define __NO_RETURN __declspec(noreturn)
|
||||||
|
#endif
|
||||||
|
#ifndef CMSIS_DEPRECATED
|
||||||
|
#define CMSIS_DEPRECATED __attribute__((deprecated))
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT __packed struct
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ########################## Core Instruction Access ######################### */
|
||||||
|
/**
|
||||||
|
\brief No Operation
|
||||||
|
*/
|
||||||
|
#define __NOP __nop
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Interrupt
|
||||||
|
*/
|
||||||
|
#define __WFI __wfi
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Event
|
||||||
|
*/
|
||||||
|
#define __WFE __wfe
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Send Event
|
||||||
|
*/
|
||||||
|
#define __SEV __sev
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Instruction Synchronization Barrier
|
||||||
|
*/
|
||||||
|
#define __ISB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__isb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Synchronization Barrier
|
||||||
|
*/
|
||||||
|
#define __DSB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__dsb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Memory Barrier
|
||||||
|
*/
|
||||||
|
#define __DMB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__dmb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (32 bit)
|
||||||
|
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __REV __rev
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#ifndef __NO_EMBEDDED_ASM
|
||||||
|
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||||
|
{
|
||||||
|
rev16 r0, r0
|
||||||
|
bx lr
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#ifndef __NO_EMBEDDED_ASM
|
||||||
|
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
|
||||||
|
{
|
||||||
|
revsh r0, r0
|
||||||
|
bx lr
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Rotate Right in unsigned value (32 bit)
|
||||||
|
\param [in] op1 Value to rotate
|
||||||
|
\param [in] op2 Number of Bits to rotate
|
||||||
|
\return Rotated value
|
||||||
|
*/
|
||||||
|
#define __ROR __ror
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Breakpoint
|
||||||
|
\param [in] value is ignored by the processor.
|
||||||
|
If required, a debugger can use it to store additional information about the breakpoint.
|
||||||
|
*/
|
||||||
|
#define __BKPT(value) __breakpoint(value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse bit order of value
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __RBIT __rbit
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Count leading zeros
|
||||||
|
\param [in] value Value to count the leading zeros
|
||||||
|
\return number of leading zeros in value
|
||||||
|
*/
|
||||||
|
#define __CLZ __clz
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 8 bit value.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint8_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 16 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint16_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 32 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint32_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 8 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 16 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 32 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Remove the exclusive lock
|
||||||
|
\details Removes the exclusive lock which is created by LDREX.
|
||||||
|
*/
|
||||||
|
#define __CLREX __clrex
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Signed Saturate
|
||||||
|
\details Saturates a signed value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (1..32)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __SSAT __ssat
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Unsigned Saturate
|
||||||
|
\details Saturates an unsigned value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (0..31)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __USAT __usat
|
||||||
|
|
||||||
|
/* ########################### Core Function Access ########################### */
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get FPSCR (Floating Point Status/Control)
|
||||||
|
\return Floating Point Status/Control register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||||
|
{
|
||||||
|
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||||
|
register uint32_t __regfpscr __ASM("fpscr");
|
||||||
|
return(__regfpscr);
|
||||||
|
#else
|
||||||
|
return(0U);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set FPSCR (Floating Point Status/Control)
|
||||||
|
\param [in] fpscr Floating Point Status/Control value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||||
|
{
|
||||||
|
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||||
|
register uint32_t __regfpscr __ASM("fpscr");
|
||||||
|
__regfpscr = (fpscr);
|
||||||
|
#else
|
||||||
|
(void)fpscr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get CPSR (Current Program Status Register)
|
||||||
|
\return CPSR Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_CPSR(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regCPSR __ASM("cpsr");
|
||||||
|
return(__regCPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Set CPSR (Current Program Status Register)
|
||||||
|
\param [in] cpsr CPSR value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_CPSR(uint32_t cpsr)
|
||||||
|
{
|
||||||
|
register uint32_t __regCPSR __ASM("cpsr");
|
||||||
|
__regCPSR = cpsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get Mode
|
||||||
|
\return Processor Mode
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_mode(void)
|
||||||
|
{
|
||||||
|
return (__get_CPSR() & 0x1FU);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set Mode
|
||||||
|
\param [in] mode Mode value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM void __set_mode(uint32_t mode)
|
||||||
|
{
|
||||||
|
MOV r1, lr
|
||||||
|
MSR CPSR_C, r0
|
||||||
|
BX r1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get Stack Pointer
|
||||||
|
\return Stack Pointer
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM uint32_t __get_SP(void)
|
||||||
|
{
|
||||||
|
MOV r0, sp
|
||||||
|
BX lr
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set Stack Pointer
|
||||||
|
\param [in] stack Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM void __set_SP(uint32_t stack)
|
||||||
|
{
|
||||||
|
MOV sp, r0
|
||||||
|
BX lr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Get USR/SYS Stack Pointer
|
||||||
|
\return USR/SYSStack Pointer
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM uint32_t __get_SP_usr(void)
|
||||||
|
{
|
||||||
|
ARM
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
MRS R1, CPSR
|
||||||
|
CPS #0x1F ;no effect in USR mode
|
||||||
|
MOV R0, SP
|
||||||
|
MSR CPSR_c, R1 ;no effect in USR mode
|
||||||
|
ISB
|
||||||
|
BX LR
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set USR/SYS Stack Pointer
|
||||||
|
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
|
||||||
|
{
|
||||||
|
ARM
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
MRS R1, CPSR
|
||||||
|
CPS #0x1F ;no effect in USR mode
|
||||||
|
MOV SP, R0
|
||||||
|
MSR CPSR_c, R1 ;no effect in USR mode
|
||||||
|
ISB
|
||||||
|
BX LR
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get FPEXC (Floating Point Exception Control Register)
|
||||||
|
\return Floating Point Exception Control Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_FPEXC(void)
|
||||||
|
{
|
||||||
|
#if (__FPU_PRESENT == 1)
|
||||||
|
register uint32_t __regfpexc __ASM("fpexc");
|
||||||
|
return(__regfpexc);
|
||||||
|
#else
|
||||||
|
return(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set FPEXC (Floating Point Exception Control Register)
|
||||||
|
\param [in] fpexc Floating Point Exception Control value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
|
||||||
|
{
|
||||||
|
#if (__FPU_PRESENT == 1)
|
||||||
|
register uint32_t __regfpexc __ASM("fpexc");
|
||||||
|
__regfpexc = (fpexc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include common core functions to access Coprocessor 15 registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __get_CP(cp, op1, Rt, CRn, CRm, op2) do { register volatile uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); (Rt) = tmp; } while(0)
|
||||||
|
#define __set_CP(cp, op1, Rt, CRn, CRm, op2) do { register volatile uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); tmp = (Rt); } while(0)
|
||||||
|
#define __get_CP64(cp, op1, Rt, CRm) \
|
||||||
|
do { \
|
||||||
|
uint32_t ltmp, htmp; \
|
||||||
|
__ASM volatile("MRRC p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
|
||||||
|
(Rt) = ((((uint64_t)htmp) << 32U) | ((uint64_t)ltmp)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define __set_CP64(cp, op1, Rt, CRm) \
|
||||||
|
do { \
|
||||||
|
const uint64_t tmp = (Rt); \
|
||||||
|
const uint32_t ltmp = (uint32_t)(tmp); \
|
||||||
|
const uint32_t htmp = (uint32_t)(tmp >> 32U); \
|
||||||
|
__ASM volatile("MCRR p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#include "cmsis_cp15.h"
|
||||||
|
|
||||||
|
/** \brief Enable Floating Point Unit
|
||||||
|
|
||||||
|
Critical section, called from undef handler, so systick is disabled
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE __ASM void __FPU_Enable(void)
|
||||||
|
{
|
||||||
|
ARM
|
||||||
|
|
||||||
|
//Permit access to VFP/NEON, registers by modifying CPACR
|
||||||
|
MRC p15,0,R1,c1,c0,2
|
||||||
|
ORR R1,R1,#0x00F00000
|
||||||
|
MCR p15,0,R1,c1,c0,2
|
||||||
|
|
||||||
|
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
|
||||||
|
ISB
|
||||||
|
|
||||||
|
//Enable VFP/NEON
|
||||||
|
VMRS R1,FPEXC
|
||||||
|
ORR R1,R1,#0x40000000
|
||||||
|
VMSR FPEXC,R1
|
||||||
|
|
||||||
|
//Initialise VFP/NEON registers to 0
|
||||||
|
MOV R2,#0
|
||||||
|
|
||||||
|
//Initialise D16 registers to 0
|
||||||
|
VMOV D0, R2,R2
|
||||||
|
VMOV D1, R2,R2
|
||||||
|
VMOV D2, R2,R2
|
||||||
|
VMOV D3, R2,R2
|
||||||
|
VMOV D4, R2,R2
|
||||||
|
VMOV D5, R2,R2
|
||||||
|
VMOV D6, R2,R2
|
||||||
|
VMOV D7, R2,R2
|
||||||
|
VMOV D8, R2,R2
|
||||||
|
VMOV D9, R2,R2
|
||||||
|
VMOV D10,R2,R2
|
||||||
|
VMOV D11,R2,R2
|
||||||
|
VMOV D12,R2,R2
|
||||||
|
VMOV D13,R2,R2
|
||||||
|
VMOV D14,R2,R2
|
||||||
|
VMOV D15,R2,R2
|
||||||
|
|
||||||
|
IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
|
||||||
|
//Initialise D32 registers to 0
|
||||||
|
VMOV D16,R2,R2
|
||||||
|
VMOV D17,R2,R2
|
||||||
|
VMOV D18,R2,R2
|
||||||
|
VMOV D19,R2,R2
|
||||||
|
VMOV D20,R2,R2
|
||||||
|
VMOV D21,R2,R2
|
||||||
|
VMOV D22,R2,R2
|
||||||
|
VMOV D23,R2,R2
|
||||||
|
VMOV D24,R2,R2
|
||||||
|
VMOV D25,R2,R2
|
||||||
|
VMOV D26,R2,R2
|
||||||
|
VMOV D27,R2,R2
|
||||||
|
VMOV D28,R2,R2
|
||||||
|
VMOV D29,R2,R2
|
||||||
|
VMOV D30,R2,R2
|
||||||
|
VMOV D31,R2,R2
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
//Initialise FPSCR to a known state
|
||||||
|
VMRS R2,FPSCR
|
||||||
|
LDR R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
|
||||||
|
AND R2,R2,R3
|
||||||
|
VMSR FPSCR,R2
|
||||||
|
|
||||||
|
BX LR
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CMSIS_ARMCC_H */
|
||||||
503
test/Drivers/CMSIS/Core_A/Include/cmsis_armclang.h
Normal file
503
test/Drivers/CMSIS/Core_A/Include/cmsis_armclang.h
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_armclang.h
|
||||||
|
* @brief CMSIS compiler specific macros, functions, instructions
|
||||||
|
* @version V1.0.2
|
||||||
|
* @date 10. January 2018
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CMSIS_ARMCLANG_H
|
||||||
|
#define __CMSIS_ARMCLANG_H
|
||||||
|
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
|
||||||
|
#ifndef __ARM_COMPAT_H
|
||||||
|
#include <arm_compat.h> /* Compatibility header for Arm Compiler 5 intrinsics */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CMSIS compiler specific defines */
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __FORCEINLINE
|
||||||
|
#define __FORCEINLINE __attribute__((always_inline))
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#define __NO_RETURN __attribute__((__noreturn__))
|
||||||
|
#endif
|
||||||
|
#ifndef CMSIS_DEPRECATED
|
||||||
|
#define CMSIS_DEPRECATED __attribute__((deprecated))
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed, aligned(1)))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpacked"
|
||||||
|
/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
|
||||||
|
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpacked"
|
||||||
|
/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
|
||||||
|
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpacked"
|
||||||
|
/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
|
||||||
|
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpacked"
|
||||||
|
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ########################## Core Instruction Access ######################### */
|
||||||
|
/**
|
||||||
|
\brief No Operation
|
||||||
|
*/
|
||||||
|
#define __NOP __builtin_arm_nop
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Interrupt
|
||||||
|
*/
|
||||||
|
#define __WFI __builtin_arm_wfi
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Event
|
||||||
|
*/
|
||||||
|
#define __WFE __builtin_arm_wfe
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Send Event
|
||||||
|
*/
|
||||||
|
#define __SEV __builtin_arm_sev
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Instruction Synchronization Barrier
|
||||||
|
*/
|
||||||
|
#define __ISB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__builtin_arm_isb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Synchronization Barrier
|
||||||
|
*/
|
||||||
|
#define __DSB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__builtin_arm_dsb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Memory Barrier
|
||||||
|
*/
|
||||||
|
#define __DMB() do {\
|
||||||
|
__schedule_barrier();\
|
||||||
|
__builtin_arm_dmb(0xF);\
|
||||||
|
__schedule_barrier();\
|
||||||
|
} while (0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (32 bit)
|
||||||
|
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __REV(value) __builtin_bswap32(value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __REV16(value) __ROR(__REV(value), 16)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __REVSH(value) (int16_t)__builtin_bswap16(value)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Rotate Right in unsigned value (32 bit)
|
||||||
|
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||||
|
\param [in] op1 Value to rotate
|
||||||
|
\param [in] op2 Number of Bits to rotate
|
||||||
|
\return Rotated value
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||||
|
{
|
||||||
|
op2 %= 32U;
|
||||||
|
if (op2 == 0U)
|
||||||
|
{
|
||||||
|
return op1;
|
||||||
|
}
|
||||||
|
return (op1 >> op2) | (op1 << (32U - op2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Breakpoint
|
||||||
|
\param [in] value is ignored by the processor.
|
||||||
|
If required, a debugger can use it to store additional information about the breakpoint.
|
||||||
|
*/
|
||||||
|
#define __BKPT(value) __ASM volatile ("bkpt "#value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse bit order of value
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __RBIT __builtin_arm_rbit
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Count leading zeros
|
||||||
|
\param [in] value Value to count the leading zeros
|
||||||
|
\return number of leading zeros in value
|
||||||
|
*/
|
||||||
|
#define __CLZ (uint8_t)__builtin_clz
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 8 bit value.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint8_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDREXB (uint8_t)__builtin_arm_ldrex
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 16 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint16_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDREXH (uint16_t)__builtin_arm_ldrex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 32 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint32_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDREXW (uint32_t)__builtin_arm_ldrex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 8 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#define __STREXB (uint32_t)__builtin_arm_strex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 16 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#define __STREXH (uint32_t)__builtin_arm_strex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 32 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#define __STREXW (uint32_t)__builtin_arm_strex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Remove the exclusive lock
|
||||||
|
\details Removes the exclusive lock which is created by LDREX.
|
||||||
|
*/
|
||||||
|
#define __CLREX __builtin_arm_clrex
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Signed Saturate
|
||||||
|
\details Saturates a signed value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (1..32)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __SSAT __builtin_arm_ssat
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Unsigned Saturate
|
||||||
|
\details Saturates an unsigned value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (0..31)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __USAT __builtin_arm_usat
|
||||||
|
|
||||||
|
|
||||||
|
/* ########################### Core Function Access ########################### */
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get FPSCR
|
||||||
|
\details Returns the current value of the Floating Point Status/Control register.
|
||||||
|
\return Floating Point Status/Control register value
|
||||||
|
*/
|
||||||
|
#define __get_FPSCR __builtin_arm_get_fpscr
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set FPSCR
|
||||||
|
\details Assigns the given value to the Floating Point Status/Control register.
|
||||||
|
\param [in] fpscr Floating Point Status/Control value to set
|
||||||
|
*/
|
||||||
|
#define __set_FPSCR __builtin_arm_set_fpscr
|
||||||
|
|
||||||
|
/** \brief Get CPSR Register
|
||||||
|
\return CPSR Register value
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __get_CPSR(void)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
__ASM volatile("MRS %0, cpsr" : "=r" (result) );
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set CPSR Register
|
||||||
|
\param [in] cpsr CPSR value to set
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get Mode
|
||||||
|
\return Processor Mode
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __get_mode(void)
|
||||||
|
{
|
||||||
|
return (__get_CPSR() & 0x1FU);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set Mode
|
||||||
|
\param [in] mode Mode value to set
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE void __set_mode(uint32_t mode)
|
||||||
|
{
|
||||||
|
__ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get Stack Pointer
|
||||||
|
\return Stack Pointer value
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __get_SP()
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
__ASM volatile("MOV %0, sp" : "=r" (result) : : "memory");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set Stack Pointer
|
||||||
|
\param [in] stack Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE void __set_SP(uint32_t stack)
|
||||||
|
{
|
||||||
|
__ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get USR/SYS Stack Pointer
|
||||||
|
\return USR/SYS Stack Pointer value
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __get_SP_usr()
|
||||||
|
{
|
||||||
|
uint32_t cpsr;
|
||||||
|
uint32_t result;
|
||||||
|
__ASM volatile(
|
||||||
|
"MRS %0, cpsr \n"
|
||||||
|
"CPS #0x1F \n" // no effect in USR mode
|
||||||
|
"MOV %1, sp \n"
|
||||||
|
"MSR cpsr_c, %2 \n" // no effect in USR mode
|
||||||
|
"ISB" : "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set USR/SYS Stack Pointer
|
||||||
|
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
|
||||||
|
{
|
||||||
|
uint32_t cpsr;
|
||||||
|
__ASM volatile(
|
||||||
|
"MRS %0, cpsr \n"
|
||||||
|
"CPS #0x1F \n" // no effect in USR mode
|
||||||
|
"MOV sp, %1 \n"
|
||||||
|
"MSR cpsr_c, %2 \n" // no effect in USR mode
|
||||||
|
"ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Get FPEXC
|
||||||
|
\return Floating Point Exception Control register value
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
|
||||||
|
{
|
||||||
|
#if (__FPU_PRESENT == 1)
|
||||||
|
uint32_t result;
|
||||||
|
__ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
|
||||||
|
return(result);
|
||||||
|
#else
|
||||||
|
return(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Set FPEXC
|
||||||
|
\param [in] fpexc Floating Point Exception Control value to set
|
||||||
|
*/
|
||||||
|
__STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
|
||||||
|
{
|
||||||
|
#if (__FPU_PRESENT == 1)
|
||||||
|
__ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include common core functions to access Coprocessor 15 registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
|
||||||
|
#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
|
||||||
|
#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
|
||||||
|
#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
|
||||||
|
|
||||||
|
#include "cmsis_cp15.h"
|
||||||
|
|
||||||
|
/** \brief Enable Floating Point Unit
|
||||||
|
|
||||||
|
Critical section, called from undef handler, so systick is disabled
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __FPU_Enable(void)
|
||||||
|
{
|
||||||
|
__ASM volatile(
|
||||||
|
//Permit access to VFP/NEON, registers by modifying CPACR
|
||||||
|
" MRC p15,0,R1,c1,c0,2 \n"
|
||||||
|
" ORR R1,R1,#0x00F00000 \n"
|
||||||
|
" MCR p15,0,R1,c1,c0,2 \n"
|
||||||
|
|
||||||
|
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
|
||||||
|
" ISB \n"
|
||||||
|
|
||||||
|
//Enable VFP/NEON
|
||||||
|
" VMRS R1,FPEXC \n"
|
||||||
|
" ORR R1,R1,#0x40000000 \n"
|
||||||
|
" VMSR FPEXC,R1 \n"
|
||||||
|
|
||||||
|
//Initialise VFP/NEON registers to 0
|
||||||
|
" MOV R2,#0 \n"
|
||||||
|
|
||||||
|
//Initialise D16 registers to 0
|
||||||
|
" VMOV D0, R2,R2 \n"
|
||||||
|
" VMOV D1, R2,R2 \n"
|
||||||
|
" VMOV D2, R2,R2 \n"
|
||||||
|
" VMOV D3, R2,R2 \n"
|
||||||
|
" VMOV D4, R2,R2 \n"
|
||||||
|
" VMOV D5, R2,R2 \n"
|
||||||
|
" VMOV D6, R2,R2 \n"
|
||||||
|
" VMOV D7, R2,R2 \n"
|
||||||
|
" VMOV D8, R2,R2 \n"
|
||||||
|
" VMOV D9, R2,R2 \n"
|
||||||
|
" VMOV D10,R2,R2 \n"
|
||||||
|
" VMOV D11,R2,R2 \n"
|
||||||
|
" VMOV D12,R2,R2 \n"
|
||||||
|
" VMOV D13,R2,R2 \n"
|
||||||
|
" VMOV D14,R2,R2 \n"
|
||||||
|
" VMOV D15,R2,R2 \n"
|
||||||
|
|
||||||
|
#if __ARM_NEON == 1
|
||||||
|
//Initialise D32 registers to 0
|
||||||
|
" VMOV D16,R2,R2 \n"
|
||||||
|
" VMOV D17,R2,R2 \n"
|
||||||
|
" VMOV D18,R2,R2 \n"
|
||||||
|
" VMOV D19,R2,R2 \n"
|
||||||
|
" VMOV D20,R2,R2 \n"
|
||||||
|
" VMOV D21,R2,R2 \n"
|
||||||
|
" VMOV D22,R2,R2 \n"
|
||||||
|
" VMOV D23,R2,R2 \n"
|
||||||
|
" VMOV D24,R2,R2 \n"
|
||||||
|
" VMOV D25,R2,R2 \n"
|
||||||
|
" VMOV D26,R2,R2 \n"
|
||||||
|
" VMOV D27,R2,R2 \n"
|
||||||
|
" VMOV D28,R2,R2 \n"
|
||||||
|
" VMOV D29,R2,R2 \n"
|
||||||
|
" VMOV D30,R2,R2 \n"
|
||||||
|
" VMOV D31,R2,R2 \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Initialise FPSCR to a known state
|
||||||
|
" VMRS R2,FPSCR \n"
|
||||||
|
" LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
|
||||||
|
" AND R2,R2,R3 \n"
|
||||||
|
" VMSR FPSCR,R2 "
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CMSIS_ARMCLANG_H */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user