Низкоуровневый spi

Интерфейс SPI в STM32. Часть 2

BIDIMODE – если этот бит установлен, то прием и передача данных осуществляются по одному проводу (не считая SCK). При этом, как я понял, MOSI вывод мастера подключается к MISO слейва. Экзотический режим на мой взгляд 🙂

BIDIOE – этот бит используется в однопроводном режиме. Если он установлен – SPI модуль только передает данные. Если сброшен – то принимает.

CRCEN – включает аппаратный модуль расчёт контрольной суммы. 0 – выкл, 1 – вкл. Изменять состояние этого бита можно только когда SPI модуль выключен (бит SPE=0).

CRCNEXT – если этот бит установлен, то после следующей передачи байта данных, будет отправлена контрольная сумма.

DFF – если бит сброшен, то SPI модуль передает/принимает данные по 8 бит, в противном случаее передается/принимается сразу по 16 бит. Изменять состояние этого бита можно только когда SPI модуль выключен (бит SPE=0).

RXONLY – если используется 2-х проводной режим (см бит BIDIMODE) то установка этого бита запрещает передачу, SPI модуль работает только на приём

Перед описанием следующих двух бит, нужно отметить одну интересную особенность вывода NSS (он же SS он же CS). Если SPI модуль настроен в режиме слейва, то он может получать сигнал с ноги NSS или же программно.

Если бит SSM сброшен, то сигнал SS будет считываться с ноги NSS, а если он установлен, то состояние ноги NSS игноирируется. В таком случае для управления сигналом SS возлагается на бит SSI.

Бит установлен – есть сигнал SS, в противном случае нет. Если же SPI модуль работает в режиме мастера, то ногу NSS нужно подтянуть к питанию или включить программное управление (SSM=1) и установить бит SSI.

В противном случае – SPI модуль подумает, что появился новый мастер и сам станет слейвом. Этот момент для меня был не совсем очевиден и я потратил много времени чтоб разобраться. 

LSBFIRST – задает порядок передачи бит: 0 – сначала передается старший бит

1 – сначала передается младший бит

SPE – выключает/выключает SPI модуль

BR2,BR1,BR0 – задают скорость приема/передачи (частоту SCK). Частота тактирования модуля SPI делится на число, которое задается комбинацией этих трех бит.

BR2 BR1 BR0 Делитель
2
1 4
1 8
1 1 16
1 32
1 1 64
1 1 128
1 1 1 256

Изменять состояние этих бит можно только когда SPI модуль выключен (бит SPE=0).

MSTR – если бит установлен – SPI модуль является мастером, иначе слейвом.

CPOL – полярность сигнала SCK. (см. табличку из прошлой статьи).

CPHA – фаза сигнала SCK (см. табличку из прошлой статьи).

Регистр SPI_CR2

TXEIE – разрешает прерывание, когда буфер передачи пуст (всё передалось)

RXNEIE – разрешает прерывание, когда буфер заполнен данными и их можно забирать.

ERRIE – разрешает прерывание в случае возникновения ошибки. Их всего три, чтоб разобраться какая возникла, нужно смотреть состояние бит в регистре статуса. Об этом чуть ниже.

FRF – Frame format, не разбирался что это такое.

0 –  SPI Motorola mode

1 – SPI TI mode

По умолчанию там ноль, без надобности не трогать 🙂

SSOE – Если этот бит выставлен, то SPI модуль (в режиме мастера разумеется) сам управляет выводом NSS. Т.е. как я понял перед началом передачи выставляет ноль на этом выводе, а после завершения – выставляет единицу. Возможно это не правильно, у меня так и не получилось ничего с этим битом сделать.

TXDMAEN – разрешает/запрещает запрос DMA по завершению передачи

RXDMAEN – разрешает/запрещает запрос DMA по завершению приема

Статусный регистр SPI_SR

FRE – Frame error flag, пока не совсем понятно что это за флаг ошибки, он используется когда SPI модуль работает в режиме «TI mode» (бит FRF=1). Еще он относится к интерфейсу I2S, о нем будет отдельная статья. (не путать с I2C)

BSY – если этот бит установлен, значит модуль SPI сейчас занят передачей данных.

OVR – бит выставляется в том случае, если в SPI модуль поступили новые данные и перетерли старые которые не были прочитаны.

MODF – выставляется в том случае если мастер внезапно перестал быть мастером. Такое возможно когда нога мастера NSS настроена как вход и на неё поступил сигнал низкого уровня.

CRCERR – ошибка контрольной суммы

UDR – флаг не используется в режиме SPI

TXE – Передача данных завершилась

RXNE – Приём данных завершен

Регистр SPI_DR

Представляет собой 16-ти битный регистр данных. На самом деле регистров два – один для передачи, а другой для приёма, но работа с ними осуществляется через один регистр SPI_DR. Если мы что-то в него пишем, то запись данных производится в регистр для передачи. Если читаем, то данные считываются из регистра для приёма данных.

Регистр SPI_CRCPR

Сюда записывают некоторое число, которое как-то должно повлиять на расчет контрольной суммы. По умолчанию там записано число 7.

Регистр SPI_TXCRCR

Сюда записывается контрольная сумма, которая посчиталась для передаваемых данных.

Регистр SPI_RXCRCR

Сюда записывается контрольная сумма, которая посчиталась для принятых данных.

Примеры кода

