Создание собственной системы стабилизации

oleg70
rual:

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

Стандартные функции смотрел, происходит вообще лажа какаэто, по многочисленным экспериментам имею следующие “явления”:
1.корректно записывается только первый (любой) регистр конфигурации следующий уже сбоит…
2.при исполнении SPI_SendData8(L3GD20_SPI, byte) с байтом типа “на запись” дождаться флага RXNE невозможно (будто с гиры байт не приходит)…
3.При понижении (!!!) скорости SPI ниже “SPI_BaudRatePrescaler_8” вообще ничего не читается и не пишется…
Ну и наконец самое чудное (ударение на “о”), при чтении ось Z не читается а на ее месте данные по оси Y…
Очень похоже что дело в железе.
Менял чипы два раза, проверил “печатку”, пока результат “0” , копаюсь…

SergDoc

осима секретные данные 😃
drv_spi

/**
 * MultiWii NG 0.1 - 2012
 * HAL for STM32f3Discovery: SPI
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <>.
 */

#ifndef DRV_SPI_H_INCLUDED
#define DRV_SPI_H_INCLUDED

DMA_InitTypeDef  DMA_InitStruct;

inline void init_spi() {
  /* Enable the SPI periph */
  RCC_APB2PeriphClockCmd(L3GD20_SPI_CLK, ENABLE);
  /* Enable SCK, MOSI and MISO GPIO clocks */
  RCC_AHBPeriphClockCmd(L3GD20_SPI_SCK_GPIO_CLK | L3GD20_SPI_MISO_GPIO_CLK | L3GD20_SPI_MOSI_GPIO_CLK, ENABLE);
  /* Enable CS  GPIO clock */
  RCC_AHBPeriphClockCmd(L3GD20_SPI_CS_GPIO_CLK, ENABLE);
  /* Enable INT1 GPIO clock */
  RCC_AHBPeriphClockCmd(L3GD20_SPI_INT1_GPIO_CLK, ENABLE);
  /* Enable INT2 GPIO clock */
  RCC_AHBPeriphClockCmd(L3GD20_SPI_INT2_GPIO_CLK, ENABLE);

  GPIO_PinAFConfig(L3GD20_SPI_SCK_GPIO_PORT, L3GD20_SPI_SCK_SOURCE, L3GD20_SPI_SCK_AF);
  GPIO_PinAFConfig(L3GD20_SPI_MISO_GPIO_PORT, L3GD20_SPI_MISO_SOURCE, L3GD20_SPI_MISO_AF);
  GPIO_PinAFConfig(L3GD20_SPI_MOSI_GPIO_PORT, L3GD20_SPI_MOSI_SOURCE, L3GD20_SPI_MOSI_AF);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;//GPIO_PuPd_DOWN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  /* SPI SCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = L3GD20_SPI_SCK_PIN;
  GPIO_Init(L3GD20_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
  /* SPI  MOSI pin configuration */
  GPIO_InitStructure.GPIO_Pin =  L3GD20_SPI_MOSI_PIN;
  GPIO_Init(L3GD20_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
  /* SPI MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin = L3GD20_SPI_MISO_PIN;
  GPIO_Init(L3GD20_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
  /* SPI configuration -------------------------------------------------------*/
  SPI_I2S_DeInit(L3GD20_SPI);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_Init(L3GD20_SPI, &SPI_InitStructure);
  /* Configure the RX FIFO Threshold */
  SPI_RxFIFOThresholdConfig(L3GD20_SPI, SPI_RxFIFOThreshold_QF);
  /* Enable SPI1  */
  SPI_Cmd(L3GD20_SPI, ENABLE);
  /* Configure GPIO PIN for Lis Chip select */
  GPIO_InitStructure.GPIO_Pin = L3GD20_SPI_CS_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(L3GD20_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
  /* Deselect : Chip Select high */
  GPIO_SetBits(L3GD20_SPI_CS_GPIO_PORT, L3GD20_SPI_CS_PIN);
  /* Setup DMA */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
  DMA_InitStruct.DMA_PeripheralBaseAddr =  (uint32_t)&L3GD20_SPI->DR;
  DMA_InitStruct.DMA_MemoryBaseAddr = 0;
  DMA_InitStruct.DMA_BufferSize =  0;
  /* write */
  DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_Init(DMA1_Channel3, &DMA_InitStruct);
  /* read */
  DMA_InitStruct.DMA_Priority = DMA_Priority_High;
  DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_Init(DMA1_Channel2, &DMA_InitStruct);
  /* enable DMA */
  SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Rx, ENABLE);
  SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Tx, ENABLE);
}

void _start_spi_dma(uint8_t* pBuffer, uint16_t NumByteToWrite) {
  // Setup buffer
  DMA1_Channel2->CMAR = (uint32_t)pBuffer;
  DMA1_Channel3->CMAR = (uint32_t)pBuffer;
  DMA1_Channel2->CNDTR = NumByteToWrite;
  DMA1_Channel3->CNDTR = NumByteToWrite;
  //
  DMA_ClearFlag(DMA1_FLAG_GL2);
  DMA_ClearFlag(DMA1_FLAG_GL3);
  /* start */
  DMA_Cmd(DMA1_Channel2, ENABLE);
  DMA_Cmd(DMA1_Channel3, ENABLE);
}

void _disable_spi_dma() {
  DMA_Cmd(DMA1_Channel2, DISABLE);
  DMA_Cmd(DMA1_Channel3, DISABLE);
}

static uint8_t _spi_xchange(uint8_t byte) {
  while (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_TXE) == RESET);
  SPI_SendData8(L3GD20_SPI, byte);
  while (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_RXNE) == RESET);
  while (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_BSY) == SET);
  return (uint8_t)SPI_ReceiveData8(L3GD20_SPI);
}