Теперь настало время для кода. Для первых трёх примеров можно использовать плату STM32F4DISCOVERY. Четвертый пример требует для запуска второй контроллер или еще одну отладочную платку STM32VLDISCOVERY.

Для начала рассмотрим простой пример, коего будет достаточно в 95% всех случаев. Пример показывает как настроить SPI1 в режиме мастера и отправить данные.

В бесконечном цикле происходит передача одного и того же байта (0x93).  

#include “stm32f4xx.h”
#include “stm32f4xx_gpio.h”
#include “stm32f4xx_rcc.h”
#include “stm32f4xx_spi.h” int main(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; // Тактирование модуля SPI1 и порта А RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // Настраиваем ноги SPI1 для работы в режиме альтернативной функции GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5; GPIO_Init(GPIOA, &GPIO_InitStructure); //Заполняем структуру с параметрами SPI модуля SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //полный дуплекс SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // передаем по 8 бит SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // Полярность и SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // фаза тактового сигнала SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // Управлять состоянием сигнала NSS программно SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // Предделитель SCK SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // Первым отправляется старший бит SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // Режим – мастер SPI_Init(SPI1, &SPI_InitStructure); //Настраиваем SPI1 SPI_Cmd(SPI1, ENABLE); // Включаем модуль SPI1…. // Поскольку сигнал NSS контролируется программно, установим его в единицу // Если сбросить его в ноль, то наш SPI модуль подумает, что // у нас мультимастерная топология и его лишили полномочий мастера. SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); while(1) { SPI_I2S_SendData(SPI1, 0x93); //Передаем байт 0x93 через SPI1 while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET) //Передатчик занят? ; // значит ничего не делаем }
}

Следующий пример показывает как данные могут быть приняты тем же модулем SPI который их отправил. Для этого потребуется замкнуть выводы PA7 и PA6. Он стоят рядом, можно просто накинуть перемычку. Если в SPI пришел тот же байт который мы отправили, то загорается зеленый светодиод, в противном случае – красный. 

#include “stm32f4xx.h”
#include “stm32f4xx_gpio.h”
#include “stm32f4xx_rcc.h”
#include “stm32f4xx_spi.h” #define LED_PORT GPIOD
#define LED_GREEN (1

Источник: http://easystm32.ru/45

SPI STM32

Принцип работы протокола рассматривать не будем, он был рассмотрен тут, перейдём сразу к возможностям модуля SPI у STM32:

  • полнодуплексная синхронная передача с использованием 3 линий
  • симплексная синхронная передача с использованием двух линий, возможность использования двунаправленной линии для передачи данных
  • 8 или 16 битный формат фрейма
  • работа в режиме Master или Slave
  • в режиме Master 8 значений прескалера скорости передачи(fPCLK/2 max)
  • в режиме Slave максимальное значение скорости fPCLK/2 max
  • программное и аппаратное управление выводом NSS, возможность динамического переключения Master/Slave
  • полярность и фаза тактового сигнала программируется
  • порядок следования битов программируется(MSB-first или LSB-first)
  • флаг приёма и передачи, с возможностью прерывания при их возникновении
  • флаг занятости шины SPI
  • Аппаратное вычисление CRC для надёжного обмена данными:- значение CRC может передаваться последним байтом при передаче- автоматическая проверка CRC для последнего принятого байта
  • возможность возникновения прерываний по флагам CRC error, overrun и Master mode fault
  • 1-байтовый буфер DMA для передачи и приёма: запросы Tx и Rx

Для передачи данных может использоваться четыре вывода:

Miso(Master In / Slave Out data) — в зависимости от режима вывод может быть настроен как вход или выход, вход в режиме Master и выход в режиме Slave

Mosi(Master Out / Slave In data) – тут наоборот, выход в режиме Master и вход в режиме Slave

SCK – тактовый сигнал, генерируемый Master.

NSS – вывод предназначен для выбора подчинённого устройства в режиме Slave, при подаче на его вход логического ноля, также с помощью этого вывода можно переключать режимы SPI (Master/Slave), в мультимастерной шине.

Итак, вывод NSS работает не совсем так, как привычный CS у AVR, и в режиме Master для выбора ведомого необходимо использовать GPIO.

В режиме Slave сигнал(Сhip Select) можно получить с вывода NSS или программно, зависит это от значения бита SSM, если он сброшен, то считывается состояние вывода NSS, иначе определяющим является состояние бита SSI. Для приёма данных в таком случае(при программном управлении) необходимо установить SSM = 1, SSI = 0.

В режиме Master, вывод необходимо подтянуть к питанию или включить программную подтяжку (SSM =1, SSI = 1). В случае программной подтяжки вывод можно использовать как обычный GPIO.

Возможен ещё один вариант SSM = 0, SSOE = 0, вывод NSS настроен как вход с подтяжкой к питанию, при появлении на нём низкого уровня, SPI модуль подумает что появился новый Master и сам станет Slave, такой вариант используется в мультимастерной шине.

Так выглядит подключение одного Master к Slave.Шина SPI представляет собой два последовательно соединённых между собой сдвиговых регистра и по каждому тактовому импульсу данные в регистрах сдвигаются.

То есть по каждому тактовому импульсу один бит уходит из регистра, остальные биты сдвигаются к выходу, а на входе появляется свободное место, его и занимает вновь пришедший бит.Ниже представлена блочная диаграмма модуля SPI.