void spi_write_buff(uint8_t* buff, uint8_t reg, uint16_t size) {
  if(size > 0x01) reg |= (uint8_t)MULTIPLEBYTE_CMD;
  _spi_xchange(reg);
  while(size >= 0x01) {
    _spi_xchange(*buff);
    size--; buff++;
  }
}

inline void spi_write_byte(uint8_t reg, uint8_t val) {
  spi_write_buff(&val, reg, 1);
}

void spi_read_buff(uint8_t* buff, uint8_t reg, uint16_t size) {
  reg |= (uint8_t)READWRITE_CMD;
  if(size > 0x01) reg |= (uint8_t)(MULTIPLEBYTE_CMD);
  _spi_xchange(reg);
  while(size > 0x00) {
    *buff = _spi_xchange(0x00);
    size--; buff++;
  }
}

inline uint8_t spi_read_byte(uint8_t reg) {
  uint8_t buff;
  spi_read_buff(&buff, reg, 1);
  return buff;
}

static PT_THREAD(spi_read_buffer_pt(struct pt *pt, uint8_t reg, uint8_t *buff, uint8_t size)) {
  PT_BEGIN(pt);
  PT_WAIT_WHILE(pt, (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_TXE) == RESET));
  reg |= (uint8_t)READWRITE_CMD;
  if(size > 0x01) reg |= (uint8_t)(MULTIPLEBYTE_CMD);
  SPI_SendData8(L3GD20_SPI, reg);
  PT_WAIT_WHILE(pt, (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_RXNE) == RESET));
  PT_WAIT_WHILE(pt, (SPI_I2S_GetFlagStatus(L3GD20_SPI, SPI_I2S_FLAG_BSY) == SET));
  SPI_ReceiveData8(L3GD20_SPI);
  _start_spi_dma(buff, size);
  PT_WAIT_WHILE(pt, DMA_GetCurrDataCounter(DMA1_Channel2));
  _disable_spi_dma();
  PT_END(pt);
}


#endif // DRV_SPI_H_INCLUDED

stm32f3_discovery_l3gd20

/**
  ******************************************************************************
  * @file    stm32f3_discovery_l3gd20.h
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    20-September-2012
  * @brief   This file contains definitions for stm32f3_discovery_l3gd20.c
  *          firmware driver.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        
  *
  * 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.
  *
  ******************************************************************************
  */


/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F3_DISCOVERY_L3GD20_H
#define __STM32F3_DISCOVERY_L3GD20_H