На диаграмме видно, что модуль состоит из двух регистров у правления и регистра статуса, давайте рассмотрим какой бит в регистрах за что отвечает. Хотелось отметить, что изменять состояние большинства битов можно только, когда SPI выключен(SPE = 0).

Регистр управления SPI_CR1:

BIDIMODE(Bidirectional data mode enable) — если записать в этот бит единицу данные будут передаваться в двух направлениях по одной линии(однопроводной режим), если ноль —по двум линиям. При двунаправленной передаче master использует вывод MOSI, а slave вывод MISO.

BIDIOE(Output enable in bidirectional mode) — этот бит используется для настройки однопроводного режима, 1 — данные только передаются, 0 — данные только принимаются.

CRCEN(Hardware CRC calculation enable) — запись единицы в этот бит, разрешает аппаратный подсчёт CRC, 0 – запрещает.

CRCNEXT(CRC transfer next) – если этот бит установлен, это говорит о том следующей будет передаваться контрольная сумма.

DFF(Data frame format) – этот бит определяет формат фрейма, 0 — 8 бит, 1 — 16 бит.

RXONLY(Receive only) – этот бит используется в двухпроводном режиме, его установка в единицу запрещает передачу и модуль SPI работает только на приём, иначе на приём и передачу.

SSM(Software slave management) — программное управление NSS, когда этот бит установлен вместо уровня на входе NSS контролируется состояние бита SSI, если сброшен — контролируется состояние вывода NSS.

SSI(Internal slave select) — этот бит имеет силу только при установленном SSM, его значение заменяет состояние на выводе NSS.

LSBFIRST(Frame format) — определяет формат фрейма, 1 — младшим битом вперёд, 0 — старшим битом вперёд.

SPE(SPI enable) — единица в этом бите включает модуль SPI, 0 – выключает.

BR[2:0](Baud rate control) — данные биты определяют скорость передачи данных.

MSTR(Master selection) — определяет режим работы, 1 —Master, 0 — Slave.

CPOL(Clock polarity) — определяет полярность в режиме ожидания, 0 — низкий уровень в режиме ожидания, 1 — высокий уровень в режиме ожидания.

CPHA(Clock phase) – задаёт фазу тактового сигнала, 0 — выборка данных производится по переднему фронту сигнала синхронизации, 1 — выборка данных производится по заднему фронту сигнала синхронизации.

Регистр управления SPI_CR2 :

TXEIE(Tx buffer empty interrupt enable) — единица в этом бите разрешает прерывание, когда буфер передачи пуст.

RXNEIE(RX buffer not empty interrupt enable) — единица в этом бите разрешает прерывание когда буфер не пуст.

ERRIE(Error interrupt enable) — единица в этом бите разрешает прерывание при возникновении ошибки, о которой сигнализируют биты CRCERR, OVR, MODF.

SSOE(SS output enable) — единица в этом бите, разрешает использовать вывод NSS в качестве выхода и модуль SPI сам управляет выводом NSS, но управляет ним по следующему алгоритму: при включении модуля SPI(SPE = 1) на NSS появляется низкий уровень и сохраняется пока модуль не будет выключен(SPE = 0), что в большинстве случаев не подходит, поэтому для этих целей использую GPIO, а на NSS в режиме Master программно выставляю единицу(SSM = 1, SSI = 1).

TXDMAEN(Tx buffer DMA enable) — разрешает/запрещает формировать запрос к DMA при появлении флага TXE(по завершении передачи).

RXDMAEN(Rx buffer DMA enable) — разрешает/запрещает формировать запрос к DMA при появлении флага RXE(по завершении приёма).

Регистр статуса SPI_SR:

BSY(Busy flag) — флаг занятости, предназначен для отслеживания состояния сдвигового регистра, устанавливается аппаратно во время обмена данными, а точнее с момента когда данные из регистра SPI_DR поступают в сдвиговый регистр, сбрасывается при опустошении сдвигового регистра, то есть когда все данные ушли в линию MOSI.

Производители не советуют проверять его при приёме и передаче, вместо этого советуют пользоваться флагами TXE и RXNE.

OVR(Overrun flag) – устанавливается при переполнении буфера, когда новые данные перезаписали старые, которые ещё не были прочитаны.

MODF(Mode fault) — устанавливается если в режиме Master на вход NSS поступает сигнал низкого уровня, и он становится Slave. Сбросить его можно с помощью специальной последовательности.

CRCERR(CRC error flag) – флаг ошибки контрольной суммы.

TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных

RXNE(Receive buffer not empty) — устанавливается когда приёмный буфер содержит данные, очищается при считывании данных.

SPI_DR(Data register) – регистр данных, фактически он состоит из двух буферов: приёма и передачи, но мы работаем только с регистром DR, поэтому для отправки данных пишем в регистр DR, для приёма читаем его же.

SPI_CRCPR(CRC polynomial register) – содержит полином для расчёта CRC, после сброса его значение равно 0x0007.

SPI_RXCRCR(Rx CRC register) – содержит вычисленную CRC принятых данных.

SPI_TXCRCR(Tx CRC register) – содержит вычисленную CRC передаваемых данных.

Инициализация модуля из рабочего проекта.

#define CS_LOW GPIOB->BSRR = GPIO_BSRR_BR10;
#define CS_HIGH GPIOB->BSRR = GPIO_BSRR_BS10; void Spi_Init(void)
{
//включаем тактирование порта B и альтернативных функций RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN; //13(SCK) и 15(MOSI) вывод – альтернативная функция push pull, 14(MISO) вывод – Input floating, 10(CS) вывод – выход, push-pull GPIOB->CRH &= ~(GPIO_CRH_CNF13_0 | GPIO_CRH_CNF15_0 | GPIO_CRH_CNF10_0); GPIOB->CRH |= GPIO_CRH_CNF13_1 | GPIO_CRH_CNF15_1; GPIOB->CRH |= GPIO_CRH_MODE10_0 | GPIO_CRH_MODE13_1 | GPIO_CRH_MODE15_1; //включаем тактирование SPI2 RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; SPI2->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256 SPI2->CR1 &= ~SPI_CR1_CPOL; //Polarity cls signal CPOL = 0; SPI2->CR1 &= ~SPI_CR1_CPHA; //Phase cls signal CPHA = 0; SPI2->CR1 |= SPI_CR1_DFF; //16 bit data SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB will be first SPI2->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; //Software slave management & Internal slave select SPI2->CR1 |= SPI_CR1_MSTR; //Mode Master SPI2->CR1 |= SPI_CR1_SPE; //Enable SPI2
} uint16_t Spi_Write_Data(uint16_t data)
{ //ждём пока опустошится Tx буфер while(!(SPI2->SR & SPI_SR_TXE)); //активируем Chip Select CS_LOW //отправляем данные SPI2->DR = data; //ждём пока придёт ответ while(!(SPI2->SR & SPI_SR_RXNE)); //считываем полученные данные data = SPI2->DR; //деактивируем Chip Select CS_HIGH //возвращаем то, что прочитали return data; }

Такой способ обмена данными нашёл на форуме st.com, в нём есть некоторые вещи, которые надо бы изменить, как минимум установить порог ожидания флагов, а то мало ли что может случиться. Но пока всё работает, решил не трогать.

Источник: https://hubstub.ru/stm32/100-spi-stm32.html

Новости API

Судя по всему, с играми на будущих девайсах Apple можно попрощаться. Может быть не со всеми, однако новое решение компании должно очень больно ударить по разработчикам, желающим выпустить порт на Mac.

  В заметках для iOS и macOS компания сообщила о прекращении поддержки графических и вычислительных API с открытым исходным кодом: OpenGL, OpenGL ES и OpenCL.

Вместо этого Apple мотивирует разработчиков использовать Metal API, доступный уже несколько лет и не представляющий большого интереса для тех, кто хочет выпускать игры не только на Windows.  Новости нельзя назвать особе…

SteamSpy — отличный сервис, который позволял любому желающему посмотреть, насколько популярна та или иная игра на PC. Хотя информацию нельзя назвать 100% точной, этого было более чем достаточно для аналитиков, СМИ и просто заинтересованных геймеров.

К сожалению, эти славные деньки подошли к концу. SteamSpy более не сможет использовать данные, которые Valve предоставляла через API. Связано это с изменениями в настройках приватности Steam.

Как отмечает Valve в своем блоге, пользователи теперь могут выбирать, кто видит данные их профиля — в том числе и список игр, как уже купленных,…

Во время недавней презентации AMD компания объявила, что в 2018 году будет активно инвестировать в успех графического API Vulkan, уже доказавшего свою эффективность на видеокартах компании.

Если AMD удастся привлечь даже нескольких крупных разработчиков, это станет началом серьезной конкуренции с Nvidia… как когда-то в прошлом. Vulkan API отличается возможностью работать с железом, следуя концепциям OpenGL.

Благодаря этому игры на Vulkan отлично работают с картами архитектуры Graphics Core Next линейки Vega, обходя даже мощные видеокарты Nvidia. В последние годы Vulkan не смогла захва…

CryTek объявила о выпуске новой превью-версии CRYENGINE, включающей набор новых особенностей, упрощающих жизнь разработчиков. Апдейт уже доступен и его можно скачать на Github. Там же доступны все заметки по апдейту и планы по разработке.  CRYENGINE версии 5.

4 также включает бета-версию рендеринга на Vulkan API, в дополнении к DX12, который ввели еще в прошлом году. Vulkan — кросс-платформенное API, позволяющее добиваться высокой производительности благодаря низкоуровнему доступу и балансированию использования CPU/GPU.

На данный момент Vulkan работает только на PC-версии движка. В …

Crytek продолжает развитие CryEngine и недавно в сети появилась информация о следующих обновлениях. Версия движка 5.2 получит полную поддержку DirectX 12, а следующий апдейт 5.3, запланированный на октябрь, будет поддерживать графическое API Vulkan.

Что именно входит в DX12 рендер, который уже должен быть доступен: Поддержка Scaleform Flash в DX12 Обновленная система рендеринга элементов Обновленная система для Тумана, Облаков и Воды Обновленная система Deferred Decals AuxRenderer  Поддержка мульти-GPU в VR Оптимизация шейдинга Forward pass использует обновл…

Студия id Software выпустила новое обновление для Doom, вводящее поддержку графического API Vulkan, повышая частоту кадров на графических картах, поддерживающих Vulkan.

После установки обновления и последних драйверов, игроки получают опцию играть в Doom при помощи OpenGL или Vulkan API. Согласно данным AMD, у игроков, которые используют Vulkan, частота кадров может вырасти до 20%.

Не забывайте обновлять графические драйвера AMD и Nvidia. Порой они способны повысить частоту на пару-тройку кадров даже не на самых новых картах.

Во время недавнего эвента Nvidia, Bethesda продемонстрировала как будет работать Doom на новых графических картах GTX 1080 с использованием API Vulkan, выдавая от 120 кадров в секунду при ультра-настройках графики. порой, поднимаясь даже под 200 fps.

Теперь же Nvidia опубликовала прямую запись геймплея Doom сделанную на карте Titan X, со 120 градусным обзором, 1080p разрешением и стабильными 60 fps.

Хотя это и не новая GTX 1080, да и меньшей частоты от Titan X ждать не стоило при таком разрешении, по крайней мере это доказательство, что графическое API Vulkan справляется с работой и может со…

Во время эвента Samsung Galaxy Unpacked 2016 в Барселоне, Epic Games продемонстрировала новый проект ProtoStar, созданный на Unreal Engine 4 при помощи графического API Vulkan.

После объявления, что Vulkan работает на Galaxy S7 и S7 Edge, основатель Epic Games — Тим Суини, пообещал на мобильных платформах особенности, которые доступны только на топовых консолях.

“Благодаря Vulkan мы можем рендерить объекты в четыре раза быстрей, чем на OpenGL, что позволит нам добиваться высококачественной графики при слабом энергоптреблении. Наш новый проект представляет механику космических тел….

Khronos Group объявила сегодня о немедленном релизе нового бесплатного графического API Vulkan 1.0. Как указано в пресс-релизе, Vulkan предоставляет высокую эффективность, кросс-платформенный доступ к графике и вычислениям на GPU на широком спектре девайсов от PC, до консолей и телефонов.

Vulkan основан на концепции OpenGL и OpenGL ES 3D API. Его главная цель — предоставить прямой контроль над GPU для максимизации производительности и минимизации влияния CPU, а также эффективная мульти-трединговая работа. Драйвера и SDK Vulkan 1.

0 уже доступны для разработчиков, которые заинтересованы …

В этом году мы выяснили, что DirectX 12 включает особенность известную как Мультиадаптер. Она позволяет использовать несколько различных GPU — в том числе от разных производителей. По крайней в теории, если разработчики игр будут использовать ее преимущества.

Проще говоря, с данной функцией вы можете оснащать свою систему одновременно AMD и Nvidia. Студия Oxide Games разработала специальный билд своей стратегии Ashes of the Singularity, которая использует особенность мультиадаптера DirectX 12.

Так как игра довольно прожорливая на ресурсы, то это хороший способ оценить то, каки…

Во время выставки SIGGRAPH прошедшей в прошлом месяце, Дэн Гинсбург из Valve поговорил о новых графических API, которые предоставят разработчикам низкоуровневый доступ к GPU и CPU, повышая производительность в играх. И, по словам разработчика, Vulkan превосходит DirectX 12.

  “Если вы не слишком агрессивны, чтобы выпускать игру на DirectX 12 в этом году, я бы сказал, что нет серьезной причины использовать DX12 для вашего тайтла. Дело в том, что Vulkan справляется с той же работой на Windows 10, при этом не ограничиваясь только одной платформой.

Vulkan будет работать на всем – не тол…

В последний год большая часть взглядов прикована к DirectX 12 – новой версии API от Microsoft, благодаря которому разработчики смогут работать на более низком уровне с железом, выжимая дополнительную мощность из существующего железа.

Однако помимо DX12, в этом году интерес вызвал графический API Vulkan. Создаваемый группой Khronos и представленный на GDC 2015, Vulkan является продолжением идей AMD Mantle и обещает снизить потребление мощности CPU и распределить работу по нескольким ядрам.

Но, помимо прямой пользы от железа в самих системах, также Vulkan можно будет использовать и в обла…

AMD подтвердила, что хотя они не отказываются от поддержки своего API – Mantle, полностью, они прекращают работу над оптимизацией. В частности, драйвера Mantle вообще не были оптимизированы для GCN 1.2, куда входят: R9 Fury X, R9 285, R9 380 и Carrizo APU.

  Связано все это на переброску всех сил для развития поддержки Vulkan и DirectX 12. AMD рекомендует разработчикам использовать данные API в своих играх, вместо Mantle.

Данный шаг вполне ожидаем, так как DX12 и Vulcan сами по себе являются низкоуровневыми API с широкой поддержкой.

OpenVR – API разработанная Valve позволяющее получать доступ к железу девайсов виртуальной реальности от различных производителей, без необходимости иметь специфические знания относительно конкретной платформы.

Проще говоря, это черная магия, благодаря которой работать с VR девайсами значительно проще.  Теперь же код для OpenVR был опубликован на GitHub – в репозитории можно найти как API, так и несколько примеров.

Документация находится отдельно, там на GitHub.  

Мы уже много слышали про DirectX 12 от Microsoft и Mantle от AMD – новые типы низкоуровневых графических API. Однако в начале Марта на сцену вышел новый игрок – open-source API Vulkan – наследнике OpenGL, ранее известном как glNext.

 Далее новое видео с сессии проведенной Khronos Group на тему “Будущее Графики и Вычислений”, представляя Vulkan и SPIR-V. Напомним, что Vulkan уже поддерживается различными разработчиками.

В том числе Valve, которая заложила Vulkan в основу Source 2.

Khronos Group опубликовала официальную презентацию Vulkan – нового графического API создаваемого специально для того, чтобы выжимать из железа максимум, в то же время оставаясь открытым и развиваясь при поддержке всего сообщества. Далее основные пункты. Всю презентацию смотрите тут.

Состояние Индустрии Все согласны, что необходимы низкоуровневые графические API Mantle стал одним из первых проложив путь DX12 и Mantle помогают в развитии Vulkan Стандарт Работа со всеми современными GPU Поддержка на всех платформах – десктопы и мобильные  Совместная разработка &nda…

Во время GDC 2015, как и ожидалось, Khronos Group объявила официальное название графического API glNext. Имя ему – Vulkan. Valve проведет особую презентацию по нему в этот Четверг.

Вот что говорит на эту тему Гейб Ньюэлл: “Valve и другие члены Khronos работают чтобы этот высокопроизводительный графический интерфейс был доступен так шикроко, как это возможно, так как для нас это критический компонент SteamOS и будущих игр Valve”. Все официально, Valve таки разрабатывает новые игры!

Следующая неделя будет одной из самых интересных недель в отношении технологий за последние несколько лет. DirectX 12, glNext, разработки Valve и других компаний – скучно точно не будет. И, среди прочего, Khronos Group может анонсировать новое официальное имя для glNext.

Предположение основано на регистрации торговой марки Vulcan, для компьютерного софта отвечающего за выведение 2D и 3D-графики. Описание указанное в регистрации фактически представляет из себя API.

Однако вопрос в том, будет ли Vulcan анонсирован на следующей неделе и действительно ли это новая версия glNext.

Tomshardware сообщил интересный слух, и если он окажется правдой, то это значительно поменяет то, как сегодня геймеры используют системы из нескольких GPU.

Подобно Mantle, DirectX 12 может позволить разработчикам активировать интеграцию нескольких графических карт, чтобы они совместно обрабатывали текстуры и геометрию в каждом кадре. Таким образом, разработчики смогут использовать суммарный объем видео-памяти двух и более видеокарт.

Об этом мы уже слышали ранее, и это не так интересно, как вторая часть. Tomshardware добавляет, что DX 12 может ввести поддержку разной архитектуры GPU, таким об…

В последнее время в индустрии компьютерной графики наметилась тенденция к пересмотру основных концепций API. Все началось с того, что компания AMD анонсировала свой низкоуровневый интерфейс – Mantle.

Данная технология снижает нагрузку на CPU и позволяет обращаться к видео карте напрямую, почти так же как это реализовано на консолях. Благодаря этому шагу Microsoft анонсировала DirectX 12, а Apple анонсировала Metal. Но все это проприетарные стандарты, т.е.

использовать данные api можно только в связке с платформами собственников. DirectX только на windows и Xbox, а Metal на iOS и Mac. Вс…

Источник: https://shazoo.ru/tags/3446/api

Нативный низкоуровневый интерфейс плагина

В дополнение к основному интерфейсу скриптов Native Code Plugins Unity может принимать запросы и вызовы, когда происходят какие-либо события. Обычно это используется для низкоуровневого рендеринга в вашем плагине, а также позволяет работать с многопоточными процессами рендеринга Unity.

Headers defining interfaces exposed by Unity are provided with the editor.

Interface Registry

A plugin should export UnityPluginLoad and UnityPluginUnload to handle main Unity events. See IUnityInterface.h for the correct signatures. IUnityInterfaces is provided to the plugin to access further Unity APIs.

#include “IUnityInterface.h” #include “IUnityGraphics.h” // Unity plugin load event extern “C” void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { IUnityGraphics* graphics = unityInterfaces->Get(); }

Доступ к графическому устройству

A plugin can access generic graphics device functionality by getting the IUnityGraphics interface. In earlier versions of Unity a UnitySetGraphicsDevice function had to be exported in order to receive notification about events on the graphics device. Starting with Unity 5.2 the new IUnityGraphics interface (found in IUnityGraphics.h) provides a way to register a callback.

#include “IUnityInterface.h” #include “IUnityGraphics.h” static IUnityInterfaces* s_UnityInterfaces = NULL; static IUnityGraphics* s_Graphics = NULL; static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull; // Unity plugin load event extern “C” void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { s_UnityInterfaces = unityInterfaces; s_Graphics = unityInterfaces->Get(); s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); // Run OnGraphicsDeviceEvent(initialize) manually on plugin load // to not miss the event in case the graphics device is already initialized OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); } // Unity plugin unload event extern “C” void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() { s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); } static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { switch (eventType) { case kUnityGfxDeviceEventInitialize: { s_RendererType = s_Graphics->GetRenderer(); //TODO: user initialization code break; } case kUnityGfxDeviceEventShutdown: { s_RendererType = kUnityGfxRendererNull; //TODO: user shutdown code break; } case kUnityGfxDeviceEventBeforeReset: { //TODO: user Direct3D 9 code break; } case kUnityGfxDeviceEventAfterReset: { //TODO: user Direct3D 9 code break; } }; }

Вызовы плагина из потока рендеринга

Рендеринг в Unity может быть многопоточным, если позволяет используемая платформа и количество доступных для него процессоров.

Когда используется многопоточный рендеринг, команды API рендеринга выполняются в потоке, который полностью отделен от того, который запускает сценарии MonoBehaviour.

Следовательно, ваш плагин не всегда сможет начать рендеринг немедленно, так как ему может помешать общий поток отрисовки, выполняемый в это время.

Для того чтобы сделать какой-либо рендеринг из плагина, вы должны вызвать GL.IssuePluginEvent из скрипта, который вызовет ваш плагин из потока отрисовки. Например, если вы вызовите GL.IssuePluginEvent из функции камеры OnPostRender, то получите обратный вызов плагина сразу же после завершения обработки камеры.

Signature for the UnityRenderingEvent callback is provided in IUnityGraphics.h. Native plugin code example:

// Plugin function to handle a specific rendering event static void UNITY_INTERFACE_API OnRenderEvent(int eventID) { //TODO: user rendering code } // Freely defined function to pass a callback to plugin-specific scripts extern “C” UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() { return OnRenderEvent; }

Managed plugin code example:

#if UNITY_IPHONE && !UNITY_EDITOR [DllImport (“__Internal”)] #else [DllImport(“RenderingPlugin”)] #endif private static extern IntPtr GetRenderEventFunc(); // Queue a specific callback to be called on the render thread GL.IssuePluginEvent(GetRenderEventFunc(), 1);

Such callbacks can now also be added to CommandBuffers via CommandBuffer.IssuePluginEvent.

Пример

Пример плагина низкоуровневого рендеринга можно скачать здесь. В нём продемонстрированы два аспекта:

  • Изображение вращающегося треугольника из кода C++ после завершения всех процессов рендеринга.
  • Заполнение процедурной текстуры из кода C++, используя Texture.GetNativeTexturePtr для доступа.

Проект работает с:

  • Windows (Visual Studio 2008) и Mac OS X (Xcode 3.2) и использует Direct3D 9, Direct3D 11 или OpenGL, в зависимости от платформы. Direct3D 9 часть кода также демонстрирует как управлять “потерянными” устройствами.
  • Windows Store Apps, (см. RenderingPluginWSAVisualStudio2012 для получения большей информации)

Источник: https://docs.unity3d.com/ru/530/Manual/NativePluginInterface.html

STM32 с нуля. Интерфейс SPI

Сегодня мы будем помогать двум микроконтроллерам подружиться с помощью SPI. Для начала обсудим, что же такое вообще SPI, а потом и программку набросаем

Источник: https://microtechnics.ru/stm32-s-nulya-interfejs-spi/

Подключение SD-карт к микроконтроллерам ARM | file-systems | programming

Подключение SD-карт к микроконтроллерам ARM
Ссылка на основную публикацию
Adblock
detector
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}
Добавил(а) microsin   