#ifdef __cplusplus
 extern "C" {
#endif

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

/** @addtogroup Utilities
  * @{
  */

/** @addtogroup STM32F3_DISCOVERY
  * @{
  */

/** @addtogroup STM32F3_DISCOVERY_L3GD20
  * @{
  */

/** @defgroup STM32F3_DISCOVERY_L3GD20_Exported_Types
  * @{
  */

/* L3GD20 struct */
typedef struct
{
  uint8_t Power_Mode;                         /* Power-down/Sleep/Normal Mode */
  uint8_t Output_DataRate;                    /* OUT data rate */
  uint8_t Axes_Enable;                        /* Axes enable */
  uint8_t Band_Width;                         /* Bandwidth selection */
  uint8_t BlockData_Update;                   /* Block Data Update */
  uint8_t Endianness;                         /* Endian Data selection */
  uint8_t Full_Scale;                         /* Full Scale selection */
}L3GD20_InitTypeDef;

/* L3GD20 High Pass Filter struct */
typedef struct
{
  uint8_t HighPassFilter_Mode_Selection;      /* Internal filter mode */
  uint8_t HighPassFilter_CutOff_Frequency;    /* High pass filter cut-off frequency */
}L3GD20_FilterConfigTypeDef;

/* L3GD20 Interrupt struct */
typedef struct
{
  uint8_t Latch_Request;                      /* Latch interrupt request into CLICK_SRC register */
  uint8_t Interrupt_Axes;                     /* X, Y, Z Axes Interrupts */
  uint8_t Interrupt_ActiveEdge;               /*  Interrupt Active edge */
}L3GD20_InterruptConfigTypeDef;

/**
  * @}
  */


/**
  * @}
  */

/** @defgroup STM32F3_DISCOVERY_L3GD20_Exported_Constants
  * @{
  */

/* Read/Write command */
#define READWRITE_CMD              ((uint8_t)0x80)
/* Multiple byte read/write command */
#define MULTIPLEBYTE_CMD           ((uint8_t)0x40)
/* Dummy Byte Send by the SPI Master device in order to generate the Clock to the Slave device */
#define DUMMY_BYTE                 ((uint8_t)0x00)

/* Uncomment the following line to use the default L3GD20_TIMEOUT_UserCallback()
   function implemented in stm32f3_discovery_lgd20.c file.
   L3GD20_TIMEOUT_UserCallback() function is called whenever a timeout condition
   occure during communication (waiting transmit data register empty flag(TXE)
   or waiting receive data register is not empty flag (RXNE)). */
/* #define USE_DEFAULT_TIMEOUT_CALLBACK */

/* Maximum Timeout values for flags waiting loops. These timeouts are not based
   on accurate values, they just guarantee that the application will not remain
   stuck if the SPI communication is corrupted.
   You may modify these timeout values depending on CPU frequency and application
   conditions (interrupts routines ...). */
#define L3GD20_FLAG_TIMEOUT             ((uint32_t)0x1000)

/**
  * @brief  L3GD20 SPI Interface pins
  */
#define L3GD20_SPI                       SPI1
#define L3GD20_SPI_CLK                   RCC_APB2Periph_SPI1

#define L3GD20_SPI_SCK_PIN               GPIO_Pin_5                  /* PA.05 */
#define L3GD20_SPI_SCK_GPIO_PORT         GPIOA                       /* GPIOA */
#define L3GD20_SPI_SCK_GPIO_CLK          RCC_AHBPeriph_GPIOA
#define L3GD20_SPI_SCK_SOURCE            GPIO_PinSource5
#define L3GD20_SPI_SCK_AF                GPIO_AF_5

#define L3GD20_SPI_MISO_PIN              GPIO_Pin_6                  /* PA.6 */
#define L3GD20_SPI_MISO_GPIO_PORT        GPIOA                       /* GPIOA */
#define L3GD20_SPI_MISO_GPIO_CLK         RCC_AHBPeriph_GPIOA
#define L3GD20_SPI_MISO_SOURCE           GPIO_PinSource6
#define L3GD20_SPI_MISO_AF               GPIO_AF_5

#define L3GD20_SPI_MOSI_PIN              GPIO_Pin_7                  /* PA.7 */
#define L3GD20_SPI_MOSI_GPIO_PORT        GPIOA                       /* GPIOA */
#define L3GD20_SPI_MOSI_GPIO_CLK         RCC_AHBPeriph_GPIOA
#define L3GD20_SPI_MOSI_SOURCE           GPIO_PinSource7
#define L3GD20_SPI_MOSI_AF               GPIO_AF_5

#define L3GD20_SPI_CS_PIN                GPIO_Pin_3                  /* PE.03 */
#define L3GD20_SPI_CS_GPIO_PORT          GPIOE                       /* GPIOE */
#define L3GD20_SPI_CS_GPIO_CLK           RCC_AHBPeriph_GPIOE

#define L3GD20_SPI_INT1_PIN              GPIO_Pin_0                  /* PE.00 */
#define L3GD20_SPI_INT1_GPIO_PORT        GPIOE                       /* GPIOE */
#define L3GD20_SPI_INT1_GPIO_CLK         RCC_AHBPeriph_GPIOE
#define L3GD20_SPI_INT1_EXTI_LINE        EXTI_Line0
#define L3GD20_SPI_INT1_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define L3GD20_SPI_INT1_EXTI_PIN_SOURCE  EXTI_PinSource0
#define L3GD20_SPI_INT1_EXTI_IRQn        EXTI0_IRQn

#define L3GD20_SPI_INT2_PIN              GPIO_Pin_1                  /* PE.01 */
#define L3GD20_SPI_INT2_GPIO_PORT        GPIOE                       /* GPIOE */
#define L3GD20_SPI_INT2_GPIO_CLK         RCC_AHBPeriph_GPIOE
#define L3GD20_SPI_INT2_EXTI_LINE        EXTI_Line1
#define L3GD20_SPI_INT2_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define L3GD20_SPI_INT2_EXTI_PIN_SOURCE  EXTI_PinSource1
#define L3GD20_SPI_INT2_EXTI_IRQn        EXTI1_IRQn

/******************************************************************************/
/*************************** START REGISTER MAPPING  **************************/
/******************************************************************************/
#define L3GD20_WHO_AM_I_ADDR          0x0F  /* device identification register */
#define L3GD20_CTRL_REG1_ADDR         0x20  /* Control register 1 */
#define L3GD20_CTRL_REG2_ADDR         0x21  /* Control register 2 */
#define L3GD20_CTRL_REG3_ADDR         0x22  /* Control register 3 */
#define L3GD20_CTRL_REG4_ADDR         0x23  /* Control register 4 */
#define L3GD20_CTRL_REG5_ADDR         0x24  /* Control register 5 */
#define L3GD20_REFERENCE_REG_ADDR     0x25  /* Reference register */
#define L3GD20_OUT_TEMP_ADDR          0x26  /* Out temp register */
#define L3GD20_STATUS_REG_ADDR        0x27  /* Status register */
#define L3GD20_OUT_X_L_ADDR           0x28  /* Output Register X */
#define L3GD20_OUT_X_H_ADDR           0x29  /* Output Register X */
#define L3GD20_OUT_Y_L_ADDR           0x2A  /* Output Register Y */
#define L3GD20_OUT_Y_H_ADDR           0x2B  /* Output Register Y */
#define L3GD20_OUT_Z_L_ADDR           0x2C  /* Output Register Z */
#define L3GD20_OUT_Z_H_ADDR           0x2D  /* Output Register Z */
#define L3GD20_FIFO_CTRL_REG_ADDR     0x2E  /* Fifo control Register */
#define L3GD20_FIFO_SRC_REG_ADDR      0x2F  /* Fifo src Register */

#define L3GD20_INT1_CFG_ADDR          0x30  /* Interrupt 1 configuration Register */
#define L3GD20_INT1_SRC_ADDR          0x31  /* Interrupt 1 source Register */
#define L3GD20_INT1_TSH_XH_ADDR       0x32  /* Interrupt 1 Threshold X register */
#define L3GD20_INT1_TSH_XL_ADDR       0x33  /* Interrupt 1 Threshold X register */
#define L3GD20_INT1_TSH_YH_ADDR       0x34  /* Interrupt 1 Threshold Y register */
#define L3GD20_INT1_TSH_YL_ADDR       0x35  /* Interrupt 1 Threshold Y register */
#define L3GD20_INT1_TSH_ZH_ADDR       0x36  /* Interrupt 1 Threshold Z register */
#define L3GD20_INT1_TSH_ZL_ADDR       0x37  /* Interrupt 1 Threshold Z register */
#define L3GD20_INT1_DURATION_ADDR     0x38  /* Interrupt 1 DURATION register */

/******************************************************************************/
/**************************** END REGISTER MAPPING  ***************************/
/******************************************************************************/

#define I_AM_L3GD20		    ((uint8_t)0xD4)

/** @defgroup Power_Mode_selection
  * @{
  */
#define L3GD20_MODE_POWERDOWN       ((uint8_t)0x00)
#define L3GD20_MODE_ACTIVE          ((uint8_t)0x08)
/**
  * @}
  */

/** @defgroup OutPut_DataRate_Selection
  * @{
  */
#define L3GD20_OUTPUT_DATARATE_1    ((uint8_t)0x00)
#define L3GD20_OUTPUT_DATARATE_2    ((uint8_t)0x40)
#define L3GD20_OUTPUT_DATARATE_3    ((uint8_t)0x80)
#define L3GD20_OUTPUT_DATARATE_4    ((uint8_t)0xC0)
/**
  * @}
  */

/** @defgroup Axes_Selection
  * @{
  */
#define L3GD20_X_ENABLE            ((uint8_t)0x02)
#define L3GD20_Y_ENABLE            ((uint8_t)0x01)
#define L3GD20_Z_ENABLE            ((uint8_t)0x04)
#define L3GD20_AXES_ENABLE         ((uint8_t)0x07)
#define L3GD20_AXES_DISABLE        ((uint8_t)0x00)
/**
  * @}
  */

/** @defgroup BandWidth_Selection
  * @{
  */
#define L3GD20_BANDWIDTH_1         ((uint8_t)0x00)
#define L3GD20_BANDWIDTH_2         ((uint8_t)0x10)
#define L3GD20_BANDWIDTH_3         ((uint8_t)0x20)
#define L3GD20_BANDWIDTH_4         ((uint8_t)0x30)
/**
  * @}
  */

/** @defgroup Full_Scale_Selection
  * @{
  */
#define L3GD20_FULLSCALE_250               ((uint8_t)0x00)
#define L3GD20_FULLSCALE_500               ((uint8_t)0x10)
#define L3GD20_FULLSCALE_2000              ((uint8_t)0x20)
/**
  * @}
  */

/** @defgroup Block_Data_Update
  * @{
  */
#define L3GD20_BlockDataUpdate_Continous   ((uint8_t)0x00)
#define L3GD20_BlockDataUpdate_Single      ((uint8_t)0x80)
/**
  * @}
  */

/** @defgroup Endian_Data_selection
  * @{
  */
#define L3GD20_BLE_LSB                     ((uint8_t)0x00)
#define L3GD20_BLE_MSB	                   ((uint8_t)0x40)
/**
  * @}
  */

/** @defgroup High_Pass_Filter_status
  * @{
  */
#define L3GD20_HIGHPASSFILTER_DISABLE      ((uint8_t)0x00)
#define L3GD20_HIGHPASSFILTER_ENABLE	     ((uint8_t)0x10)
/**
  * @}
  */

/** @defgroup INT1_Interrupt_status
  * @{
  */
#define L3GD20_INT1INTERRUPT_DISABLE       ((uint8_t)0x00)
#define L3GD20_INT1INTERRUPT_ENABLE	   ((uint8_t)0x80)
/**
  * @}
  */

/** @defgroup INT2_Interrupt_status
  * @{
  */
#define L3GD20_INT2INTERRUPT_DISABLE       ((uint8_t)0x00)
#define L3GD20_INT2INTERRUPT_ENABLE	   ((uint8_t)0x08)
/**
  * @}
  */

/** @defgroup INT1_Interrupt_ActiveEdge
  * @{
  */
#define L3GD20_INT1INTERRUPT_LOW_EDGE      ((uint8_t)0x20)
#define L3GD20_INT1INTERRUPT_HIGH_EDGE     ((uint8_t)0x00)
/**
  * @}
  */

/** @defgroup Boot_Mode_selection
  * @{
  */
#define L3GD20_BOOT_NORMALMODE             ((uint8_t)0x00)
#define L3GD20_BOOT_REBOOTMEMORY           ((uint8_t)0x80)
/**
  * @}
  */

/** @defgroup High_Pass_Filter_Mode
  * @{
  */
#define L3GD20_HPM_NORMAL_MODE_RES         ((uint8_t)0x00)
#define L3GD20_HPM_REF_SIGNAL              ((uint8_t)0x10)
#define L3GD20_HPM_NORMAL_MODE             ((uint8_t)0x20)
#define L3GD20_HPM_AUTORESET_INT           ((uint8_t)0x30)
/**
  * @}
  */

/** @defgroup High_Pass_CUT OFF_Frequency
  * @{
  */
#define L3GD20_HPFCF_0              0x00
#define L3GD20_HPFCF_1              0x01
#define L3GD20_HPFCF_2              0x02
#define L3GD20_HPFCF_3              0x03
#define L3GD20_HPFCF_4              0x04
#define L3GD20_HPFCF_5              0x05
#define L3GD20_HPFCF_6              0x06
#define L3GD20_HPFCF_7              0x07
#define L3GD20_HPFCF_8              0x08
#define L3GD20_HPFCF_9              0x09
/**
  * @}
  */


/** @defgroup STM32F3_DISCOVERY_L3GD20_Exported_Macros
  * @{
  */
#define L3GD20_CS_LOW()       GPIO_ResetBits(L3GD20_SPI_CS_GPIO_PORT, L3GD20_SPI_CS_PIN)
#define L3GD20_CS_HIGH()      GPIO_SetBits(L3GD20_SPI_CS_GPIO_PORT, L3GD20_SPI_CS_PIN)
/**
  * @}
  */

/** @defgroup STM32F3_DISCOVERY_L3GD20_Exported_Functions
  * @{
  */
/* Sensor Configuration Functions */
void L3GD20_Init(L3GD20_InitTypeDef *L3GD20_InitStruct);
void L3GD20_RebootCmd(void);

/*INT1 Interrupt Configuration Functions */
void L3GD20_INT1InterruptCmd(uint8_t InterruptState);
void L3GD20_INT2InterruptCmd(uint8_t InterruptState);
void L3GD20_INT1InterruptConfig(L3GD20_InterruptConfigTypeDef *L3GD20_IntConfigStruct);
uint8_t L3GD20_GetDataStatus(void);

/* High Pass Filter Configuration Functions */
void L3GD20_FilterConfig(L3GD20_FilterConfigTypeDef *L3GD20_FilterStruct);
void L3GD20_FilterCmd(uint8_t HighPassFilterState);
void L3GD20_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite);
void L3GD20_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead);

/* USER Callbacks: This is function for which prototype only is declared in
   MEMS accelerometre driver and that should be implemented into user applicaiton. */
/* L3GD20_TIMEOUT_UserCallback() function is called whenever a timeout condition
   occure during communication (waiting transmit data register empty flag(TXE)
   or waiting receive data register is not empty flag (RXNE)).
   You can use the default timeout callback implementation by uncommenting the
   define USE_DEFAULT_TIMEOUT_CALLBACK in stm32f3_discovery_l3gd20.h file.
   Typically the user implementation of this callback should reset MEMS peripheral
   and re-initialize communication or in worst case reset all the application. */
uint32_t L3GD20_TIMEOUT_UserCallback(void);

#ifdef __cplusplus
}
#endif

#endif /* __STM32F3_DISCOVERY_L3GD20_H */
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

по моемУ - выделил нулевой сектор - прокатило, теперь застрял на инициализации АЦП (и вроде же из примера брал)… не что-то не так с виртуальником… не пишет оно туда…

SergDoc

в общем, флеш если отключать или использовать не занятую прошивкой - оно не работает, работает если занято, следовательно надо зарезервировать часть флеши в прошивке, вот как это сделать в f4 непонятно, примеры просто супер коварные…

SergDoc

Блин совсем уже крыша поехала, если стирать в указанной области - то стирает гдебы она не была, а вот записывать только может где данные во флеши, т.е. указываем например 0-й сектор (там у нас сама программа) - перезапишет сколько успеет, а если в пустом секторе-висяк конкретный, надо каким-то образом сектор включить в ПО и ff-ками заполнить… мыслей уже ноль…
аа сам дурак, а кто в переменные глядеть должен, в 16-ти битную ну никак не влезет hex 20000, ну надо теперь всё перепроверять…