Здесь приведен перевод популярной статьи [1] от Martin THOMAS, в которой раскрывается полезная тема использования карт памяти вместе с микроконтроллерами. 

[Общие замечания по подключению карт памяти к микроконтроллерам]

Карты памяти SD (SDHC) или старые MMC (далее под картами SD подразумеваются карты MMC, SD, microSD) предоставляют объемное и относительно недорогое хранилище данных.

К картам SD можно получить доступ в режиме SPI, при этом для подключения к микроконтроллеру нужно только 4 сигнала (chip-select, MOSI, MISO, SCK, это режим с 1-разрядной шиной данных. Подробнее см. [2]). Для чтения и записи данных карт файлами на них должна быть создана “стандартная” файловая система, использующаяся на компьютерах PC.

Некоторые основные замечания: если Вы ищете библиотеку FAT, и у Вас есть код для низкоуровневого доступа к интерфейсу SPI (позволяющий писать/читать данные блоками сырые данные), то присмотритесь к библиотеке Chan FAT File System Module (FatFS, Petit FatFS, см. [3] или оригинальный сайт elm-chan.org).

Это компактная, легко портируемая, бесплатная и быстрая библиотека, написанная на языке C. Она поддерживает FAT16 и FAT32, и начиная с версии R0.07 даже поддерживает длинные имена файлов. Другая библиотека, поддерживающая длинные имена, это libfat из пакета DevkitPro [4].

Лицензия у неё в стиле BSD, и никаких проблем быть не должно. Код предоставляет базовый набор функций – среди них поддержка длинных имен (LFN) и также некоторое кэширование, однако при этом потребуется дополнительная память.

Автор не проводил обширных экспериментов с libfat, однако проекты на основе AT91SAM7S и LPC2000 (ядро ARM7TDMI(-S)) на ней успешно работали.

Все варианты реализации файловых систем FAT требуют наличия некоторого минимального набора интерфейсных функций, чтобы получить доступ к аппаратуре.

В зависимости от используемого микроконтроллера с картой SD можно работать через 4-разрядную шину (так называемый режим MCI) или 1-разрядную шину (1-разрядную шину называют режимом SPI; некоторые современные карты micro-SD не могут работать в режиме SPI).

Для физического доступа к картам памяти Вам понадобятся как минимум 3 функции: одна для инициализации аппаратуры микроконтроллера и самой карты SD, другая для чтения блока данных (обычно размер блока 512 байт) из карты SD в RAM, и третья для записи блока данных из RAM на карту.

Здесь также могут пригодится готовые шаблоны таких функций, которые можно найти в составе примеров из библиотеки на сайте Chan FatFs. Некоторые поставщики аппаратных средств (микроконтроллеров) или компиляторов также предоставляют коды функций драйвера для карт SD как минимум для режима SPI.