SergDoc
oleg70:

Вот что у меня осталось от DiscoveryF3

Олег, попробуйте на всякий случай повесить резистор помиж кондёрами на кварц (между лапами кварца) килоОм 100-150…

Razek

копать от сюда и до заката =))
Приводим значение адреса в указатель на адрес памяти и копируем с этого адреса.

rual
oleg70:

Стандартные функции смотрел,

Олег, вот стандартная инициализация ДУС через стандартные драйверы дисковери (ранее я прилагал архив), см. внимательно, там же есть функции чтения и записи ИММЕНО по Ф3дисковери.

void DUS_Config(void)
{
 L3GD20_InitTypeDef L3GD20_InitStructure;
 L3GD20_FilterConfigTypeDef L3GD20_FilterStructure;
 /* Configure Mems L3GD20 */
 L3GD20_InitStructure.Power_Mode = L3GD20_MODE_ACTIVE;
 L3GD20_InitStructure.Output_DataRate = L3GD20_OUTPUT_DATARATE_3;
 L3GD20_InitStructure.Axes_Enable = L3GD20_AXES_ENABLE;
 L3GD20_InitStructure.Band_Width = L3GD20_BANDWIDTH_4;
 L3GD20_InitStructure.BlockData_Update = L3GD20_BlockDataUpdate_Continous;
 L3GD20_InitStructure.Endianness = L3GD20_BLE_LSB;
 L3GD20_InitStructure.Full_Scale = L3GD20_FULLSCALE_2000;
 L3GD20_Init(&L3GD20_InitStructure);

 L3GD20_FilterStructure.HighPassFilter_Mode_Selection =L3GD20_HPM_NORMAL_MODE_RES;
 L3GD20_FilterStructure.HighPassFilter_CutOff_Frequency = L3GD20_HPFCF_3;
 L3GD20_FilterConfig(&L3GD20_FilterStructure) ;
 L3GD20_FilterCmd(L3GD20_HIGHPASSFILTER_ENABLE);
 L3GD20_INT2InterruptCmd(L3GD20_INT2INTERRUPT_ENABLE);
}
SergDoc:

кто в переменные глядеть должен, в 16-ти битную ну никак не влезет

пишем исключительно полусловами (16 бит), вот моя перекладка демки

/*------------------- ýìóëÿòîð ôëýø ------------------------*/
FLASH_Status FLASH_Write16(uint32_t addr, uint16_t* buf, uint32_t size)
{
 FLASH_Status FLASHStatus = FLASH_COMPLETE;
 uint32_t inx = 0;
 uint32_t EraseCounter = 0x00, Address = 0x00;
  uint32_t NbrOfPage = 0x00;

 /* ïðîâåðèì âûõîä çà ïðåäåëû ðàçðåøåííîé îáëàñòè */
 if (addr+size*2 > FLASH_USER_END_ADDR) return FLASH_ERROR_PROGRAM;

  /* Ðàçáëîêèðîâêà äîñòóïà ê çàïèñè ôëåø */
  FLASH_Unlock();

  /* Î÷èñòèì ôëàãè */
  FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  /* Îïðåäåëèì êîëè÷åñòâî ñòèðàåìûõ ñòðàíèö */
  NbrOfPage = 1 + size / FLASH_PAGE_SIZE;
  /* Ñòèðàåì ñòðàíèöû */
  for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
  {
  FLASHStatus = FLASH_ErasePage(FLASH_USER_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
    if (FLASHStatus != FLASH_COMPLETE)  return FLASHStatus;
  }

  /* Ïðîãðàììèðóåì ôëåø */

  Address = FLASH_USER_START_ADDR;
  while (inx < size) {
  FLASHStatus = FLASH_ProgramHalfWord(Address, buf[inx]);

    if (FLASHStatus == FLASH_COMPLETE){
      Address += 2;
   inx++;
  }
    else return FLASHStatus;
  }
  /* Çàáëîêèðóåì çàïèñü âî ôëåø */
  FLASH_Lock();

 return FLASHStatus;
}

Вот стандартная функция записи полуслова

/**
  * @brief  Programs a half word at a specified address.
  * @note   To correctly run this function, the FLASH_Unlock() function
  *         must be called before.
  *         Call the FLASH_Lock() to disable the flash memory access
  *         (recommended to protect the FLASH memory against possible unwanted operation)
  * @param  Address: specifies the address to be programmed.
  * @param  Data: specifies the data to be programmed.
  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
  *         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
  */
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
  FLASH_Status status = FLASH_COMPLETE;
  /* Check the parameters */
  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

  if(status == FLASH_COMPLETE)
  {
    /* If the previous operation is completed, proceed to program the new data */
    FLASH->CR |= FLASH_CR_PG;

    *(__IO uint16_t*)Address = Data;
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

    /* Disable the PG Bit */
    FLASH->CR &= ~FLASH_CR_PG;
  } 

У меня всё отлично заработало, писал в старший сектор, чтоб линкёр в него не лез уменьшил верхнюю границу флеши в настройке проекта. Почитаю про ф4, напишу отличия…

SergDoc

урааааа у меня зажегся первый светодиод(проверочный) !!! 😃

rual:

пишем исключительно полусловами (16 бит), вот моя перекладка демки

я имел ввиду адрес сектора отрезанного под еепромку 😃
ну с одной мёртвой точки сдвинулся, пойду дальше копать…

rual
SergDoc:

урааааа у меня зажегся первый светодиод(проверочный) !!!

Поздравляю! С флешей разобрался? Вообщем от Ф3 практически не отличается, кроме возможности установить ширину данных, и ещё не увидел в описании процедуры программирования снятие бита программирования
PG bit in the FLASH_CR register, надо смотреть стандартные библиотеки

SergDoc:

я имел ввиду адрес сектора отрезанного под еепромку

ну тут без вариантов uint32_t

SergDoc

так у меня проблема - проц запускается на частоте - 53.76 Мгц - чё я где утварил?
Виноват, сам скопировал от Discovery system_stm32f4xx.c и забыл про это…

SergDoc
rual:

и ещё не увидел в описании процедуры программирования снятие бита программирования
PG bit in the FLASH_CR register,

тут?
stm32f4xx_flash.c



if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_BYTE;
    FLASH->CR |= FLASH_CR_PG;

    *(__IO uint8_t*)Address = Data;

    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  }
rual:

У меня всё отлично заработало, писал в старший сектор, чтоб линкёр в него не лез уменьшил верхнюю границу флеши в настройке проекта.

посмотри st-link видит эту область, а то когда я по незнанке сносил нулевой сектор, то видел что он стирается и в него пишется, а так нет, а отпаивать, что-бы выдрать ввесь дамп, ну не хочется - при запаяном программаторе через uart не достучишься… ага вспомнил, если бы с виртуальником были бы траблы, он бы мне сообщил - светодиод бы моргал часто-часто, да и дальше бы не пошел…
сейчас дошел до автодетекта (его выкинуть надо), а так как нечего детектировать то висим перемигиваемся светодиодиками - почему и заметил, что как-то не так моргают, полез частоту проверять…

rual
SergDoc:

тут? stm32f4xx_flash.c

Да, ту всё нормально, а в доке на Ф3 нет ничего про снятие бита программирования.

SergDoc:

посмотри st-link видит эту область,

СТ-ЛИНК видит-читает, но непосредственно править в отладчике не даёт, только через программирование.

SergDoc

да-да у меня тоже всё прекрасно записано - отладчиком сейчас заглянул в седьмой сектор 0x08060000 - и до победы, занято только примерно пол килобайта, ещё 127,5 - свободны 😃


#include "board.h"
#include "mw.h"
#include <string.h>

#ifndef FLASH_PAGE_COUNT
#define FLASH_PAGE_COUNT 3
#endif
#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */


#define FLASH_PAGE_SIZE                 ((uint32_t)0x20000)
#define FLASH_WRITE_ADDR              ADDR_FLASH_SECTOR_7  //(0x08000000 + (uint32_t)FLASH_PAGE_SIZE*10 * (FLASH_PAGE_COUNT - 1))       // use the last KB for storage

config_t cfg;
const char rcChannelLetters[] = "AERT1234";

static uint8_t EEPROM_CONF_VERSION = 40;
static uint32_t enabledSensors = 0;
static void resetConf(void);

void parseRcChannels(const char *input)
{
    const char *c, *s;

    for (c = input; *c; c++) {
        s = strchr(rcChannelLetters, *c);
        if (s)
            cfg.rcmap[s - rcChannelLetters] = c - input;
    }
}

static uint8_t validEEPROM(void)
{
    const config_t *temp = (const config_t *)FLASH_WRITE_ADDR;//;ADDR_FLASH_SECTOR_7
    const uint8_t *p;
    uint8_t chk = 0;

    // check version number
    if (EEPROM_CONF_VERSION != temp->version)
        return 0;

    // check size and magic numbers
    if (temp->size != sizeof(config_t) || temp->magic_be != 0xBE || temp->magic_ef != 0xEF)
        return 0;

    // verify integrity of temporary copy
    for (p = (const uint8_t *)temp; p < ((const uint8_t *)temp + sizeof(config_t)); p++)
        chk ^= *p;

    // checksum failed
    if (chk != 0)
        return 0;

    // looks good, let's roll!
    return 1;
}