Например, есть отличные примеры от компании Atmel для её микроконтроллеров ARM составе дистрибутива среды разработки IAR, см. также пакет SDK для микроконтроллеров STM. Примеры кода для реализации устройств USB MSD (USB mass-storage device, т. е.

флешка), могут иметь программный интерфейс доступа к карте памяти и её содержимому, так что можно позаимствовать оттуда соответствующий низкоуровневый код (в соответствии с требованиями лицензии).

Если Вы с нуля начинаете работать с картами через SPI, то просмотрите код для AVR примеров от Chan, измените соответствующие специфичные для AVR куски низкоуровневого кода (который использует аппаратуру SPI), и в результате получите работоспособный код для доступа к файловой системе.

Для начала разберите простые готовые примеры, которые распечатывают содержимое каталога, читают несколько байт из файла, который уже есть на карте, создают файл. После того, как протестируете примеры и убедитесь в их исправной работе в нужной Вам аппаратной среде, можно приступать к пошаговой оптимизации кода и адаптации его к Вашим требованиям (или даже провести эксперименты с другой библиотекой FAT).

Прим. переводчика: для некоторых файловых систем (например, для FatFS) требуется также таймер для отсчета реального времени (таймауты обращения к диску). Для полной поддержки меток времени файлов также желательно предоставить функции для получения текущего времени (применимо к системам, которые имеют на борту энергонезависимые часы реального времени).