void readEEPROM(void)
{
    uint8_t i;

    // Read flash
    memcpy(&cfg, (char *)FLASH_WRITE_ADDR, sizeof(config_t));//ADDR_FLASH_SECTOR_7

    for (i = 0; i < 6; i++)
        lookupPitchRollRC[i] = (2500 + cfg.rcExpo8 * (i * i - 25)) * i * (int32_t) cfg.rcRate8 / 2500;

    for (i = 0; i < 11; i++) {
        int16_t tmp = 10 * i - cfg.thrMid8;
        uint8_t y = 1;
        if (tmp > 0)
            y = 100 - cfg.thrMid8;
        if (tmp < 0)
            y = cfg.thrMid8;
        lookupThrottleRC[i] = 10 * cfg.thrMid8 + tmp * (100 - cfg.thrExpo8 + (int32_t) cfg.thrExpo8 * (tmp * tmp) / (y * y)) / 10;      // [0;1000]
        lookupThrottleRC[i] = cfg.minthrottle + (int32_t) (cfg.maxthrottle - cfg.minthrottle) * lookupThrottleRC[i] / 1000;     // [0;1000] -> [MINTHROTTLE;MAXTHROTTLE]
    }

    cfg.tri_yaw_middle = constrain(cfg.tri_yaw_middle, cfg.tri_yaw_min, cfg.tri_yaw_max);       //REAR
}

void writeParams(uint8_t b)
{
    FLASH_Status status;
    uint32_t i;
    uint8_t chk = 0;
    const uint8_t *p;

    cfg.version = EEPROM_CONF_VERSION;
    cfg.size = sizeof(config_t);
    cfg.magic_be = 0xBE;
    cfg.magic_ef = 0xEF;
    cfg.chk = 0;
    // recalculate checksum before writing
    for (p = (const uint8_t *)&cfg; p < ((const uint8_t *)&cfg + sizeof(config_t)); p++)
        chk ^= *p;
    cfg.chk = chk;

    // write it
    FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

    if (FLASH_EraseSector(FLASH_Sector_7, VoltageRange_3) == FLASH_COMPLETE) {
        for (i = 0; i < sizeof(config_t); i += 4) {
            status = FLASH_ProgramWord(FLASH_WRITE_ADDR + i, *(uint32_t *) ((char *) &cfg + i));//ADDR_FLASH_SECTOR_7
            if (status != FLASH_COMPLETE)
                break;          // TODO: fail
        }
    }
    FLASH_Lock();

    readEEPROM();
    if (b)
        blinkLED(15, 20, 1);
}

void checkFirstTime(bool reset)
{
    // check the EEPROM integrity before resetting values
    if (!validEEPROM() || reset)
        resetConf();
}

// Default settings
static void resetConf(void)
{
    int i;
    const int8_t default_align[3][3] = { /* GYRO */ { 0, 0, 0 }, /* ACC */ { 0, 0, 0 }, /* MAG */ { -2, -3, 1 } };

    memset(&cfg, 0, sizeof(config_t));

    cfg.version = EEPROM_CONF_VERSION;
    cfg.mixerConfiguration = MULTITYPE_QUADX;
    featureClearAll();
    setFeature(FEATURE_VBAT);

    // cfg.looptime = 0;
    cfg.P8[ROLL] = 40;
    cfg.I8[ROLL] = 30;
    cfg.D8[ROLL] = 23;
    cfg.P8[PITCH] = 40;
    cfg.I8[PITCH] = 30;
    cfg.D8[PITCH] = 23;
    cfg.P8[YAW] = 55;
    cfg.I8[YAW] = 45;
    // cfg.D8[YAW] = 0;
    cfg.P8[PIDALT] = 11;
    cfg.I8[PIDALT] = 15;
    cfg.D8[PIDALT] = 7;
    cfg.P8[PIDPOS] = 11; // POSHOLD_P * 100;
    // cfg.I8[PIDPOS] = 0; // POSHOLD_I * 100;
    // cfg.D8[PIDPOS] = 0;
    cfg.P8[PIDPOSR] = 20; // POSHOLD_RATE_P * 10;
    cfg.I8[PIDPOSR] = 8; // POSHOLD_RATE_I * 100;
    cfg.D8[PIDPOSR] = 45; // POSHOLD_RATE_D * 1000;
    cfg.P8[PIDNAVR] = 14; // NAV_P * 10;
    cfg.I8[PIDNAVR] = 20; // NAV_I * 100;
    cfg.D8[PIDNAVR] = 80; // NAV_D * 1000;
    cfg.P8[PIDLEVEL] = 70;
    cfg.I8[PIDLEVEL] = 10;
    cfg.D8[PIDLEVEL] = 20;
    cfg.P8[PIDMAG] = 40;
    // cfg.P8[PIDVEL] = 0;
    // cfg.I8[PIDVEL] = 0;
    // cfg.D8[PIDVEL] = 0;
    cfg.rcRate8 = 99;
    cfg.rcExpo8 = 20;
    // cfg.rollPitchRate = 0;
    // cfg.yawRate = 0;
    // cfg.dynThrPID = 0;
    cfg.thrMid8 = 50;
    // cfg.thrExpo8 = 0;
    // for (i = 0; i < CHECKBOXITEMS; i++)
    //     cfg.activate[i] = 0;
    // cfg.angleTrim[0] = 0;
    // cfg.angleTrim[1] = 0;
    // cfg.accZero[0] = 0;
    // cfg.accZero[1] = 0;
    // cfg.accZero[2] = 0;
    // cfg.mag_declination = 0;    // For example, -6deg 37min, = -637 Japan, format is [sign]dddmm (degreesminutes) default is zero.
    memcpy(&cfg.align, default_align, sizeof(cfg.align));
    cfg.acc_hardware = ACC_DEFAULT;     // default/autodetect
    cfg.acc_lpf_factor = 4;
    cfg.acc_lpf_for_velocity = 10;
    cfg.accz_deadband = 50;
    cfg.gyro_cmpf_factor = 400; // default MWC
    cfg.gyro_lpf = 42;
    cfg.mpu6050_scale = 1; // fuck invensense
    cfg.baro_tab_size = 21;
    cfg.baro_noise_lpf = 0.6f;
    cfg.baro_cf = 0.985f;
    cfg.moron_threshold = 32;
    cfg.gyro_smoothing_factor = 0x00141403;     // default factors of 20, 20, 3 for R/P/Y
    cfg.vbatscale = 110;
    cfg.vbatmaxcellvoltage = 43;
    cfg.vbatmincellvoltage = 33;
    // cfg.power_adc_channel = 0;

    // Radio
    parseRcChannels("AETR1234");
    // cfg.deadband = 0;
    // cfg.yawdeadband = 0;
    cfg.alt_hold_throttle_neutral = 20;
    // cfg.spektrum_hires = 0;
    cfg.midrc = 1500;
    cfg.mincheck = 1100;
    cfg.maxcheck = 1900;
    // cfg.retarded_arm = 0;       // disable arm/disarm on roll left/right

    // Failsafe Variables
    cfg.failsafe_delay = 10;            // 1sec
    cfg.failsafe_off_delay = 200;       // 20sec
    cfg.failsafe_throttle = 1200;       // decent default which should always be below hover throttle for people.

    // Motor/ESC/Servo
    cfg.minthrottle = 1150;
    cfg.maxthrottle = 1850;
    cfg.mincommand = 1000;
    cfg.motor_pwm_rate = 490;
    cfg.servo_pwm_rate = 50;

    // servos
    cfg.yaw_direction = 1;
    cfg.tri_yaw_middle = 1500;
    cfg.tri_yaw_min = 1020;
    cfg.tri_yaw_max = 2000;

    // fixed wing
    cfg.pitch_min = 1020;
    cfg.pitch_mid = 1500;
    cfg.pitch_max = 1980;
    cfg.yaw_min = 1020;
    cfg.yaw_mid = 1500;
    cfg.yaw_max = 1980;
    cfg.flaperons = 0;						// enable (1) / disable (0) flaperon function
    cfg.flap_aux = 0;						// which AUX channel use to toggle flaps
    cfg.vtail = 0;							// airplane tail configuration, X (elev + rudd) [0] or V tail [1]
    cfg.pitch_direction = 1;				// airplane pitch servo orientation
    cfg.pitch_direction_l = 1;              // (Flying-wing only) left servo - pitch orientation
    cfg.pitch_direction_r = -1;              // (Flying-wing only) right servo - pitch orientation (opposite sign to pitch_direction_l if servos are mounted mirrored)
    cfg.roll_direction_l = 1;               // left servo - roll orientation
    cfg.roll_direction_r = -1;               // right servo - roll orientation  (same sign as ROLL_DIRECTION_L, if servos are mounted in mirrored orientation)

    // flying wing
    cfg.wing_left_min = 1020;
    cfg.wing_left_mid = 1500;
    cfg.wing_left_max = 1980;
    cfg.wing_right_min = 1020;
    cfg.wing_right_mid = 1500;
    cfg.wing_right_max = 1980;
    cfg.pitch_direction_l = 1;
    cfg.pitch_direction_r = -1;
    cfg.roll_direction_l = 1;
    cfg.roll_direction_r = 1;

    // gimbal
    cfg.gimbal_pitch_gain = 10;
    cfg.gimbal_roll_gain = 10;
    cfg.gimbal_flags = GIMBAL_NORMAL;
    cfg.gimbal_pitch_min = 1020;
    cfg.gimbal_pitch_max = 2000;
    cfg.gimbal_pitch_mid = 1500;
    cfg.gimbal_roll_min = 1020;
    cfg.gimbal_roll_max = 2000;
    cfg.gimbal_roll_mid = 1500;

    // gps/nav stuff
    cfg.gps_type = GPS_NMEA;
    cfg.gps_baudrate = 115200;
    cfg.gps_wp_radius = 200;
    cfg.gps_lpf = 20;
    cfg.nav_slew_rate = 30;
    cfg.nav_controls_heading = 1;
    cfg.nav_speed_min = 100;
    cfg.nav_speed_max = 300;

    // serial (USART1) baudrate
    cfg.serial_baudrate = 115200;

    // custom mixer. clear by defaults.
    for (i = 0; i < MAX_MOTORS; i++)
        cfg.customMixer[i].throttle = 0.0f;
    writeParams(0);
}

bool getSensors(uint32_t mask)
{
    return enabledSensors & mask;
}

void setSensors(uint32_t mask)
{
    enabledSensors |= mask;
}

void clearSensors(uint32_t mask)
{
    enabledSensors &= ~(mask);
}

uint32_t sensorsMask(void)
{
    return enabledSensors;
}

bool getFeature(uint32_t mask)
{
    return cfg.enabledFeatures & mask;
}

void setFeature(uint32_t mask)
{
    cfg.enabledFeatures |= mask;
}

void featureClear(uint32_t mask)
{
    cfg.enabledFeatures &= ~(mask);
}

void featureClearAll()
{
    cfg.enabledFeatures = 0;
}

uint32_t featureMask(void)
{
    return cfg.enabledFeatures;
}
rual
SergDoc:

занято только примерно пол килобайта, ещё 127,5 - свободны

Жалко тереть такую страницу, лучше всёж попытаться уйти в мелкий сектор.

SergDoc

ну пока не напрягает, у меня всего кода на 68к… хотя можно смело спрыгнуть в первый сектор (не нулевой)…

rual

Сергей, у тебя к этому порту ГУЙ Вийский или что-то своё?

SergDoc

Вий но пока до него не добрался… в вингуи сделали сразу терминал, разберусь с датчиками буду пробовать цепляться…
тут обновил

SergDoc

Добрался до гиро-акселя, пока присматриваю откуда спилить, вопрос такого плана DMA на SPI1 (там мпу висит) использовать?

rual
SergDoc:

вопрос такого плана DMA на SPI1 (там мпу висит) использовать?

Конечно использовать, это пзволит избежать затрат времени на тупую пересылку байт. Вообще можно по готовности ДУСа читтать весь набор регистров в буфер, а потом по необходимости программно разбирать.