По поводу аппаратуры: нужно как минимум добавить pull-up резистор на сигнал MISO микроконтроллера (сигнал DO карты); если в микроконтроллере есть такая возможность (например, AVR и ARM от Atmel позволяют программно подключить pull-up резистор), то вместо внешнего нагрузочного резистора можно использовать встроенный в микроконтроллер. Убедитесь, что напряжение питания находится в допустимом для карты диапазоне – номинальное напряжение 3.3V, подробнее см. [2]. Для получения стабильного напряжения используйте специальный регулятор (прогуглите low drop out voltage regulator), во избежание проблем не применяйте хаки наподобие гасящих напряжение резисторов или цепочек на диодах. Подключите конденсатор емкостью как минимум 100 нФ между шинами VCC и GND рядом со слотом карты, и также должен быть добавлен конденсатор на 10 мкФ.

Также рекомендуется добавить схему для полного выключения питания карты, например на полевом P-канальном транзисторе FET, что позволит при необходимости программно сбросить карту в случае ошибок (карты MMC/SD/SDHC не имеют специального сигнала сброса).

Помните о том, что при выключении питания нужно также отключить pull-up резисторы микроконтроллера, поскольку они могут подавать на карту паразитное питание. Когда начинаете экспериментировать, установите меньше частоты шины (это делается при инициализации карты, подробности см.

даташиты на карты памяти); далее в процессе оптимизации нужно подобрать частоту шины, чтобы добиться устойчивой работы интерфейса во всех условиях с разными типами карт. Избегайте использования согласования уровня сигналов с помощью делителей на резисторах.

 Ознакомьтесь со статьей “How to Use MMC/SDC” на сайте Chan (перевод приведен по ссылке [2]), где обсуждаются тонкости работы с интерфейсом, в частности освобождение сигнала DO/MISO.

• http://elm-chan.org/fsw/ff/00index_e.html – файловая система Chan FAT(12,16,32), где в одном пакете с библиотекой файловой системы есть несколько примеров для разных микроконтроллеров (например AVR SPI и LPC23xx/24xx MCI).

• http://elm-chan.org/docs/mmc/mmc_e.html – статья “How to Use MMC/SDC” [2].

• http://sourceforge.net/projects/efsl/ EFSL файловая система FAT16/32, некоторые примеры/расширения описаны далее.

• http://www.holger-klabunde.de/avr/avrboard.htm#cf код FAT16/32 для AVR, LPC2000, автор Holger Klabundes (статья на немецком языке).

• http://sourceforge.net/projects/devkitpro/ devkitpro libfat FAT16/32, поддержка длинных имен файлов (LFN) реализована для GBA и DS, но код легко портируется как минимум на ARM7 и ARM9.

• http://www.zws.com/products/dosfs/index.html DOSFS Free FAT12/FAT16/FAT32 Filesystem. Описана как “бесплатная, FAT-совместимая, предназначенная относительно маломощных встраиваемых систем. Минимальные требования к целевой системе 1K RAM, 4K ROM”.

• ftp://ftp.circuitcellar.com/pub/Circuit_Cellar/2005/176/Sham176.zip Circuit Cellar FAT16 MMC/SD с интерфейсом для MSP430.

• Implementing FAT32 File Systems on ADSP-BF533 Blackfin Processors site:analog.com апноут и код от компании Analog Devices.

• FAT Atmel AVR32 UC3 Software-Library site:atmel.com код системы FAT в составе библиотеки подпрограмм для микроконтроллеров AVR32 UC3 компании Atmel.

• AVR916: Upgrading the Flash using a U-Disk site:atmel.com апноут Atmel, где описывается обновление firmware микроконтроллера с помощью диска на карте памяти. 

Источник: http://microsin.net/programming/file-systems/interfacing-arm-controllers-with-memory-cards.html