diff --git a/arch/arm/include/stm32f7/dma2d.h b/arch/arm/include/stm32f7/dma2d.h new file mode 100755 index 00000000000..0ebffb05f50 --- /dev/null +++ b/arch/arm/include/stm32f7/dma2d.h @@ -0,0 +1,415 @@ +/**************************************************************************** + * arch/arm/include/stm32/dma2d.h + * + * Copyright (C) 2015 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_STM32F7_DMA2D_H +#define __ARCH_ARM_INCLUDE_STM32F7_DMA2D_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct ltdc_area_s; /* see arch/chip/ltdc.h */ + +/* Blend mode definitions */ + +enum dma2d_blend_e +{ + DMA2D_BLEND_NONE = 0, /* Disable all blend operation */ + DMA2D_BLEND_ALPHA = 0x1, /* Enable alpha blending */ + DMA2D_BLEND_PIXELALPHA = 0x2, /* Enable alpha blending from pixel color */ +}; + +/* The layer is controlled through the following structure */ + +struct dma2d_layer_s +{ + /* Name: getvideoinfo + * + * Description: + * Get video information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * vinfo - Reference to the video info structure + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getvideoinfo)(FAR struct dma2d_layer_s *layer, + FAR struct fb_videoinfo_s *vinfo); + + /* Name: getplaneinfo + * + * Description: + * Get plane information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * planeno - Number of the plane + * pinfo - Reference to the plane info structure + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getplaneinfo)(FAR struct dma2d_layer_s *layer, int planeno, + FAR struct fb_planeinfo_s *pinfo); + + /* Name: getlid + * + * Description: + * Get a specific layer identifier. + * + * Parameter: + * layer - Reference to the layer structure + * lid - Reference to store the layer id + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getlid)(FAR struct dma2d_layer_s *layer, int *lid); + +#ifdef CONFIG_STM32F7_DMA2D_L8 + /* Name: setclut + * + * Description: + * Configure layer clut (color lookup table). + * Non clut is defined during initializing. + * + * Parameter: + * layer - Reference to the layer structure + * cmap - color lookup table with up the 256 entries + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*setclut)(FAR struct dma2d_layer_s *layer, + const FAR struct fb_cmap_s *cmap); + + /* Name: getclut + * + * Description: + * Get configured layer clut (color lookup table). + * + * Parameter: + * layer - Reference to the layer structure + * cmap - Reference to valid color lookup table accept up the 256 color + * entries + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getclut)(FAR struct dma2d_layer_s *layer, FAR struct fb_cmap_s *cmap); +#endif + + /* Name: setalpha + * + * Description: + * Configure layer alpha value factor into blend operation. + * During the layer blend operation the source alpha value is multiplied + * with this alpha value. If the source color format doesn't support alpha + * channel (e.g. non ARGB8888) this alpha value will be used as constant + * alpha value for blend operation. + * Default value during initializing: 0xff + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*setalpha)(FAR struct dma2d_layer_s *layer, uint8_t alpha); + + /* Name: getalpha + * + * Description: + * Get configured layer alpha value factor for blend operation. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Reference to store the alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getalpha)(FAR struct dma2d_layer_s *layer, uint8_t *alpha); + + /* Name: setblendmode + * + * Description: + * Configure blend mode of the layer. + * Default mode during initializing: DMA2D_BLEND_NONE + * Blendmode is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Blend mode (see DMA2D_BLEND_*) + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure information: + * DMA2D_BLEND_NONE: + * Informs the driver to disable all blend operation for the given layer. + * That means the layer is opaque. + * + * DMA2D_BLEND_ALPHA: + * Informs the driver to enable alpha blending for the given layer. + * + * DMA2D_BLEND_PIXELALPHA: + * Informs the driver to use the pixel alpha value of the layer instead + * the constant alpha value. This is only useful for ARGB8888 + * color format. + */ + + int (*setblendmode)(FAR struct dma2d_layer_s *layer, uint32_t mode); + + /* Name: getblendmode + * + * Description: + * Get configured blend mode of the layer. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Reference to store the blend mode + * + * Return: + * On success - OK + * On error - -EINVAL + */ + + int (*getblendmode)(FAR struct dma2d_layer_s *layer, uint32_t *mode); + + /* Name: blit + * + * Description: + * Copy selected area from a source layer to selected position of the + * destination layer. + * + * Parameter: + * dest - Reference to the destination layer + * destxpos - Selected x target position of the destination layer + * destypos - Selected y target position of the destination layer + * src - Reference to the source layer + * srcarea - Reference to the selected area of the source layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the + * selected source area outside the visible area of the + * destination layer. (The visible area usually represents the + * display size) + * -ECANCELED - Operation cancelled, something goes wrong. + */ + + int (*blit)(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea); + + /* Name: blend + * + * Description: + * Blends the selected area from a background layer with selected position + * of the foreground layer. Copies the result to the selected position of + * the destination layer. Note! The content of the foreground and background + * layer keeps unchanged as long destination layer is unequal to the + * foreground and background layer. + * + * Parameter: + * dest - Reference to the destination layer + * fore - Reference to the foreground layer + * forexpos - Selected x target position of the foreground layer + * foreypos - Selected y target position of the foreground layer + * back - Reference to the background layer + * backarea - Reference to the selected area of the background layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the + * selected source area outside the visible area of the + * destination layer. (The visible area usually represents the + * display size) + * -ECANCELED - Operation cancelled, something goes wrong. + */ + + int (*blend)(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea); + + /* Name: fillarea + * + * Description: + * Fill the selected area of the whole layer with a specific color. + * + * Parameter: + * layer - Reference to the layer structure + * area - Reference to the valid area structure select the area + * color - Color to fill the selected area. Color must be formatted + * according to the layer pixel format. + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the + * selected area outside the visible area of the layer. + * -ECANCELED - Operation cancelled, something goes wrong. + */ + + int (*fillarea)(FAR struct dma2d_layer_s *layer, + FAR const struct ltdc_area_s *area, + uint32_t color); +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dma2dgetlayer + * + * Description: + * Get a dma2d layer structure by the layer identifier + * + * Parameter: + * lid - Layer identifier + * + * Return: + * Reference to the dma2d layer control structure on success or Null if no + * related exist. + * + ****************************************************************************/ + +FAR struct dma2d_layer_s *up_dma2dgetlayer(int lid); + +/**************************************************************************** + * Name: up_dma2dcreatelayer + * + * Description: + * Create a new dma2d layer object to interact with the dma2d controller + * + * Parameter: + * width - Layer width + * height - Layer height + * fmt - Pixel format of the layer + * + * Return: + * On success - A valid dma2d layer reference + * On error - NULL and errno is set to + * -EINVAL if one of the parameter is invalid + * -ENOMEM if no memory available or exceeds + * CONFIG_STM32F7_DMA2D_NLAYERS + * + ****************************************************************************/ + +FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width, + fb_coord_t height, + uint8_t fmt); + +/**************************************************************************** + * Name: up_dma2dremovelayer + * + * Description: + * Remove and deallocate the dma2d layer + * + * Parameter: + * layer - Reference to the layer to remove + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer); + +/**************************************************************************** + * Name: up_dma2dinitialize + * + * Description: + * Initialize the dma2d controller + * + * Return: + * OK - On success + * An error if initializing failed. + * + ****************************************************************************/ + +int up_dma2dinitialize(void); + +/**************************************************************************** + * Name: up_dma2duninitialize + * + * Description: + * Uninitialize the dma2d controller + * + ****************************************************************************/ + +void up_dma2duninitialize(void); + +#endif /* __ARCH_ARM_INCLUDE_STM32F7_DMA2D_H */ diff --git a/arch/arm/include/stm32f7/ltdc.h b/arch/arm/include/stm32f7/ltdc.h new file mode 100755 index 00000000000..ef5fa17f242 --- /dev/null +++ b/arch/arm/include/stm32f7/ltdc.h @@ -0,0 +1,592 @@ +/**************************************************************************** + * arch/arm/include/stm32/ltdc.h + * + * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_STM32F7_LTDC_H +#define __ARCH_ARM_INCLUDE_STM32F7_LTDC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_STM32F7_LTDC +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct dma2d_layer_s; /* see arch/chip/dma2d.h */ + +/* Blend mode definitions */ + +enum ltdc_blend_e +{ + LTDC_BLEND_NONE = 0, /* Disable all blend operation */ + LTDC_BLEND_ALPHA = 0x1, /* Enable alpha blending */ + LTDC_BLEND_PIXELALPHA = 0x2, /* Enable alpha blending from pixel color */ + LTDC_BLEND_COLORKEY = 0x4, /* Enable colorkey */ + LTDC_BLEND_ALPHAINV = 0x8, /* Inverse alpha blending of source */ + LTDC_BLEND_PIXELALPHAINV = 0x10 /* Invers pixel alpha blending of source */ +}; + +/* layer control definitions */ + +enum ltdc_layer_e +{ + LTDC_LAYER_OWN = 0, /* The given layer */ + LTDC_LAYER_TOP = 0x1, /* The initialized top layer */ + LTDC_LAYER_BOTTOM = 0x2, /* the initialized bottom layer */ + LTDC_LAYER_ACTIVE = 0x4, /* The current visible flip layer */ + LTDC_LAYER_INACTIVE = 0x8 /* The current invisible flip layer */ +#ifdef CONFIG_STM32F7_DMA2D + ,LTDC_LAYER_DMA2D = 0x10 /* The dma2d interface layer id */ +#endif +}; + +/* Update operation flag */ + +enum ltdc_update_e +{ + LTDC_UPDATE_NONE = 0, /* Update given layer only */ + LTDC_UPDATE_SIM = 0x1, /* Update both layer simultaneous */ + LTDC_UPDATE_FLIP = 0x2, /* Perform flip operation */ + LTDC_UPDATE_ACTIVATE = 0x4 /* Set the given layer to the active layer */ +}; + +/* sync mode definitions */ + +enum ltdc_sync_e +{ + LTDC_SYNC_NONE = 0, /* Immediately */ + LTDC_SYNC_VBLANK = 0x100, /* Upon vertical sync */ + LTDC_SYNC_WAIT = 0x200 /* Waits upon vertical sync */ +}; + +/* Definition of the visible layer position and size */ + +struct ltdc_area_s +{ + fb_coord_t xpos; /* X position in pixel */ + fb_coord_t ypos; /* Y position in pixel */ + fb_coord_t xres; /* X resolution in pixel */ + fb_coord_t yres; /* Y resolution in pixel */ +}; + +/* The layer is controlled through the following structure */ + +struct ltdc_layer_s +{ + + /* + * Name: getvideoinfo + * + * Description: + * Get video information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * vinfo - Reference to the video info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getvideoinfo)(FAR struct ltdc_layer_s *layer, + FAR struct fb_videoinfo_s *vinfo); + + /* + * Name: getplaneinfo + * + * Description: + * Get plane information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * planeno - Number of the plane + * pinfo - Reference to the plane info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getplaneinfo)(FAR struct ltdc_layer_s *layer, int planeno, + FAR struct fb_planeinfo_s *pinfo); + + /* + * Name: getlid + * + * Description: + * Get a specific layer identifier. + * + * Parameter: + * layer - Reference to the layer structure + * lid - Reference to store the layer id + * flag - Operation flag describe the layer identifier + * e.g. get the current active or inactive layer. + * See LTDC_LAYER_* for possible values + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getlid)(FAR struct ltdc_layer_s *layer, int *lid, uint32_t flag); + +#ifdef CONFIG_FB_CMAP + /* + * Name: setclut + * + * Description: + * Configure layer clut (color lookup table). + * Non clut is defined during initializing. + * Clut is active during next vertical blank period. Do not need an update. + * + * Parameter: + * layer - Reference to the layer structure + * cmap - color lookup table with up the 256 entries + * enable - Enable or disable clut support (if false cmap is ignored and can + * be NULL) + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*setclut)(FAR struct ltdc_layer_s *layer, + const FAR struct fb_cmap_s *cmap); + + /* + * Name: getclut + * + * Description: + * Get configured layer clut (color lookup table). + * + * Parameter: + * layer - Reference to the layer structure + * cmap - Reference to valid color lookup table accept up the 256 color + * entries + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getclut)(FAR struct ltdc_layer_s *layer, FAR struct fb_cmap_s *cmap); +#endif + + /* + * Name: setcolor + * + * Description: + * Configure layer color for the non active layer area. + * Default value during initializing: 0x00000000 + * Color is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * argb - ARGB8888 color value + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*setcolor)(FAR struct ltdc_layer_s *layer, uint32_t argb); + + /* + * Name: getcolor + * + * Description: + * Get configured layer color for the non active layer area. + * + * Parameter: + * layer - Reference to the layer structure + * argb - Reference to store the ARGB8888 color value + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getcolor)(FAR struct ltdc_layer_s *layer, uint32_t *argb); + + /* + * Name: setcolorkey + * + * Description: + * Configure the layer color key (chromakey) for transparence. + * Default value during initializing: 0x00000000 + * Colorkey is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * rgb - RGB888 color key + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*setcolorkey)(FAR struct ltdc_layer_s *layer, uint32_t rgb); + + /* + * Name: getcolorkey + * + * Description: + * Get the configured layer color key (chromakey) for transparence. + * + * Parameter: + * layer - Reference to the layer structure + * rgb - Reference to store the RGB888 color key + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getcolorkey)(FAR struct ltdc_layer_s *layer, uint32_t *rgb); + + /* + * Name: setalpha + * + * Description: + * Configure layer alpha value factor into blend operation. + * During the layer blend operation the source alpha value is multiplied + * with this alpha value. If the source color format doesn't support alpha + * channel (e.g. non ARGB8888) this alpha value will be used as constant + * alpha value for blend operation. + * Default value during initializing: 0xff + * Alpha is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*setalpha)(FAR struct ltdc_layer_s *layer, uint8_t alpha); + + /* + * Name: getalpha + * + * Description: + * Get configured layer alpha value factor for blend operation. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Reference to store the alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getalpha)(FAR struct ltdc_layer_s *layer, uint8_t *alpha); + + /* + * Name: setblendmode + * + * Description: + * Configure blend mode of the layer. + * Default mode during initializing: LTDC_BLEND_NONE + * Blendmode is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Blend mode (see LTDC_BLEND_*) + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure information: + * LTDC_BLEND_NONE: + * Informs the driver to disable all blend operation for the given layer. + * That means the layer is opaque. Note this has no effect on the + * colorkey settings. + * + * LTDC_BLEND_ALPHA: + * Informs the driver to enable alpha blending for the given layer. + * + * LTDC_BLEND_COLORKEY: + * Informs the driver to enable colorkeying for the given layer. + * + * LTDC_BLEND_SRCPIXELALPHA: + * Informs the driver to use the pixel alpha value of the layer instead + * the constant alpha value. This is only useful for ARGB8888 + * color format. + * + * LTDC_BLEND_DESTPIXELALPHA: + * Informs the driver to use the pixel alpha value of the subjacent layer + * instead the constant alpha value. This is only useful for ARGB8888 + * color format. + * + */ + int (*setblendmode)(FAR struct ltdc_layer_s *layer, uint32_t mode); + + /* + * Name: getblendmode + * + * Description: + * Get configured blend mode of the layer. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Reference to store the blend mode + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getblendmode)(FAR struct ltdc_layer_s *layer, uint32_t *mode); + + /* + * Name: setarea + * + * Description: + * Configure visible layer area and the reference position of the first + * pixel of the whole layer which is the first visible top left pixel in + * the active area. + * Default value during initializing: + * xpos = 0 + * ypos = 0 + * xres = display x resolution + * yres = display y resolution + * + * Area is active after next update. + * + * Parameter: + * layer - Reference to the layer control structure + * area - Reference to the valid area structure for the new active area + * srcxpos - x position of the visible pixel of the whole layer + * srcypos - y position of the visible pixel of the whole layer + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure Information: + * If the srcxpos and srcypos unequal the xpos and ypos of the coord + * structure this acts like moving the visible area to another position on + * the screen during the next update operation. + * + */ + int (*setarea)(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + fb_coord_t srcxpos, + fb_coord_t srcypos); + + /* + * Name: getarea + * + * Description: + * Get configured visible layer area. + * + * Parameter: + * layer - Reference to the layer control structure + * area - Reference to the area structure to store the active area + * srcxpos - Reference to store the referenced x position of the whole layer + * srcypos - Reference to store the reterenced y position of the whole layer + * + * Return: + * On success - OK + * On error - -EINVAL + * + */ + int (*getarea)(FAR struct ltdc_layer_s *layer, + FAR struct ltdc_area_s *area, + fb_coord_t *srcxpos, + fb_coord_t *srcypos); + + /* + * Name: update + * + * Description: + * Update current layer settings and make changes visible. + * + * Parameter: + * layer - Reference to the layer structure + * mode - operation mode (see LTDC_UPDATE_*) + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid + * -ECANCELED - Operation cancelled, something goes wrong + * + * Procedure information: + * LTDC_UPDATE_SIM: + * Informs the driver to update both ltdc layers simultaneously. Otherwise + * update the given layer only. + * + * LTDC_UPDATE_FLIP: + * Informs the driver to perform a flip operation. + * This only effects the ltdc layer 1 and 2 and can be useful for double + * buffering. Each flip operation changed the active layer ot the inactive + * and vice versa. In the context of the ltdc that means, the inactive layer + * is complete disabled. So the subjacent layer is the background layer + * (background color). To reactivate both layer and their settings perform + * an update without LTDC_UPDATE_FLIP flag. + * + * LTDC_UPDATE_ACTIVATE: + * Informs the driver that the given layer should be the active layer when + * the operation is complete. + * + * LTDC_SYNC_VBLANK: + * Informs the driver to update the layer upon vertical blank. Otherwise + * immediately. + * + */ + int (*update)(FAR struct ltdc_layer_s *layer, uint32_t mode); + +#ifdef CONFIG_STM32F7_DMA2D + /* + * Name: blit + * + * Description: + * Copy selected area from a source layer to selected position of the + * destination layer. + * + * Parameter: + * dest - Reference to the destination layer + * destxpos - Selected x position of the destination layer + * destypos - Selected y position of the destination layer + * src - Reference to the source layer + * srcarea - Reference to the selected area of the source layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * + */ + int (*blit)(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea); + /* + * + * Name: blend + * + * Description: + * Blends the selected area from a foreground layer with selected position + * of the background layer. Copy the result to the destination layer. Note! + * The content of the foreground and background layer is not changed. + * + * Parameter: + * dest - Reference to the destination layer + * destxpos - Selected x position of the destination layer + * destypos - Selected y position of the destination layer + * fore - Reference to the foreground layer + * forexpos - Selected x position of the foreground layer + * foreypos - Selected y position of the foreground layer + * back - Reference to the background layer + * backarea - Reference to the selected area of the background layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * + */ + int (*blend)(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea); + + /* + * Name: fillarea + * + * Description: + * Fill the selected area of the whole layer with a specific color. + * + * Parameter: + * layer - Reference to the layer structure + * area - Reference to the valid area structure select the area + * color - Color to fill the selected area. Color must be formatted + * according to the layer pixel format. + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * area outside the visible area of the layer. + * + */ + int (*fillarea)(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + uint32_t color); +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_ltdcgetlayer + * + * Description: + * Get the ltdc layer structure to perform hardware layer operation + * + * Parameter: + * lid - Layer identifier + * + * Return: + * Reference to the layer control structure on success or Null if parameter + * invalid. + * + ****************************************************************************/ +FAR struct ltdc_layer_s *up_ltdcgetlayer(int lid); +#endif /* CONFIG_STM32F7_LTDC */ +#endif /* __ARCH_ARM_INCLUDE_STM32F7_LTDC_H */ diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index 123277ba133..fc257a833a0 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1176,9 +1176,12 @@ config STM32F7_LTDC depends on STM32F7_HAVE_LTDC ---help--- The STM32 LTDC is an LCD-TFT Display Controller available on - the STM32F429 and STM32F439 devices. It is a standard parallel - video interface (HSYNC, VSYNC, etc.) for controlling TFT - LCD displays. + the STM32F7x6, STM32F7x7, STM32F7x8 and STM32F7x9 devices. + It features a standard RGB888 parallel video interface (along with HSYNC, VSYNC, etc.) + for controlling TFT LCD displays. + With the STM32F7x8/9, the graphics signals can optionally + be output via DSI instead of the parallel interface: + See config options STM32F7_DSIHOST and STM32F7_LTDC_USE_DSI. config STM32F7_OTGFS bool "OTG FS" @@ -4655,4 +4658,215 @@ config STM32F7_ETHMAC_REGDEBUG Enable very low-level register access debug. Depends on CONFIG_DEBUG_FEATURES. endmenu # Ethernet MAC configuration + +if STM32F7_LTDC + +menu "LTDC Configuration" + +config STM32F7_LTDC_INTERFACE + bool "LTDC interface support" + default n + ---help--- + Enable the ltdc interface to support ltdc layer control. + +config STM32F7_LTDC_USE_DSI + bool "Use DSI as display connection" + default n + depends on STM32F7_DSIHOST + ---help--- + Select this if your display is connected via DSI. + Deselect option if your display is connected via digital RGB+HSYNC+VSYNC + +config STM32F7_LTDC_BACKLIGHT + bool "Backlight support" + default y + +config STM32F7_LTDC_DEFBACKLIGHT + hex "Default backlight level" + default 0xf0 + +config STM32F7_LTDC_BACKCOLOR + hex "Background color" + default 0x0 + ---help--- + This is the background color that will be used as the LTDC + background layer color. It is an RGB888 format value. + +config STM32F7_LTDC_DITHER + bool "Dither support" + default n + +config STM32F7_LTDC_DITHER_RED + depends on STM32F7_LTDC_DITHER + int "Dither red width" + range 0 7 + default 2 + ---help--- + This is the dither red width. + +config STM32F7_LTDC_DITHER_GREEN + depends on STM32F7_LTDC_DITHER + int "Dither green width" + range 0 7 + default 2 + ---help--- + This is the dither green width. + +config STM32F7_LTDC_DITHER_BLUE + depends on STM32F7_LTDC_DITHER + int "Dither blue width" + range 0 7 + default 2 + ---help--- + This is the dither blue width. + +config STM32F7_LTDC_FB_BASE + hex "Framebuffer memory start address" + ---help--- + If you are using the LTDC, then you must provide the address + of the start of the framebuffer. This address will typically + be in the SRAM or SDRAM memory region of the FSMC. + +config STM32F7_LTDC_FB_SIZE + int "Framebuffer memory size (bytes)" + default 0 + +choice + prompt "Layer 1 color format" + default STM32F7_LTDC_L1_RGB565 + +config STM32F7_LTDC_L1_L8 + bool "8 bpp L8 (8-bit CLUT)" + +config STM32F7_LTDC_L1_AL44 + bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + +config STM32F7_LTDC_L1_AL88 + bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + +config STM32F7_LTDC_L1_RGB565 + bool "16 bpp RGB 565" + +config STM32F7_LTDC_L1_ARGB4444 + bool "16 bpp ARGB 4444" + +config STM32F7_LTDC_L1_ARGB1555 + bool "16 bpp ARGB 1555" + +config STM32F7_LTDC_L1_RGB888 + bool "24 bpp RGB 888" + +config STM32F7_LTDC_L1_ARGB8888 + bool "32 bpp ARGB 8888" + +endchoice # Layer 1 color format + +config STM32F7_LTDC_L2 + bool "Enable Layer 2 support" + default y + +if STM32F7_LTDC_L2 + +choice + prompt "Layer 2 (top layer) color format" + default STM32F7_LTDC_L2_RGB565 + +config STM32F7_LTDC_L2_L8 + bool "8 bpp L8 (8-bit CLUT)" + +config STM32F7_LTDC_L2_AL44 + bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + +config STM32F7_LTDC_L2_AL88 + bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + +config STM32F7_LTDC_L2_RGB565 + bool "16 bpp RGB 565" + +config STM32F7_LTDC_L2_ARGB4444 + bool "16 bpp ARGB 4444" + +config STM32F7_LTDC_L2_ARGB1555 + bool "16 bpp ARGB 1555" + +config STM32F7_LTDC_L2_RGB888 + bool "24 bpp RGB 888" + +config STM32F7_LTDC_L2_ARGB8888 + bool "32 bpp ARGB 8888" + +endchoice # Layer 2 color format + +endif # STM32F7_LTDC_L2 + +if STM32F7_LTDC_L1_L8 || STM32F7_LTDC_L2_L8 + +config FB_CMAP + bool "Enable color map support" + default y + ---help--- + Enabling color map support is neccessary for ltdc L8 format. + +config FB_TRANSPARENCY + bool "Enable transparency color map support" + default y + ---help--- + Enabling transparency color map support is neccessary for ltdc L8 format. + +endif +endmenu + +endif # STM32F7_LTDC + +if STM32F7_DMA2D + +menu "DMA2D Configuration" + +config STM32F7_DMA2D_NLAYERS + int "Number DMA2D layers" + default 2 + ---help--- + Number of allocatable DMA2D layers except the LTDC layer. + +menu "Supported pixel format" + +config STM32F7_DMA2D_L8 + depends on FB_CMAP + bool "8 bpp L8 (8-bit CLUT)" + default y + +config STM32F7_DMA2D_AL44 + depends on FB_CMAP + bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + default n + +config STM32F7_DMA2D_AL88 + depends on FB_CMAP + bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + default n + +config STM32F7_DMA2D_RGB565 + bool "16 bpp RGB 565" + default y + +config STM32F7_DMA2D_ARGB4444 + bool "16 bpp ARGB 4444" + default n + +config STM32F7_DMA2D_ARGB1555 + bool "16 bpp ARGB 1555" + default n + +config STM32F7_DMA2D_RGB888 + bool "24 bpp RGB 888" + default y + +config STM32F7_DMA2D_ARGB8888 + bool "32 bpp ARGB 8888" + default n + +endmenu +endmenu +endif # STM32F7_DMA2D + endif # ARCH_CHIP_STM32F7 diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs index 06a190f463f..283f28e172e 100644 --- a/arch/arm/src/stm32f7/Make.defs +++ b/arch/arm/src/stm32f7/Make.defs @@ -202,3 +202,11 @@ endif ifeq ($(CONFIG_STM32F7_RNG),y) CHIP_CSRCS += stm32_rng.c endif + +ifeq ($(CONFIG_STM32F7_LTDC),y) +CHIP_CSRCS += stm32_ltdc.c +endif + +ifeq ($(CONFIG_STM32F7_DMA2D),y) +CHIP_CSRCS += stm32_dma2d.c +endif diff --git a/arch/arm/src/stm32f7/chip/stm32_dma2d.h b/arch/arm/src/stm32f7/chip/stm32_dma2d.h new file mode 100755 index 00000000000..7a44561a1db --- /dev/null +++ b/arch/arm/src/stm32f7/chip/stm32_dma2d.h @@ -0,0 +1,230 @@ +/**************************************************************************** + * arch/arm/src/stm32/chip/stm32_dma2d.h + * + * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip/stm32_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32_DMA2D_NCLUT 256 /* Number of entries in the CLUT */ + +/* DMA2D Register Offsets ****************************************************/ + +#define STM32_DMA2D_CR_OFFSET 0x0000 /* DMA2D Control Register */ +#define STM32_DMA2D_ISR_OFFSET 0x0004 /* DMA2D Interrupt Status Register */ +#define STM32_DMA2D_IFCR_OFFSET 0x0008 /* DMA2D Interrupt Flag Clear Register */ +#define STM32_DMA2D_FGMAR_OFFSET 0x000C /* DMA2D Foreground Memory Address Register */ +#define STM32_DMA2D_FGOR_OFFSET 0x0010 /* DMA2D Foreground Offset Register */ +#define STM32_DMA2D_BGMAR_OFFSET 0x0014 /* DMA2D Background Memory Address Register */ +#define STM32_DMA2D_BGOR_OFFSET 0x0018 /* DMA2D Background Offset Register */ +#define STM32_DMA2D_FGPFCCR_OFFSET 0x001C /* DMA2D Foreground PFC Control Register */ +#define STM32_DMA2D_FGCOLR_OFFSET 0x0020 /* DMA2D Foreground Color Register */ +#define STM32_DMA2D_BGPFCCR_OFFSET 0x0024 /* DMA2D Background PFC Control Register */ +#define STM32_DMA2D_BGCOLR_OFFSET 0x0028 /* DMA2D Background Color Register */ +#define STM32_DMA2D_FGCMAR_OFFSET 0x002C /* DMA2D Foreground CLUT Memory Address Register */ +#define STM32_DMA2D_BGCMAR_OFFSET 0x0030 /* DMA2D Background CLUT Memory Address Register */ +#define STM32_DMA2D_OPFCCR_OFFSET 0x0034 /* DMA2D Output PFC Control Register */ +#define STM32_DMA2D_OCOLR_OFFSET 0x0038 /* DMA2D Output Color Register */ +#define STM32_DMA2D_OMAR_OFFSET 0x003C /* DMA2D Output Memory Address Register */ +#define STM32_DMA2D_OOR_OFFSET 0x0040 /* DMA2D Output Offset Register */ +#define STM32_DMA2D_NLR_OFFSET 0x0044 /* DMA2D Number Of Line Register */ +#define STM32_DMA2D_LWR_OFFSET 0x0048 /* DMA2D Line Watermark Register */ +#define STM32_DMA2D_AMTCR_OFFSET 0x004C /* DMA2D AHB Master Time Configuration Register */ + +/* DMA2D Register Addresses **************************************************/ + +#define STM32_DMA2D_CR (STM32_DMA2D_BASE+STM32_DMA2D_CR_OFFSET) +#define STM32_DMA2D_ISR (STM32_DMA2D_BASE+STM32_DMA2D_ISR_OFFSET) +#define STM32_DMA2D_IFCR (STM32_DMA2D_BASE+STM32_DMA2D_IFCR_OFFSET) +#define STM32_DMA2D_FGMAR (STM32_DMA2D_BASE+STM32_DMA2D_FGMAR_OFFSET) +#define STM32_DMA2D_FGOR (STM32_DMA2D_BASE+STM32_DMA2D_FGOR_OFFSET) +#define STM32_DMA2D_BGMAR (STM32_DMA2D_BASE+STM32_DMA2D_BGMAR_OFFSET) +#define STM32_DMA2D_BGOR (STM32_DMA2D_BASE+STM32_DMA2D_BGOR_OFFSET) +#define STM32_DMA2D_FGPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_FGPFCCR_OFFSET) +#define STM32_DMA2D_FGCOLR (STM32_DMA2D_BASE+STM32_DMA2D_FGCOLR_OFFSET) +#define STM32_DMA2D_BGPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_BGPFCCR_OFFSET) +#define STM32_DMA2D_BGCOLR (STM32_DMA2D_BASE+STM32_DMA2D_BGCOLR_OFFSET) +#define STM32_DMA2D_FGCMAR (STM32_DMA2D_BASE+STM32_DMA2D_FGCMAR_OFFSET) +#define STM32_DMA2D_BGCMAR (STM32_DMA2D_BASE+STM32_DMA2D_BGCMAR_OFFSET) +#define STM32_DMA2D_OPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_OPFCCR_OFFSET) +#define STM32_DMA2D_OCOLR (STM32_DMA2D_BASE+STM32_DMA2D_OCOLR_OFFSET) +#define STM32_DMA2D_OMAR (STM32_DMA2D_BASE+STM32_DMA2D_OMAR_OFFSET) +#define STM32_DMA2D_OOR (STM32_DMA2D_BASE+STM32_DMA2D_OOR_OFFSET) +#define STM32_DMA2D_NLR (STM32_DMA2D_BASE+STM32_DMA2D_NLR_OFFSET) +#define STM32_DMA2D_LWR (STM32_DMA2D_BASE+STM32_DMA2D_LWR_OFFSET) + +/* DMA2D Register Bit Definitions ********************************************/ + +/* DMA2D Control Register */ + +#define DMA2D_CR_START (1 << 0) /* Start Bit */ +#define DMA2D_CR_SUSP (1 << 1) /* Suspend Bit */ +#define DMA2D_CR_ABORT (1 << 2) /* Abort Bit */ +#define DMA2D_CR_TEIE (1 << 8) /* Transfer Error Interupt Enable Bit */ +#define DMA2D_CR_TCIE (1 << 9) /* Transfer Complete Interrupt Enable Bit */ +#define DMA2D_CR_TWIE (1 << 10) /* Transfer Watermark Interrupt Enable Bit */ +#define DMA2D_CR_CAEIE (1 << 11) /* CLUT Access Error Interrupt Enable Bit */ +#define DMA2D_CR_CTCIE (1 << 12) /* CLUT Transfer Complete Interrupt Enable Bit */ +#define DMA2D_CR_CEIE (1 << 13) /* Configuration Error Interrupt Enable Bit */ +#define DMA2D_CR_MODE_SHIFT (16) /* Bits 16-17 DMA2D mode Bits */ +#define DMA2D_CR_MODE_MASK (3 << DMA2D_CR_MODE_SHIFT) +#define DMA2D_CR_MODE(n) ((uint32_t)(n) << DMA2D_CR_MODE_SHIFT) + +/* DMA2D Interrupt Status Register */ + +#define DMA2D_ISR_TEIF (1 << 0) /* Transfer error interrupt flag */ +#define DMA2D_ISR_TCIF (1 << 1) /* Transfer Complete Interrupt flag */ +#define DMA2D_ISR_TWIF (1 << 2) /* Transfer Watermark Interrupt flag */ +#define DMA2D_ISR_CAEIF (1 << 3) /* CLUT Access Error Interrupt flag */ +#define DMA2D_ISR_CTCIF (1 << 4) /* CLUT Transfer Complete Interrupt flag */ +#define DMA2D_ISR_CEIF (1 << 5) /* Configuration Error Interrupt flag */ + +/* DMA2D Interrupt Flag Clear Register */ + +#define DMA2D_IFCR_CTEIF (1 << 0) /* Clear Transfer Interrupt Flag */ +#define DMA2D_IFCR_CTCIF (1 << 1) /* Clear Transfer Complete Interrupt Flag */ +#define DMA2D_IFCR_CTWIF (1 << 2) /* Clear Transfer Watermark Interrupt Flag */ +#define DMA2D_IFCR_CAECIF (1 << 3) /* Clear CLUT Access Error Interrupt Flag */ +#define DMA2D_IFCR_CCTCIF (1 << 4) /* Clear CLUT Transfer Complete Interrupt Flag */ +#define DMA2D_IFCR_CCEIF (1 << 5) /* Clear Configuration Error Interrupt Flag */ + +/* DMA2D Foreground Memory Access Register */ + +/* DMA2D Background Memory Access Register */ + +/* DMA2D Foreground/Background Offset Register */ + +#define DMA2D_xGOR_SHIFT (0) /* Bits 0-13 Line Offset */ +#define DMA2D_xGOR_MASK (0x3FFF << DMA2D_xGOR_SHIFT) +#define DMA2D_xGOR(n) ((uint32_t)(n) << DMA2D_xGOR_SHIFT) + +/* DMA2D Foreground/Background PFC Control Register */ + +#define DMA2D_xGPFCCR_CM_SHIFT (0) /* Bits 0-3 Color Mode */ +#define DMA2D_xGPFCCR_CM_MASK (0xF << DMA2D_xGPFCCR_CM_SHIFT) +#define DMA2D_xGPFCCR_CM(n) ((uint32_t)(n) << DMA2D_xGPFCCR_CM_SHIFT) +#define DMA2D_xGPFCCR_CCM (1 << 4) /* CLUT Color Mode */ +#define DMA2D_xGPFCCR_START (1 << 5) /* Start */ +#define DMA2D_xGPFCCR_CS_SHIFT (8) /* Bits 8-15 CLUT Size */ +#define DMA2D_xGPFCCR_CS_MASK (0xFF << DMA2D_xGPFCCR_CS_SHIFT) +#define DMA2D_xGPFCCR_CS(n) ((uint32_t)(n) << DMA2D_xGPFCCR_CS_SHIFT) +#define DMA2D_xGPFCCR_AM_SHIFT (16) /* Bits 16-17 Alpha Mode */ +#define DMA2D_xGPFCCR_AM_MASK (3 << DMA2D_xGPFCCR_AM_SHIFT) +#define DMA2D_xGPFCCR_AM(n) ((uint32_t)(n) << DMA2D_xGPFCCR_AM_SHIFT) +#define DMA2D_xGPFCCR_ALPHA_SHIFT (24) /* Bits 24-31 Alpha Value */ +#define DMA2D_xGPFCCR_ALPHA_MASK (0xFF << DMA2D_xGPFCCR_ALPHA_SHIFT) +#define DMA2D_xGPFCCR_ALPHA(n) ((uint32_t)(n) << DMA2D_xGPFCCR_ALPHA_SHIFT) + +/* DMA2D Foreground/Background Color Register */ + +#define DMA2D_xGCOLR_BLUE_SHIFT (0) /* Bits 0-7 Blue Value */ +#define DMA2D_xGCOLR_BLUE_MASK (0xFF << DMA2D_xGCOLR_BLUE_SHIFT) +#define DMA2D_xGCOLR_BLUE(n) ((uint32_t)(n) << DMA2D_xGCOLR_BLUE_SHIFT) +#define DMA2D_xGCOLR_GREEN_SHIFT (8) /* Bits 8-15 Green Value */ +#define DMA2D_xGCOLR_GREEN_MASK (0xFF << DMA2D_xGCOLR_GREEN_SHIFT) +#define DMA2D_xGCOLR_GREEN(n) ((uint32_t)(n) << DMA2D_xGCOLR_GREEN_SHIFT) +#define DMA2D_xGCOLR_RED_SHIFT (16) /* Bits 16-23 Red Value */ +#define DMA2D_xGCOLR_RED_MASK (0xFF << DMA2D_xGCOLR_RED_SHIFT) +#define DMA2D_xGCOLR_RED(n) ((uint32_t)(n) << DMA2D_xGCOLR_RED_SHIFT) + +/* DMA2D Foreground CLUT Memory Address Register */ + +/* DMA2D Background CLUT Memory Address Register */ + +/* DMA2D Output PFC Control Register */ + +#define DMA2D_OPFCCR_CM_SHIFT (0) /* Bits 0-2 Color Mode */ +#define DMA2D_OPFCCR_CM_MASK (7 << DMA2D_OPFCCR_CM_SHIFT) +#define DMA2D_OPFCCR_CM(n) ((uint32_t)(n) << DMA2D_OPFCCR_CM_SHIFT) + +/* DMA2D Output Color Register */ + +#define DMA2D_OCOLR_BLUE_SHIFT (0) /* Bits 0-7 Blue Value */ +#define DMA2D_OCOLR_BLUE_MASK (0xFF << DMA2D_OCOLR_BLUE_SHIFT) +#define DMA2D_OCOLR_BLUE(n) ((uint32_t)(n) << DMA2D_OCOLR_BLUE_SHIFT) +#define DMA2D_OCOLR_GREEN_SHIFT (8) /* Bits 8-15 Green Value */ +#define DMA2D_OCOLR_GREEN_MASK (0xFF << DMA2D_OCOLR_GREEN_SHIFT) +#define DMA2D_OCOLR_GREEN(n) ((uint32_t)(n) << DMA2D_OCOLR_GREEN_SHIFT) +#define DMA2D_OCOLR_RED_SHIFT (16) /* Bits 16-23 Red Value */ +#define DMA2D_OCOLR_RED_MASK (0xFF << DMA2D_OCOLR_RED_SHIFT) +#define DMA2D_OCOLR_RED(n) ((uint32_t)(n) << DMA2D_OCOLR_RED_SHIFT) +#define DMA2D_OCOLR_ALPHA_SHIFT (24) /* Bits 24-31 Alpha Value */ +#define DMA2D_OCOLR_ALPHA_MASK (0xFF << DMA2D_OCOLR_ALPHA_SHIFT) +#define DMA2D_OCOLR_ALPHA(n) ((uint32_t)(n) << DMA2D_OCOLR_ALPHA_SHIFT) + +/* DMA2D Output Memory Address Register */ + +/* DMA2D Output Offset Register */ + +#define DMA2D_OOR_LO_SHIFT (0) /* Bits 0-13 Line Offset */ +#define DMA2D_OOR_LO_MASK (0x3FFF << DMA2D_OOR_LO_SHIFT) +#define DMA2D_OOR_LO(n) ((uint32_t)(n) << DMA2D_OOR_LO_SHIFT) + +/* DMA2D Number Of Line Register */ + +#define DMA2D_NLR_NL_SHIFT (0) /* Bits 0-15 Number Of Lines */ +#define DMA2D_NLR_NL_MASK (0xFFFF << DMA2D_NLR_NL_SHIFT) +#define DMA2D_NLR_NL(n) ((uint32_t)(n) << DMA2D_NLR_NL_SHIFT) +#define DMA2D_NLR_PL_SHIFT (16) /* Bits 16-29 Pixel per Lines */ +#define DMA2D_NLR_PL_MASK (0x3FFF << DMA2D_NLR_PL_SHIFT) +#define DMA2D_NLR_PL(n) ((uint32_t)(n) << DMA2D_NLR_PL_SHIFT) + +/* DMA2D Line Watermark Register */ + +#define DMA2D_LWR_LW_SHIFT (0) /* Bits 0-15 Line Watermark */ +#define DMA2D_LWR_LW_MASK (0xFFFF << DMA2D_LWR_LW_SHIFT) +#define DMA2D_LWR_LW(n) ((uint32_t)(n) << DMA2D_LWR_LW_SHIFT) + +/* DMA2D AHB Master Timer Configuration Register */ + +#define DMA2D_AMTCR_EN (1 << 0) /* Enable */ +#define DMA2D_AMTCR_DT_SHIFT (0) /* Bits 8-15 Dead Time */ +#define DMA2D_AMTCR_DT_MASK (0xFF << DMA2D_AMTCR_DT_SHIFT) +#define DMA2D_AMTCR_DT(n) ((uint32_t)(n) << DMA2D_AMTCR_DT_SHIFT) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H */ diff --git a/arch/arm/src/stm32f7/chip/stm32_ltdc.h b/arch/arm/src/stm32f7/chip/stm32_ltdc.h new file mode 100755 index 00000000000..38068183c5d --- /dev/null +++ b/arch/arm/src/stm32f7/chip/stm32_ltdc.h @@ -0,0 +1,381 @@ +/************************************************************************************ + * arch/arm/src/stm32/chip/stm32_ltdc.h + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32F7_CHIP_STM32_LTDC_H +#define __ARCH_ARM_SRC_STM32F7_CHIP_STM32_LTDC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip/stm32_memorymap.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_LTDC_NCLUT 256 /* Number of entries in the CLUTs */ + +/* LCDC Register Offsets ************************************************************/ + +#define STM32_LTDC_SSCR_OFFSET 0x0008 /* LTDC Synchronization Size Config Register */ +#define STM32_LTDC_BPCR_OFFSET 0x000c /* LTDC Back Porch Configuration Register */ +#define STM32_LTDC_AWCR_OFFSET 0x0010 /* LTDC Active Width Configuration Register */ +#define STM32_LTDC_TWCR_OFFSET 0x0014 /* LTDC Total Width Configuration Register */ +#define STM32_LTDC_GCR_OFFSET 0x0018 /* LTDC Global Control Register */ + /* 0x0020 Reserved */ +#define STM32_LTDC_SRCR_OFFSET 0x0024 /* LTDC Shadow Reload Configuration Register */ + /* 0x0028 Reserved */ +#define STM32_LTDC_BCCR_OFFSET 0x002C /* LTDC Background Color Configuration Register */ + /* 0x0030 Reserved */ +#define STM32_LTDC_IER_OFFSET 0x0034 /* LTDC Interrupt Enable Register */ +#define STM32_LTDC_ISR_OFFSET 0x0038 /* LTDC Interrupt Status Register */ +#define STM32_LTDC_ICR_OFFSET 0x003C /* LTDC Interrupt Clear Register */ +#define STM32_LTDC_LIPCR_OFFSET 0x0040 /* LTDC Line Interrupt Position Config Register */ +#define STM32_LTDC_CPSR_OFFSET 0x0044 /* LTDC Current Position Status Register */ +#define STM32_LTDC_CDSR_OFFSET 0x0048 /* LTDC Current Display Status Register */ + /* 0x004c-0x0080 Reserved */ + +#define STM32_LTDC_L1CR_OFFSET 0x0084 /* LTDC Layer 1 Control Register */ +#define STM32_LTDC_L1WHPCR_OFFSET 0x0088 /* LTDC Layer 1 Window Horiz Pos Config Register */ +#define STM32_LTDC_L1WVPCR_OFFSET 0x008C /* LTDC Layer 1 Window Vert Pos Config Register */ +#define STM32_LTDC_L1CKCR_OFFSET 0x0090 /* LTDC Layer 1 Color Keying Config Register */ +#define STM32_LTDC_L1PFCR_OFFSET 0x0094 /* LTDC Layer 1 Pixel Format Configuration Register */ +#define STM32_LTDC_L1CACR_OFFSET 0x0098 /* LTDC Layer 1 Constant Alpha Config Register */ +#define STM32_LTDC_L1DCCR_OFFSET 0x009C /* LTDC Layer 1 Default Color Config Register */ +#define STM32_LTDC_L1BFCR_OFFSET 0x00A0 /* LTDC Layer 1 Blending Factors Config Register */ + /* 0x00A4-0x00A8 Reserved */ +#define STM32_LTDC_L1CFBAR_OFFSET 0x00AC /* LTDC Layer 1 Color Frame Buffer Address Register */ +#define STM32_LTDC_L1CFBLR_OFFSET 0x00B0 /* LTDC Layer 1 Color Frame Buffer Length Register */ +#define STM32_LTDC_L1CFBLNR_OFFSET 0x00B4 /* LTDC Layer 1 Color Frame Buffer Line Number Register */ + /* 0x00B8-0x00C0 Reserved */ +#define STM32_LTDC_L1CLUTWR_OFFSET 0x00C4 /* LTDC Layer 1 CLUT Write Register */ + /* 0x00C8-0x0100 Reserved */ +#define STM32_LTDC_L2CR_OFFSET 0x0104 /* LTDC Layer 2 Control Register */ +#define STM32_LTDC_L2WHPCR_OFFSET 0x0108 /* LTDC Layer 2 Window Horiz Pos Config Register */ +#define STM32_LTDC_L2WVPCR_OFFSET 0x010C /* LTDC Layer 2 Window Vert Pos Config Register */ +#define STM32_LTDC_L2CKCR_OFFSET 0x0110 /* LTDC Layer 2 Color Keying Config Register */ +#define STM32_LTDC_L2PFCR_OFFSET 0x0114 /* LTDC Layer 2 Pixel Format Configuration Register */ +#define STM32_LTDC_L2CACR_OFFSET 0x0118 /* LTDC Layer 2 Constant Alpha Config Register */ +#define STM32_LTDC_L2DCCR_OFFSET 0x011C /* LTDC Layer 2 Default Color Config Register */ +#define STM32_LTDC_L2BFCR_OFFSET 0x0120 /* LTDC Layer 2 Blending Factors Config Register */ + /* 0x0124-0x0128 Reserved */ +#define STM32_LTDC_L2CFBAR_OFFSET 0x012C /* LTDC Layer 2 Color Frame Buffer Address Register */ +#define STM32_LTDC_L2CFBLR_OFFSET 0x0130 /* LTDC Layer 2 Color Frame Buffer Length Register */ +#define STM32_LTDC_L2CFBLNR_OFFSET 0x0134 /* LTDC Layer 2 Color Frame Buffer Line Number Register */ + /* 0x0138-0x0130 Reserved */ +#define STM32_LTDC_L2CLUTWR_OFFSET 0x0144 /* LTDC Layer 2 CLUT Write Register */ + /* 0x0148-0x03ff Reserved */ + +/* LTDC Register Addresses *********************************************************/ + +#define STM32_LTDC_SSCR (STM32_LTDC_BASE+STM32_LTDC_SSCR_OFFSET) +#define STM32_LTDC_BPCR (STM32_LTDC_BASE+STM32_LTDC_BPCR_OFFSET) +#define STM32_LTDC_AWCR (STM32_LTDC_BASE+STM32_LTDC_AWCR_OFFSET) +#define STM32_LTDC_TWCR (STM32_LTDC_BASE+STM32_LTDC_TWCR_OFFSET) +#define STM32_LTDC_GCR (STM32_LTDC_BASE+STM32_LTDC_GCR_OFFSET) +#define STM32_LTDC_SRCR (STM32_LTDC_BASE+STM32_LTDC_SRCR_OFFSET) +#define STM32_LTDC_BCCR (STM32_LTDC_BASE+STM32_LTDC_BCCR_OFFSET) +#define STM32_LTDC_IER (STM32_LTDC_BASE+STM32_LTDC_IER_OFFSET) +#define STM32_LTDC_ISR (STM32_LTDC_BASE+STM32_LTDC_ISR_OFFSET) +#define STM32_LTDC_ICR (STM32_LTDC_BASE+STM32_LTDC_ICR_OFFSET) +#define STM32_LTDC_LIPCR (STM32_LTDC_BASE+STM32_LTDC_LIPCR_OFFSET) +#define STM32_LTDC_CPSR (STM32_LTDC_BASE+STM32_LTDC_CPSR_OFFSET) +#define STM32_LTDC_CDSR (STM32_LTDC_BASE+STM32_LTDC_CDSR_OFFSET) + +#define STM32_LTDC_L1CR (STM32_LTDC_BASE+STM32_LTDC_L1CR_OFFSET) +#define STM32_LTDC_L1WHPCR (STM32_LTDC_BASE+STM32_LTDC_L1WHPCR_OFFSET) +#define STM32_LTDC_L1WVPCR (STM32_LTDC_BASE+STM32_LTDC_L1WVPCR_OFFSET) +#define STM32_LTDC_L1CKCR (STM32_LTDC_BASE+STM32_LTDC_L1CKCR_OFFSET) +#define STM32_LTDC_L1PFCR (STM32_LTDC_BASE+STM32_LTDC_L1PFCR_OFFSET) +#define STM32_LTDC_L1CACR (STM32_LTDC_BASE+STM32_LTDC_L1CACR_OFFSET) +#define STM32_LTDC_L1DCCR (STM32_LTDC_BASE+STM32_LTDC_L1DCCR_OFFSET) +#define STM32_LTDC_L1BFCR (STM32_LTDC_BASE+STM32_LTDC_L1BFCR_OFFSET) +#define STM32_LTDC_L1CFBAR (STM32_LTDC_BASE+STM32_LTDC_L1CFBAR_OFFSET) +#define STM32_LTDC_L1CFBLR (STM32_LTDC_BASE+STM32_LTDC_L1CFBLR_OFFSET) +#define STM32_LTDC_L1CFBLNR (STM32_LTDC_BASE+STM32_LTDC_L1CFBLNR_OFFSET) +#define STM32_LTDC_L1CLUTWR (STM32_LTDC_BASE+STM32_LTDC_L1CLUTWR_OFFSET) + +#define STM32_LTDC_L2CR (STM32_LTDC_BASE+STM32_LTDC_L2CR_OFFSET) +#define STM32_LTDC_L2WHPCR (STM32_LTDC_BASE+STM32_LTDC_L2WHPCR_OFFSET) +#define STM32_LTDC_L2WVPCR (STM32_LTDC_BASE+STM32_LTDC_L2WVPCR_OFFSET) +#define STM32_LTDC_L2CKCR (STM32_LTDC_BASE+STM32_LTDC_L2CKCR_OFFSET) +#define STM32_LTDC_L2PFCR (STM32_LTDC_BASE+STM32_LTDC_L2PFCR_OFFSET) +#define STM32_LTDC_L2CACR (STM32_LTDC_BASE+STM32_LTDC_L2CACR_OFFSET) +#define STM32_LTDC_L2DCCR (STM32_LTDC_BASE+STM32_LTDC_L2DCCR_OFFSET) +#define STM32_LTDC_L2BFCR (STM32_LTDC_BASE+STM32_LTDC_L2BFCR_OFFSET) +#define STM32_LTDC_L2CFBAR (STM32_LTDC_BASE+STM32_LTDC_L2CFBAR_OFFSET) +#define STM32_LTDC_L2CFBLR (STM32_LTDC_BASE+STM32_LTDC_L2CFBLR_OFFSET) +#define STM32_LTDC_L2CFBLNR (STM32_LTDC_BASE+STM32_LTDC_L2CFBLNR_OFFSET) +#define STM32_LTDC_L2CLUTWR (STM32_LTDC_BASE+STM32_LTDC_L2CLUTWR_OFFSET) + +/* LTDC Register Bit Definitions ***************************************************/ + +/* LTDC Synchronization Size Configuration Register */ + +#define LTDC_SSCR_VSH_SHIFT (0) /* Bits 0-10: Vertical Sync Height (scan lines) */ +#define LTDC_SSCR_VSH_MASK (0x7ff << LTDC_SSCR_VSH_SHIFT) +# define LTDC_SSCR_VSH(n) ((uint32_t)(n) << LTDC_SSCR_VSH_SHIFT) +#define LTDC_SSCR_HSW_SHIFT (16) /* Bits 16-27: Horizontal Sync Width (pixel clocks) */ +#define LTDC_SSCR_HSW_MASK (0xfff << LTDC_SSCR_HSW_SHIFT) +# define LTDC_SSCR_HSW(n) ((uint32_t)(n) << LTDC_SSCR_HSW_SHIFT) + +/* LTDC Back Porch Configuration Register */ + +#define LTDC_BPCR_AVBP_SHIFT (0) /* Bits 0-10: Accumulated Vertical back porch (scan lines) */ +#define LTDC_BPCR_AVBP_MASK (0x7ff << LTDC_BPCR_AVBP_SHIFT) +# define LTDC_BPCR_AVBP(n) ((uint32_t)(n) << LTDC_BPCR_AVBP_SHIFT) +#define LTDC_BPCR_AHBP_SHIFT (16) /* Bits 16-27: Accumulated Horizontal back porch (pixel clocks) */ +#define LTDC_BPCR_AHBP_MASK (0xfff << LTDC_BPCR_AVBP_SHIFT) +# define LTDC_BPCR_AHBP(n) ((uint32_t)(n) << LTDC_BPCR_AHBP_SHIFT) + +/* LTDC Active Width Configuration Register */ + +#define LTDC_AWCR_AAH_SHIFT (0) /* Bits 0-10: Accumulated Active Height (scan lines) */ +#define LTDC_AWCR_AAH_MASK (0x7ff << LTDC_AWCR_AAH_SHIFT) +# define LTDC_AWCR_AAH(n) ((uint32_t)(n) << LTDC_AWCR_AAH_SHIFT) +#define LTDC_AWCR_AAW_SHIFT (16) /* Bits 16-27: Accumulated Active Width (pixel clocks) */ +#define LTDC_AWCR_AAW_MASK (0xfff << LTDC_AWCR_AAW_SHIFT) +# define LTDC_AWCR_AAW(n) ((uint32_t)(n) << LTDC_AWCR_AAW_SHIFT) + +/* LTDC Total Width Configuration Register */ + +#define LTDC_TWCR_TOTALH_SHIFT (0) /* Bits 0-10: Total Height (scan lines) */ +#define LTDC_TWCR_TOTALH_MASK (0x7ff << LTDC_TWCR_TOTALH_SHIFT) +# define LTDC_TWCR_TOTALH(n) ((uint32_t)(n) << LTDC_TWCR_TOTALH_SHIFT) +#define LTDC_TWCR_TOTALW_SHIFT (16) /* Bits 16-27: Total Width (pixel clocks) */ +#define LTDC_TWCR_TOTALW_MASK (0xfff << LTDC_TWCR_TOTALW_SHIFT) +# define LTDC_TWCR_TOTALW(n) ((uint32_t)(n) << LTDC_TWCR_TOTALW_SHIFT) + +/* LTDC Global Control Register */ + +#define LTDC_GCR_LTDCEN (1 << 0) /* Bit 0: LCD-TFT Controller Enable Bit */ +#define LTDC_GCR_DBW_SHIFT (4) /* Bits 4-6: Dither Blue Width */ +#define LTDC_GCR_DBW_MASK (0x7 << LTDC_GCR_DBW_SHIFT) +# define LTDC_GCR_DBW(n) ((uint32_t)(n) << LTDC_GCR_DBW_SHIFT) +#define LTDC_GCR_DGW_SHIFT (8) /* Bits 8-10: Dither Green Width */ +#define LTDC_GCR_DGW_MASK (0x7 << LTDC_GCR_DGW_SHIFT) +# define LTDC_GCR_DGW(n) ((uint32_t)(n) << LTDC_GCR_DGW_SHIFT) +#define LTDC_GCR_DRW_SHIFT (12) /* Bits 12-14: Dither Red Width */ +#define LTDC_GCR_DRW_MASK (0x7 << LTDC_GCR_DRW_SHIFT) +# define LTDC_GCR_DRW(n) ((uint32_t)(n) << LTDC_GCR_DRW_SHIFT) +#define LTDC_GCR_DEN (1 << 16) /* Bit 16: Dither Enable */ +#define LTDC_GCR_PCPOL (1 << 28) /* Bit 28: Pixel Clock Polarity */ +#define LTDC_GCR_DEPOL (1 << 29) /* Bit 29: Data Enable Polarity */ +#define LTDC_GCR_VSPOL (1 << 30) /* Bit 30: Vertical Sync Polarity */ +#define LTDC_GCR_HSPOL (1 << 31) /* Bit 31: Horizontal Sync Polarity */ + +/* LTDC Shadow Reload Configuration Register */ + +#define LTDC_SRCR_IMR (1 << 0) /* Bit 0: Immediate Reload */ +#define LTDC_SRCR_VBR (1 << 1) /* Bit 1: Vertical Blanking Reload */ + +/* LTDC Background Color Configuration Register */ + +#define LTDC_BCCR_BCBLUE_SHIFT (0) /* Bits 0-7: Background Color Blue Value */ +#define LTDC_BCCR_BCBLUE_MASK (0xFF << LTDC_BCCR_BCBLUE_SHIFT) +# define LTDC_BCCR_BCBLUE(n) ((uint32_t)(n) << LTDC_BCCR_BCBLUE_SHIFT) +#define LTDC_BCCR_BCGREEN_SHIFT (8) /* Bits 8-15: Background Color Green Value */ +#define LTDC_BCCR_BCGREEN_MASK (0xFF << LTDC_BCCR_BCGREEN_SHIFT) +# define LTDC_BCCR_BCGREEN(n) ((uint32_t)(n) << LTDC_BCCR_BCGREEN_SHIFT) +#define LTDC_BCCR_BCRED_SHIFT (16) /* Bits 16-23: Background Color Red Value */ +#define LTDC_BCCR_BCRED_MASK (0xFF << LTDC_BCCR_BCRED_SHIFT) +# define LTDC_BCCR_BCRED(n) ((uint32_t)(n) << LTDC_BCCR_BCRED_SHIFT) + +/* LTDC Interrupt Enable Register */ + +#define LTDC_IER_LIE (1 << 0) /* Bit 0: Line Interrupt Enable */ +#define LTDC_IER_FUIE (1 << 1) /* Bit 1: FIFO Underrun Interrupt Enable */ +#define LTDC_IER_TERRIE (1 << 2) /* Bit 2: Transfer Error Interrupt Enable */ +#define LTDC_IER_RRIE (1 << 3) /* Bit 3: Register Reload Interrupt Enable */ + +/* LTDC Interrupt Status Register */ + +#define LTDC_ISR_LIF (1 << 0) /* Bit 0: Line Interrupt Flag */ +#define LTDC_ISR_FUIF (1 << 1) /* Bit 1: FIFO Underrun Interrupt Flag */ +#define LTDC_IER_TERRIF (1 << 2) /* Bit 2: Transfer Error Interrupt Flag */ +#define LTDC_ISR_RRIF (1 << 3) /* Bit 3: Register Reload Interrupt Flag */ + +/* LTDC Interrupt Clear Register */ + +#define LTDC_ICR_CLIF (1 << 0) /* Bit 0: Clear Line Interrupt Flag */ +#define LTDC_ICR_CFUIF (1 << 1) /* Bit 1: Clear FIFO Underrun Interrupt Flag */ +#define LTDC_ICR_CTERRIF (1 << 2) /* Bit 2: Clear Transfer Error Interrupt Flag */ +#define LTDC_ICR_CRRIF (1 << 3) /* Bit 3: Clear Register Reload Interrupt Flag */ + +/* LTDC Line Interrupt Posittion Configuration Register */ + +#define LTDC_LIPCR_LIPOS_SHIFT (0) /* Bits 0-10: Line Interrupt Position */ +#define LTDC_LIPCR_LIPOS_MASK (0x7FF << LTDC_LIPCR_LIPOS_SHIFT) +# define LTDC_LIPCR_LIPOS(n) ((uint32_t)(n) << LTDC_LIPCR_LIPOS_SHIFT) + +/* LTDC Current Position Status Register */ + +#define LTDC_CPSR_CYPOS_SHIFT (0) /* Bits 0-15: Current Y Position */ +#define LTDC_CPSR_CYPOS_MASK (0xFFFF << LTDC_CPSR_CYPOS_SHIFT) +# define LTDC_CPSR_CYPOS(n) ((uint32_t)(n) << LTDC_CPSR_CYPOS_SHIFT) +#define LTDC_CPSR_CXPOS_SHIFT (16) /* Bits 15-31: Current X Position */ +#define LTDC_CPSR_CXPOS_MASK (0xFFFF << LTDC_CPSR_CXPOS_SHIFT) +# define LTDC_CPSR_CXPOS(n) ((uint32_t)(n) << LTDC_CPSR_CXPOS_SHIFT) + +/* LTDC Current Display Status Register */ + +#define LTDC_CDSR_VDES (1 << 0) /* Bit 0: Vertical Data Enable display Status */ +#define LTDC_CDSR_HDES (1 << 1) /* Bit 1: Horizontal Data Enable display Status */ +#define LTDC_CDSR_VSYNCS (1 << 2) /* Bit 2: Vertical Sync display Status */ +#define LTDC_CDSR_HSYNCS (1 << 3) /* Bit 3: Horizontal Sync display Status */ + +/* LTDC Layer x Control Register */ + +#define LTDC_LxCR_LEN (1 << 0) /* Bit 0: Layer Enable */ +#define LTDC_LxCR_COLKEN (1 << 1) /* Bit 1: Color Keying Enable */ +#define LTDC_LxCR_CLUTEN (1 << 4) /* Bit 4: Color Look-Up Table Enable */ + +/* LTDC Layer x Window Horizontal Position Configuration Register */ + +#define LTDC_LxWHPCR_WHSTPOS_SHIFT (0) /* Bits 0-11: Window Horizontal Start Position */ +#define LTDC_LxWHPCR_WHSTPOS_MASK (0xFFF << LTDC_LxWHPCR_WHSTPOS_SHIFT) +# define LTDC_LxWHPCR_WHSTPOS(n) ((uint32_t)(n) << LTDC_LxWHPCR_WHSTPOS_SHIFT) +#define LTDC_LxWHPCR_WHSPPOS_SHIFT (16) /* Bits 16-27: Window Horizontal Stop Position */ +#define LTDC_LxWHPCR_WHSPPOS_MASK (0xFFF << LTDC_LxWHPCR_WHSPPOS_SHIFT) +# define LTDC_LxWHPCR_WHSPPOS(n) ((uint32_t)(n) << LTDC_LxWHPCR_WHSPPOS_SHIFT) + +/* LTDC Layer x Window Vertical Position Configuration Register */ + +#define LTDC_LxWVPCR_WVSTPOS_SHIFT (0) /* Bits 0-10: Window Vertical Start Position */ +#define LTDC_LxWVPCR_WVSTPOS_MASK (0x7FF << LTDC_LxWVPCR_WVSTPOS_SHIFT) +# define LTDC_LxWVPCR_WVSTPOS(n) ((uint32_t)(n) << LTDC_LxWVPCR_WVSTPOS_SHIFT) +#define LTDC_LxWVPCR_WVSPPOS_SHIFT (16) /* Bits 16-26: Window Vertical Stop Position */ +#define LTDC_LxWVPCR_WVSPPOS_MASK (0x7FF << LTDC_LxWVPCR_WVSPPOS_SHIFT) +# define LTDC_LxWVPCR_WVSPPOS(n) ((uint32_t)(n) << LTDC_LxWVPCR_WVSPPOS_SHIFT) + +/* LTDC Layer x Color Keying Configuration Register */ + +#define LTDC_LxCKCR_CKBLUE_SHIFT (0) /* Bits 0-7: Color Key Blue Value */ +#define LTDC_LxCKCR_CKBLUE_MASK (0xFF << LTDC_LxCKCR_CKBLUE_SHIFT) +# define LTDC_LxCKCR_CKBLUE(n) ((uint32_t)(n) << LTDC_LxCKCR_CKBLUE_SHIFT) +#define LTDC_LxCKCR_CKGREEN_SHIFT (8) /* Bits 8-15: Color Key Green Value */ +#define LTDC_LxCKCR_CKGREEN_MASK (0xFF << LTDC_LxCKCR_CKGREEN_SHIFT) +# define LTDC_LxCKCR_CKGREEN(n) ((uint32_t)(n) << LTDC_LxCKCR_CKGREEN_SHIFT) +#define LTDC_LxCKCR_CKRED_SHIFT (16) /* Bits 16-23: Color Key Red Value */ +#define LTDC_LxCKCR_CKRED_MASK (0xFF << LTDC_LxCKCR_CKRED_SHIFT) +# define LTDC_LxCKCR_CKRED(n) ((uint32_t)(n) << LTDC_LxCKCR_CKRED_SHIFT) + +/* LTDC Layer x Pixel Format Configuration Register */ + +#define LTDC_LxPFCR_PF_SHIFT (0) /* Bits 0-2: Pixel Format */ +#define LTDC_LxPFCR_PF_MASK (0x7 << LTDC_LxPFCR_PF_SHIFT) +# define LTDC_LxPFCR_PF(n) ((uint32_t)(n) << LTDC_LxPFCR_PF_SHIFT) + +#define LTDC_PF_ARGB8888 0 +#define LTDC_PF_RGB888 1 +#define LTDC_PF_RGB565 2 +#define LTDC_PF_ARGB1555 3 +#define LTDC_PF_ARGB4444 4 +#define LTDC_PF_L8 5 /* 8-bit Luninance (CLUT lookup) */ +#define LTDC_PF_AL44 6 /* 4-bit Alpha, 4-bit Luminance */ +#define LTDC_PF_AL88 7 /* 8-bit Alpha, 8-bit Luminance */ + +/* LTDC Layer x Constant Alpha Configuration Register */ + +#define LTDC_LxCACR_CONSTA_SHIFT (0) /* Bits 0-7: Constant Alpha */ +#define LTDC_LxCACR_CONSTA_MASK (0x7 << LTDC_LxCACR_CONSTA_SHIFT) +# define LTDC_LxCACR_CONSTA(n) ((uint32_t)(n) << LTDC_LxCACR_CONSTA_SHIFT) + +/* LTDC Layer x Default Color Configuration Register */ + +#define LTDC_LxDCCR_DCBLUE_SHIFT (0) /* Bits 0-7: Default Color Blue Value */ +#define LTDC_LxDCCR_DCBLUE_MASK (0xFF << LTDC_LxDCCR_DCBLUE_SHIFT) +# define LTDC_LxDCCR_DCBLUE(n) ((uint32_t)(n) << LTDC_LxDCCR_DCBLUE_SHIFT) +#define LTDC_LxDCCR_DCGREEN_SHIFT (8) /* Bits 8-15: Default Color Green Value */ +#define LTDC_LxDCCR_DCGREEN_MASK (0xFF << LTDC_LxDCCR_DCGREEN_SHIFT) +# define LTDC_LxDCCR_DCGREEN(n) ((uint32_t)(n) << LTDC_LxDCCR_DCGREEN_SHIFT) +#define LTDC_LxDCCR_DCRED_SHIFT (16) /* Bits 16-23: Default Color Red Value */ +#define LTDC_LxDCCR_DCRED_MASK (0xFF << LTDC_LxDCCR_DCRED_SHIFT) +# define LTDC_LxDCCR_DCRED(n) ((uint32_t)(n) << LTDC_LxDCCR_DCRED_SHIFT) +#define LTDC_LxDCCR_DCALPHA_SHIFT (24) /* Bits 24-31: Default Color Alpha Value */ +#define LTDC_LxDCCR_DCALPHA_MASK (0xFF << LTDC_LxDCCR_DCALPHA_SHIFT) +# define LTDC_LxDCCR_DCALPHA(n) ((uint32_t)(n) << LTDC_LxDCCR_DCALPHA_SHIFT) + +/* LTDC Layer x Blending Factors Configuration Register */ + +#define LTDC_LxBFCR_BF2_SHIFT (0) /* Bits 0-2: Blending Factor 2 */ +#define LTDC_LxBFCR_BF2_MASK (0x7 << LTDC_LxBFCR_BF2_SHIFT) +# define LTDC_LxBFCR_BF2(n) ((uint32_t)(n) << LTDC_LxBFCR_BF2_SHIFT) +#define LTDC_LxBFCR_BF1_SHIFT (8) /* Bits 8-10: Blending Factor 1 */ +#define LTDC_LxBFCR_BF1_MASK (0x7 << LTDC_LxBFCR_BF1_SHIFT) +# define LTDC_LxBFCR_BF1(n) ((uint32_t)(n) << LTDC_LxBFCR_BF1_SHIFT) + +#define LTDC_BF1_CONST_ALPHA 0x04 /* Constant Alpha */ +#define LTDC_BF1_PIXEL_ALPHA 0x06 /* Pixel Alpha x Constant Alpha */ +#define LTDC_BF2_CONST_ALPHA 0x05 /* Constant Alpha */ +#define LTDC_BF2_PIXEL_ALPHA 0x07 /* Pixel Alpha x Constant Alpha */ + +/* LTDC Layer x Color Frame Buffer Length Configuration Register */ + +#define LTDC_LxCFBLR_CFBLL_SHIFT (0) /* Bits 0-12: Color Frame Buffer Line Length */ +#define LTDC_LxCFBLR_CFBLL_MASK (0x1FFF << LTDC_LxCFBLR_CFBLL_SHIFT) +# define LTDC_LxCFBLR_CFBLL(n) ((uint32_t)(n) << LTDC_LxCFBLR_CFBLL_SHIFT) +#define LTDC_LxCFBLR_CFBP_SHIFT (16) /* Bits 16-28: Color Frame Buffer Pitch */ +#define LTDC_LxCFBLR_CFBP_MASK (0x1FFF << LTDC_LxCFBLR_CFBP_SHIFT) +# define LTDC_LxCFBLR_CFBP(n) ((uint32_t)(n) << LTDC_LxCFBLR_CFBP_SHIFT) + +/* LTDC Layer x Color Frame Buffer Line Number Register */ + +#define LTDC_LxCFBLNR_LN_SHIFT (0) /* Bits 0-10: Color Frame Buffer Line Number */ +#define LTDC_LxCFBLNR_LN_MASK (0x7FF << LTDC_LxCFBLNR_LN_SHIFT) +# define LTDC_LxCFBLNR_LN(n) ((uint32_t)(n) << LTDC_LxCFBLNR_LN_SHIFT) + +/* LTDC Layer x CLUT Write Register */ + +#define LTDC_LxCLUTWR_BLUE_SHIFT (0) /* Bits 0-7: Default Color Blue Value */ +#define LTDC_LxCLUTWR_BLUE_MASK (0xFF << LTDC_LxCLUTWR_BLUE_SHIFT) +# define LTDC_LxCLUTWR_BLUE(n) ((uint32_t)(n) << LTDC_LxCLUTWR_BLUE_SHIFT) +#define LTDC_LxCLUTWR_GREEN_SHIFT (8) /* Bits 8-15: Default Color Green Value */ +#define LTDC_LxCLUTWR_GREEN_MASK (0xFF << LTDC_LxCLUTWR_GREEN_SHIFT) +# define LTDC_LxCLUTWR_GREEN(n) ((uint32_t)(n) << LTDC_LxCLUTWR_GREEN_SHIFT) +#define LTDC_LxCLUTWR_RED_SHIFT (16) /* Bits 16-23: Default Color Red Value */ +#define LTDC_LxCLUTWR_RED_MASK (0xFF << LTDC_LxCLUTWR_RED_SHIFT) +# define LTDC_LxCLUTWR_RED(n) ((uint32_t)(n) << LTDC_LxCLUTWR_RED_SHIFT) +#define LTDC_LxCLUTWR_CLUTADD_SHIFT (24) /* Bits 24-31: CLUT Address */ +#define LTDC_LxCLUTWR_CLUTADD_MASK (0xFF << LTDC_LxCLUTWR_CLUTADD_SHIFT) +# define LTDC_LxCLUTWR_CLUTADD(n) ((uint32_t)(n) << LTDC_LxCLUTWR_CLUTADD_SHIFT) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32F7_CHIP_STM32_LTDC_H */ diff --git a/arch/arm/src/stm32f7/chip/stm32f74xx75xx_memorymap.h b/arch/arm/src/stm32f7/chip/stm32f74xx75xx_memorymap.h old mode 100644 new mode 100755 index 41675c60b37..7c7d25241bc --- a/arch/arm/src/stm32f7/chip/stm32f74xx75xx_memorymap.h +++ b/arch/arm/src/stm32f7/chip/stm32f74xx75xx_memorymap.h @@ -160,7 +160,7 @@ #define STM32_SPI6_BASE 0x40015400 /* 0x40015400-0x400157ff: SPI6 */ #define STM32_SAI1_BASE 0x40015800 /* 0x40015800-0x40015bff: SAI1 */ #define STM32_SAI2_BASE 0x40015c00 /* 0x40015c00-0x40015fff: SAI2 */ -#define STM32_LCDTFT_BASE 0x40016800 /* 0x40016800-0x40016bff: LCD-TFT */ +#define STM32_LTDC_BASE 0x40016800 /* 0x40016800-0x40016bff: LCD-TFT */ /* AHB1 Base Addresses **************************************************************/ diff --git a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_memorymap.h b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_memorymap.h old mode 100644 new mode 100755 index db2ca6d3a95..7af9b5243de --- a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_memorymap.h +++ b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_memorymap.h @@ -162,7 +162,7 @@ #define STM32_SPI6_BASE 0x40015400 /* 0x40015400-0x400157ff: SPI6 */ #define STM32_SAI1_BASE 0x40015800 /* 0x40015800-0x40015bff: SAI1 */ #define STM32_SAI2_BASE 0x40015c00 /* 0x40015c00-0x40015fff: SAI2 */ -#define STM32_LCDTFT_BASE 0x40016800 /* 0x40016800-0x40016bff: LCD-TFT */ +#define STM32_LTDC_BASE 0x40016800 /* 0x40016800-0x40016bff: LCD-TFT */ #define STM32_DSIHOST_BASE 0x40016c00 /* 0x40016c00-0x400173ff: DSI Host */ #define STM32_DFSDM1_BASE 0x40017400 /* 0x40017400-0x400174ff: DFSDM1 */ #define STM32_MDIOS_BASE 0x40017800 /* 0x40017800-0x40017bff: MDIOS */ diff --git a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h index 6c8a7840681..1b9c041319b 100644 --- a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h +++ b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h @@ -729,9 +729,9 @@ # define RCC_DCKCFGR2_SDMMC2SEL_48MHZ (0 << RCC_DCKCFGR2_SDMMC2SEL_SHIFT) /* 48 MHz clock is selected as SDMMC 2 clock */ # define RCC_DCKCFGR2_SDMMC2SEL_SYSCLK (1 << RCC_DCKCFGR2_SDMMC2SEL_SHIFT) /* System clock is selected as SDMMC 2 clock */ #define RCC_DCKCFGR2_DSISEL_SHIFT (30) /* Bit 30: DSI clock source selection */ -#define RCC_DCKCFGR2_DSISELL_MASK (1 << RCC_DCKCFGR2_DSISEL_SHIFT) -# define RCC_DCKCFGR2_DSISEL_48MHZ (0 << RCC_DCKCFGR2_DSISEL_SHIFT) /* 48 MHz clock is selected as DSI clock */ -# define RCC_DCKCFGR2_DSISEL_SYSCLK (1 << RCC_DCKCFGR2_DSISEL_SHIFT) /* System clock is selected as DSI clock */ +#define RCC_DCKCFGR2_DSISEL_MASK (1 << RCC_DCKCFGR2_DSISEL_SHIFT) +# define RCC_DCKCFGR2_DSISEL_PHY (0 << RCC_DCKCFGR2_DSISEL_SHIFT) /* DSI PHY sources DSI clock */ +# define RCC_DCKCFGR2_DSISEL_SYSCLK (1 << RCC_DCKCFGR2_DSISEL_SHIFT) /* System clock is selected as DSI clock */ #endif /* CONFIG_STM32F7_STM32F76XX || CONFIG_STM32F7_STM32F77XX */ #endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F76XX77XX_RCC_H */ diff --git a/arch/arm/src/stm32f7/stm32_dma2d.c b/arch/arm/src/stm32f7/stm32_dma2d.c new file mode 100644 index 00000000000..912ff2a5ff7 --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_dma2d.c @@ -0,0 +1,2303 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_dma2d.c + * + * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * References: + * STM32F429 Technical Reference Manual + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "chip/stm32_ltdc.h" +#include "chip/stm32_dma2d.h" +#include "chip/stm32_dtcm.h" +#include "stm32_dma2d.h" +#include "stm32_ltdc.h" +#include "stm32_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* output, foreground and background layer */ + +#define DMA2D_NLAYERS 3 + +/* DMA2D PFC value definitions */ + +#define DMA2D_PF_ARGB8888 0 +#define DMA2D_PF_RGB888 1 +#define DMA2D_PF_RGB565 2 +#define DMA2D_PF_ARGB1555 3 +#define DMA2D_PF_ARGB14444 4 +#define DMA2D_PF_L8 5 +#define DMA2D_PF_AL44 6 +#define DMA2D_PF_AL88 7 +#define DMA2D_PF_L4 8 +#define DMA2D_PF_A8 9 +#define DMA2D_PF_A4 10 + +/* DMA2D blender control */ + +#define STM32_DMA2D_CR_MODE_BLIT DMA2D_CR_MODE(0) +#define STM32_DMA2D_CR_MODE_BLITPFC DMA2D_CR_MODE(1) +#define STM32_DMA2D_CR_MODE_BLEND DMA2D_CR_MODE(2) +#define STM32_DMA2D_CR_MODE_COLOR DMA2D_CR_MODE(3) +#define STM32_DMA2D_CR_MODE_CLEAR STM32_DMA2D_CR_MODE_COLOR + +/* DMA2D PFC alpha mode */ + +#define STM32_DMA2D_PFCCR_AM_NONE 0 +#define STM32_DMA2D_PFCCR_AM_CONST 1 +#define STM32_DMA2D_PFCCR_AM_PIXEL 10 + +/* Only 8 bit per pixel overal supported */ + +#define DMA2D_PF_BYPP(n) ((n) / 8) + +#define DMA2D_CLUT_SIZE STM32_LTDC_NCLUT - 1 + +/* Layer argb cmap conversion */ + +#define DMA2D_CLUT_ALPHA(n) ((uint32_t)(n) << 24) +#define DMA2D_CLUT_RED(n) ((uint32_t)(n) << 16) +#define DMA2D_CLUT_GREEN(n) ((uint32_t)(n) << 8) +#define DMA2D_CLUT_BLUE(n) ((uint32_t)(n) << 0) + +#define DMA2D_CMAP_ALPHA(n) ((uint32_t)(n) >> 24) +#define DMA2D_CMAP_RED(n) ((uint32_t)(n) >> 16) +#define DMA2D_CMAP_GREEN(n) ((uint32_t)(n) >> 8) +#define DMA2D_CMAP_BLUE(n) ((uint32_t)(n) >> 0) + +/* Define shadow layer for ltdc interface */ + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +# ifdef CONFIG_STM32F7_LTDC_L2 +# define DMA2D_SHADOW_LAYER 2 +# define DMA2D_SHADOW_LAYER_L1 0 +# define DMA2D_SHADOW_LAYER_L2 1 +# else +# define DMA2D_SHADOW_LAYER 1 +# define DMA2D_SHADOW_LAYER_L1 0 +# endif +# define DMA2D_LAYER_NSIZE CONFIG_STM32F7_DMA2D_NLAYERS + DMA2D_SHADOW_LAYER +#else +# define DMA2D_LAYER_NSIZE CONFIG_STM32F7_DMA2D_NLAYERS +# define DMA2D_SHADOW_LAYER 0 +#endif + +/* Debug option */ + +#ifdef CONFIG_STM32F7_DMA2D_REGDEBUG +# define regerr lcderr +# define reginfo lcdinfo +#else +# define regerr(x...) +# define reginfo(x...) +#endif + +/* check clut support */ + +#ifdef CONFIG_STM32F7_DMA2D_L8 +# ifndef CONFIG_FB_CMAP +# error "Enable cmap to support the configured layer formats!" +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* DMA2D General layer information */ + +struct stm32_dma2d_s +{ + struct dma2d_layer_s dma2d; /* public dma2d interface */ + + /* Fixed settings */ + + int lid; /* Layer identifier */ + struct fb_videoinfo_s vinfo; /* Layer videoinfo */ + struct fb_planeinfo_s pinfo; /* Layer planeinfo */ + + /* Blending */ + + uint32_t blendmode; /* the interface blendmode */ + uint8_t alpha; /* the alpha value */ + + /* Coloring */ + +#ifdef CONFIG_STM32F7_DMA2D_L8 + uint32_t *clut; /* Color lookup table */ +#endif + + /* Operation */ + uint8_t fmt; /* the controller pixel format */ + sem_t *lock; /* Ensure mutually exclusive access */ +}; + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE + +/* This structures provides the DMA2D layer for each LTDC layer */ + +struct stm32_ltdc_dma2d_s +{ + struct stm32_dma2d_s dma2ddev; +#ifdef CONFIG_STM32F7_DMA2D_L8 + FAR struct ltdc_layer_s *ltdc; +#endif +}; + +struct stm32_ltdc_layer_s +{ + /* Layer state */ + + struct stm32_ltdc_dma2d_s layer[DMA2D_SHADOW_LAYER]; +}; +#endif + +/* Interrupt handling */ + +struct stm32_interrupt_s +{ + bool wait; /* Informs that the task is waiting for the irq */ + bool handled; /* Informs that an irq was handled */ + int irq; /* irq number */ + sem_t *sem; /* Semaphore for waiting for irq */ +}; + +/* This enumeration foreground and background layer supported by the dma2d + * controller + */ + +enum stm32_layer_e +{ + DMA2D_LAYER_LFORE = 0, /* Foreground Layer */ + DMA2D_LAYER_LBACK, /* Background Layer */ + DMA2D_LAYER_LOUT, /* Output Layer */ +}; + +/* DMA2D memory address register */ + +static const uintptr_t stm32_mar_layer_t[DMA2D_NLAYERS] = +{ + STM32_DMA2D_FGMAR, + STM32_DMA2D_BGMAR, + STM32_DMA2D_OMAR +}; + +/* DMA2D offset register */ + +static const uintptr_t stm32_or_layer_t[DMA2D_NLAYERS] = +{ + STM32_DMA2D_FGOR, + STM32_DMA2D_BGOR, + STM32_DMA2D_OOR +}; + +/* DMA2D pfc control register */ + +static const uintptr_t stm32_pfccr_layer_t[DMA2D_NLAYERS] = +{ + STM32_DMA2D_FGPFCCR, + STM32_DMA2D_BGPFCCR, + STM32_DMA2D_OPFCCR +}; + +/* DMA2D color register */ + +static const uintptr_t stm32_color_layer_t[DMA2D_NLAYERS] = +{ + STM32_DMA2D_FGCOLR, + STM32_DMA2D_BGCOLR, + STM32_DMA2D_OCOLR +}; + +/* DMA2D clut memory address register */ +#if defined(CONFIG_STM32F7_DMA2D_L8) +static const uintptr_t stm32_cmar_layer_t[DMA2D_NLAYERS - 1] = +{ + STM32_DMA2D_FGCMAR, + STM32_DMA2D_BGCMAR +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Private functions */ + +static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap); +static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp); +static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits); +static int stm32_dma2dirq(int irq, void *context, FAR void *arg); +static int stm32_dma2d_waitforirq(void); +static int stm32_dma2d_start(void); +#ifdef CONFIG_STM32F7_DMA2D_L8 +static int stm32_dma2d_loadclut(uintptr_t reg); +#endif +static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer, + fb_coord_t xpos, fb_coord_t ypos); +static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer, + FAR const struct ltdc_area_s *area); + +static int stm32_dma2d_lfreelid(void); +static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void); +static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer); +static void stm32_dma2d_llayerscleanup(void); +static bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer); +static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer, + fb_coord_t xpos, fb_coord_t ypos, + FAR const struct ltdc_area_s *area); +static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer, + int lid, uint8_t fmt); + +static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid, + fb_coord_t xpos, fb_coord_t ypos, + FAR const struct ltdc_area_s *area); +static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer, + int lid, uint32_t color); +static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer, + FAR const struct ltdc_area_s *area); +static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer); +static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, + int lid, uint32_t blendmode); +/* Public functions */ + +static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer, + FAR struct fb_videoinfo_s *vinfo); +static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno, + FAR struct fb_planeinfo_s *pinfo); +static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid); +#ifdef CONFIG_STM32F7_DMA2D_L8 +static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer, + const FAR struct fb_cmap_s *cmap); +static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer, + FAR struct fb_cmap_s *cmap); +#endif +static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha); +static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha); +static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer, + uint32_t mode); +static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer, + uint32_t *mode); +static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea); +static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea); +static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer, + FAR const struct ltdc_area_s *area, uint32_t color); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Remember the layer references for alloc/deallocation */ + +static struct stm32_dma2d_s *g_layers[DMA2D_LAYER_NSIZE]; + +/* The DMA2D semaphore that enforces mutually exclusive access */ + +static sem_t g_lock; + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +/* This structure provides the DMA2D layer for each LTDC layer */ + +static struct stm32_ltdc_layer_s g_ltdc_layer; +#endif + +/* The initalized state of the driver */ + +static bool g_initialized; + +/* Semaphore for interrupt handling */ + +static sem_t g_semirq; + +/* This structure provides irq handling */ + +static struct stm32_interrupt_s g_interrupt = +{ + .wait = false, + .handled = true, + .irq = STM32_IRQ_DMA2D, + .sem = &g_semirq +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dma2d_control + * + * Description: + * Change the DMA2D control register + * + * Parameter: + * setbits - The bits to set + * clrbits - The bits to clear + * + ****************************************************************************/ + +static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits) +{ + uint32_t cr; + + lcdinfo("setbits=%08x, clrbits=%08x\n", setbits, clrbits); + + cr = getreg32(STM32_DMA2D_CR); + cr &= ~clrbits; + cr |= setbits; + putreg32(cr, STM32_DMA2D_CR); +} + +/**************************************************************************** + * Name: stm32_dma2dirq + * + * Description: + * DMA2D interrupt handler + * + ****************************************************************************/ + +static int stm32_dma2dirq(int irq, void *context, FAR void *arg) +{ + uint32_t regval = getreg32(STM32_DMA2D_ISR); + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + reginfo("irq = %d, regval = %08x\n", irq, regval); + + if (regval & DMA2D_ISR_TCIF) + { + /* Transfer complete interrupt */ + + /* Clear the interrupt status register */ + + putreg32(DMA2D_IFCR_CTCIF, STM32_DMA2D_IFCR); + } +#ifdef CONFIG_STM32F7_DMA2D_L8 + else if (regval & DMA2D_ISR_CTCIF) + { + /* CLUT transfer complete interrupt */ + + /* Clear the interrupt status register */ + + putreg32(DMA2D_IFCR_CCTCIF, STM32_DMA2D_IFCR); + } +#endif + else + { + /* Unknown irq, should not occur */ + + return OK; + } + + /* Update the handled flag */ + + priv->handled = true; + + /* Unlock the semaphore if locked */ + + if (priv->wait) + { + + int ret = sem_post(priv->sem); + + if (ret != OK) + { + lcderr("ERROR: sem_post() failed\n"); + return ret; + } + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_dma2d_waitforirq + * + * Description: + * Helper waits until the dma2d irq occurs. That means that an ongoing clut + * loading or dma transfer was completed. + * Note! The caller must use this function within a critical section. + * + * Return: + * On success OK otherwise ERROR + * + ****************************************************************************/ + +static int stm32_dma2d_waitforirq(void) +{ + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + /* Only waits if last enabled interrupt is currently not handled */ + + if (!priv->handled) + { + int ret; + + /* Inform the irq handler the task is able to wait for the irq */ + + priv->wait = true; + + ret = sem_wait(priv->sem); + + /* irq or an error occurs, reset the wait flag */ + + priv->wait = false; + + if (ret != OK) + { + lcderr("ERROR: sem_wait() failed\n"); + return ret; + } + } + + return OK; +} + + +#ifdef CONFIG_STM32F7_DMA2D_L8 +/**************************************************************************** + * Name: stm32_dma2d_loadclut + * + * Description: + * Starts clut loading but doesn't wait until loading is complete! + * + * Parameter: + * pfcreg - PFC control Register + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2d_loadclut(uintptr_t pfcreg) +{ + int ret; + uint32_t regval; + irqstate_t flags; + + flags = enter_critical_section(); + + ret = stm32_dma2d_waitforirq(); + if (ret == OK) + { + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + /* Reset the handled flag */ + + priv->handled = false; + + /* Start clut loading */ + + regval = getreg32(pfcreg); + regval |= DMA2D_xGPFCCR_START; + reginfo("set regval=%08x\n", regval); + putreg32(regval, pfcreg); + reginfo("configured regval=%08x\n", getreg32(pfcreg)); + } + + leave_critical_section(flags); + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_dma2d_start + * + * Description: + * Starts the dma transfer and waits until completed. + * + * Parameter: + * reg - Register to set the start + * startflag - The related flag to start the dma transfer + * irqflag - The interrupt enable flag in the DMA2D_CR register + * + ****************************************************************************/ + +static int stm32_dma2d_start(void) +{ + int ret; + irqstate_t flags; + + flags = enter_critical_section(); + + ret = stm32_dma2d_waitforirq(); + if (ret == OK) + { + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + /* Reset the handled flag */ + + priv->handled = false; + + /* Start clut loading */ + + stm32_dma2d_control(DMA2D_CR_START, 0); + + /* wait until transfer is complete */ + + ret = stm32_dma2d_waitforirq(); + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: stm32_dma2d_memaddress + * + * Description: + * Helper to calculate the layer memory address + * + * Parameter: + * layer - Reference to the common layer state structure + * + * Return: + * memory address + * + ****************************************************************************/ + +static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer, + fb_coord_t xpos, fb_coord_t ypos) +{ + FAR const struct fb_planeinfo_s *pinfo = &layer->pinfo; + uint32_t offset; + + offset = xpos * DMA2D_PF_BYPP(layer->pinfo.bpp) + layer->pinfo.stride * ypos; + + lcdinfo("%p\n", ((uint32_t) pinfo->fbmem) + offset); + return ((uint32_t) pinfo->fbmem) + offset; +} + +/**************************************************************************** + * Name: stm32_dma2d_lineoffset + * + * Description: + * Helper to calculate the layer line offset + * + * Parameter: + * layer - Reference to the common layer state structure + * + * Return: + * line offset + * + ****************************************************************************/ + +static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer, + FAR const struct ltdc_area_s *area) +{ + /* offset at the end of each line in the context to the area layer */ + + lcdinfo("%d\n", layer->vinfo.xres - area->xres); + return layer->vinfo.xres - area->xres; +} + +/**************************************************************************** + * Name: stm32_dma2d_pixelformat + * + * Description: + * Helper to map to dma2d controller pixel format + * + * Parameter: + * layer - Reference to the common layer state structure + * fmt - Reference to the location to store the pixel format + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap) +{ + lcdinfo("fmt=%d, fmtmap=%p\n", fmt, fmtmap); + + /* Map to the controller known format + * + * Not supported by NuttX: + * ARGB8888 + * ARGB1555 + * ARGB4444 + * AL44 + * AL88 + * L8 (non output layer only) + * L4 + * A8 + * A4 + */ + + switch (fmt) + { +#ifdef CONFIG_STM32F7_DMA2D_RGB565 + case FB_FMT_RGB16_565: + *fmtmap = DMA2D_PF_RGB565; + break; +#endif +#ifdef CONFIG_STM32F7_DMA2D_RGB888 + case FB_FMT_RGB24: + *fmtmap = DMA2D_PF_RGB888; + break; +#endif +#ifdef CONFIG_STM32F7_DMA2D_L8 + case FB_FMT_RGB8: + *fmtmap = DMA2D_PF_L8; + break; +#endif + default: + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_dma2d_bpp + * + * Description: + * Helper to get the bits per pixel + * + * Parameter: + * layer - Reference to the common layer state structure + * bpp - Reference to the location to store the pixel format + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp) +{ + lcdinfo("fmt=%d, bpp=%p\n", fmt, bpp); + + switch (fmt) + { +#ifdef CONFIG_STM32F7_DMA2D_RGB565 + case FB_FMT_RGB16_565: + *bpp = 16; + break; +#endif +#ifdef CONFIG_STM32F7_DMA2D_RGB888 + case FB_FMT_RGB24: + *bpp = 24; + break; +#endif +#ifdef CONFIG_STM32F7_DMA2D_L8 + case FB_FMT_RGB8: + *bpp = 8; + break; +#endif + default: + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_dma2d_lfreelid + * + * Description: + * Get a free layer id + * + * Return: + * The number of the free layer + * -1 if no free layer is available + * + ****************************************************************************/ + +static int stm32_dma2d_lfreelid(void) +{ + int n; + + for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++) + { + if (g_layers[n] == NULL) + { + return n; + } + } + + return -1; +} + +/**************************************************************************** + * Name: stm32_dma2d_lalloc + * + * Description: + * Allocate a new layer structure + * + * Return: + * A new allocated layer structure or NULL on error. + * + ****************************************************************************/ + +static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void) +{ + FAR struct stm32_dma2d_s *layer; + +#ifdef HAVE_DTCM_HEAP + /* First try to allocate from the dtcm heap */ + + layer = dtcm_malloc(sizeof(struct stm32_dma2d_s)); + + if (!layer) + { + /* Use default allocator */ + + layer = kmm_malloc(sizeof(struct stm32_dma2d_s)); + } +#else + layer = kmm_malloc(sizeof(struct stm32_dma2d_s)); +#endif + + return layer; +} + +/**************************************************************************** + * Name: stm32_dma2d_lfree + * + * Description: + * Deallocate the dynamic allocated layer structure + * + * Input Parameters: + * A previous allocated layer structure + * + ****************************************************************************/ + +static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer) +{ + if (layer) + { +#ifdef HAVE_DTCM_HEAP + if ( (void*)(DTCM_START) <= layer && layer <= (void*)(DTCM_END) ) + { + dtcm_free(layer); + } + else + { + kmm_free(layer); + } +#else + kmm_free(layer); +#endif + } +} + +/**************************************************************************** + * Name: stm32_dma2d_llayerscleanup + * + * Description: + * Cleanup all allocated layers + * + ****************************************************************************/ + +static void stm32_dma2d_llayerscleanup(void) +{ + int n; + + /* Do not uninitialize the ltdc related dma2d layer */ + + for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++) + { + FAR struct stm32_dma2d_s *priv = g_layers[n]; + if (priv) + { + kmm_free(priv->pinfo.fbmem); + stm32_dma2d_lfree(priv); + g_layers[n] = NULL; + } + } +} + +/**************************************************************************** + * Name: stm32_dma2d_lvalidate + * + * Description: + * Helper to validate if the layer is valid + * + * Return: + * true if validates otherwise false + * + ****************************************************************************/ + +static inline bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer) +{ + return layer && layer->lid < DMA2D_LAYER_NSIZE; +} + +/**************************************************************************** + * Name: stm32_dma2d_lvalidatesize + * + * Description: + * Helper to check if area is outside the whole layer. + * + * Parameter: + * layer - Reference to the layer control structure + * xpos - The x position inside the whole layer + * ypos - The y position inside the whole layer + * area - the area inside the whole layer + * + * Return: + * true if area is inside the whole layer otherwise false + * + ****************************************************************************/ + +static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer, + fb_coord_t xpos, fb_coord_t ypos, + FAR const struct ltdc_area_s *area) +{ + return stm32_dma2d_lvalidate(layer) && + ((layer->vinfo.xres - xpos) * (layer->vinfo.yres - ypos) >= + area->xres * area->yres); +} + +/**************************************************************************** + * Name: stm32_dma2d_linit + * + * Description: + * Initialize the internal layer structure + * + * Parameter: + * + * + ****************************************************************************/ + +static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer, + int lid, uint8_t fmt) +{ + FAR struct dma2d_layer_s *priv = &layer->dma2d; + + lcdinfo("layer=%p, lid=%d, fmt=%02x\n", layer, lid, fmt); + + /* initialize the layer interface */ + + priv->getvideoinfo = stm32_dma2dgetvideoinfo; + priv->getplaneinfo = stm32_dma2dgetplaneinfo; + priv->getlid = stm32_dma2dgetlid; +#ifdef CONFIG_STM32F7_DMA2D_L8 + priv->setclut = stm32_dma2dsetclut; + priv->getclut = stm32_dma2dgetclut; +#endif + priv->setalpha = stm32_dma2dsetalpha; + priv->getalpha = stm32_dma2dgetalpha; + priv->setblendmode = stm32_dma2dsetblendmode; + priv->getblendmode = stm32_dma2dgetblendmode; + priv->blit = stm32_dma2dblit; + priv->blend = stm32_dma2dblend; + priv->fillarea = stm32_dma2dfillarea; + + /* Initialize the layer structure */ + + layer->lid = lid; +#ifdef CONFIG_STM32F7_DMA2D_L8 + layer->clut = 0; +#endif + layer->blendmode = DMA2D_BLEND_NONE; + layer->alpha = 255; + layer->fmt = fmt; + layer->lock = &g_lock; +} + +/**************************************************************************** + * Name: stm32_dma2d_lfifo + * + * Description: + * Set the fifo for the foreground, background and output layer + * Configures the memory address register + * Configures the line offset register + * + * Parameter: + * layer - Reference to the common layer state structure + * + ****************************************************************************/ + +static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid, + fb_coord_t xpos, fb_coord_t ypos, + FAR const struct ltdc_area_s *area) +{ + lcdinfo("layer=%p, lid=%d, xpos=%d, ypos=%d, area=%p\n", + layer, lid, xpos, ypos, area); + + putreg32(stm32_dma2d_memaddress(layer, xpos, ypos), stm32_mar_layer_t[lid]); + putreg32(stm32_dma2d_lineoffset(layer, area), stm32_or_layer_t[lid]); +} + +/**************************************************************************** + * Name: stm32_dma2d_lcolor + * + * Description: + * Set the color for the layer + * + * Parameter: + * layer - Reference to the common layer state structure + * + ****************************************************************************/ + +static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer, + int lid, uint32_t color) +{ + lcdinfo("layer=%p, lid=%d, color=%08x\n", layer, lid, color); + putreg32(color, stm32_color_layer_t[lid]); +} + +/**************************************************************************** + * Name: stm32_dma2d_llnr + * + * Description: + * Set the number of line register + * + * Parameter: + * layer - Reference to the common layer state structure + * area - Reference to the area to copy + * + ****************************************************************************/ + +static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer, + FAR const struct ltdc_area_s *area) +{ + uint32_t nlrreg; + + lcdinfo("pixel per line: %d, number of lines: %d\n", area->xres, area->yres); + + nlrreg = getreg32(STM32_DMA2D_NLR); + nlrreg = (DMA2D_NLR_PL(area->xres) | DMA2D_NLR_NL(area->yres)); + putreg32(nlrreg, STM32_DMA2D_NLR); +} + +/**************************************************************************** + * Name: stm32_dma2d_loutpfc + * + * Description: + * Set the output PFC control register + * + * Parameter: + * layer - Reference to the common layer state structure + * + ****************************************************************************/ + +static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer) +{ + lcdinfo("layer=%p\n", layer); + + /* CLUT format isn't supported by the dma2d controller */ + + if (layer->fmt == DMA2D_PF_L8) + { + /* Destination layer doesn't support CLUT output */ + + lcderr("ERROR: Returning ENOSYS, " + "output to layer with CLUT format not supported.\n"); + return -ENOSYS; + } + + /* Set the mapped pixel format of source layer */ + + putreg32(DMA2D_OPFCCR_CM(layer->fmt), STM32_DMA2D_OPFCCR); + + return OK; +} + +/**************************************************************************** + * Name: stm32_dma2d_lpfc + * + * Description: + * Configure foreground and background layer PFC control register + * + * Parameter: + * layer - Reference to the common layer state structure + * + ****************************************************************************/ + +static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, + int lid, uint32_t blendmode) +{ + uint32_t pfccrreg; + + lcdinfo("layer=%p, lid=%d, blendmode=%08x\n", layer, lid, blendmode); + + /* Set color format */ + + pfccrreg = DMA2D_xGPFCCR_CM(layer->fmt); + +#ifdef CONFIG_STM32F7_DMA2D_L8 + if (layer->fmt == DMA2D_PF_L8) + { + /* Load CLUT automatically */ + + pfccrreg |= DMA2D_xGPFCCR_START; + + /* Set the CLUT color mode */ + +#ifndef CONFIG_FB_TRANSPARENCY + pfccrreg |= DMA2D_xGPFCCR_CCM; +#endif + + /* Set CLUT size */ + + pfccrreg |= DMA2D_xGPFCCR_CS(DMA2D_CLUT_SIZE); + + /* Set the CLUT memory address */ + + putreg32((uint32_t) layer->clut, stm32_cmar_layer_t[lid]); + + /* Start async clut loading */ + + stm32_dma2d_loadclut(stm32_pfccr_layer_t[lid]); + } +#endif + + if (blendmode & DMA2D_BLEND_NONE) + { + /* No blend operation */ + + pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_NONE); + } + else + { + /* Set alpha value */ + + pfccrreg |= DMA2D_xGPFCCR_ALPHA(layer->alpha); + + /* Set alpha mode */ + + if (layer->blendmode & DMA2D_BLEND_ALPHA) + { + /* Blend with constant alpha */ + + pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_CONST); + } + else if (layer->blendmode & DMA2D_BLEND_PIXELALPHA) + { + /* Blend with pixel alpha value */ + + pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_PIXEL); + } + } + + putreg32(pfccrreg, stm32_pfccr_layer_t[lid]); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dma2dgetvideoinfo + * + * Description: + * Get video information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * vinfo - Reference to the video info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer, + FAR struct fb_videoinfo_s *vinfo) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, vinfo=%p\n", layer, vinfo); + + if (stm32_dma2d_lvalidate(priv) && vinfo) + { + sem_wait(priv->lock); + memcpy(vinfo, &priv->vinfo, sizeof(struct fb_videoinfo_s)); + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: stm32_dma2dgetplaneinfo + * + * Description: + * Get plane information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * planeno - Number of the plane + * pinfo - Reference to the plane info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno, + FAR struct fb_planeinfo_s *pinfo) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, planeno=%d, pinfo=%p\n", layer, planeno, pinfo); + + if (stm32_dma2d_lvalidate(priv) && pinfo && planeno == 0) + { + sem_wait(priv->lock); + memcpy(pinfo, &priv->pinfo, sizeof(struct fb_planeinfo_s)); + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_dma2dgetlid + * + * Description: + * Get a specific layer identifier. + * + * Parameter: + * layer - Reference to the layer structure + * lid - Reference to store the layer id + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, lid=%p\n", layer, lid); + + if (stm32_dma2d_lvalidate(priv) && lid) + { + sem_wait(priv->lock); + *lid = priv->lid; + sem_post(priv->lock); + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +#ifdef CONFIG_STM32F7_DMA2D_L8 +/**************************************************************************** + * Name: stm32_dma2dsetclut + * + * Description: + * Configure layer clut (color lookup table). + * Non clut is defined during initializing. + * + * Parameter: + * layer - Reference to the layer structure + * cmap - color lookup table with up the 256 entries + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer, + const FAR struct fb_cmap_s *cmap) +{ + int ret; + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, cmap=%p\n", layer, cmap); + + if (stm32_dma2d_lvalidate(priv) && cmap) + { + sem_wait(priv->lock); + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE + if (priv->lid < DMA2D_SHADOW_LAYER) + { + /* Update the shared color lookup table. + * + * Background: + * + * We share the same memory region of the clut table with the LTDC + * driver. (see stm32_dma2dinitltdc). This is important because any + * changes to the framebuffer and color lookup table by the ltdc + * related dma2d layer should also effects to the ltdc visibility, + * except operation settings, alpha and blendmode. + * + * But we can not only update the clut memory region. The LTDC driver + * also must update they own LTDC clut register to make the changes + * visible. Using the LTDC interface to update the clut table will + * also update the clut table of the related dma2d layer. + */ + + FAR struct ltdc_layer_s *ltdc = + g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].ltdc; + + ret = ltdc->setclut(ltdc, cmap); + + sem_post(priv->lock); + + return ret; + } +#endif + + if (priv->fmt != DMA2D_PF_L8) + { + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->vinfo.fmt); + ret = -EINVAL; + } + else if (cmap->first >= STM32_DMA2D_NCLUT) + { + lcderr("ERROR: only %d color table entries supported\n", + STM32_DMA2D_NCLUT); + ret = -EINVAL; + } + else + { + uint32_t *clut; + int n; + + clut = priv->clut; + + for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++) + { + /* Update the layer clut entry */ + +#ifndef CONFIG_FB_TRANSPARENCY + uint8_t *clut888 = (uint8_t *)clut; + uint16_t offset = 3 * n; + + clut888[offset] = cmap->blue[n]; + clut888[offset + 1] = cmap->green[n]; + clut888[offset + 2] = cmap->red[n]; + + reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, + clut888[offset], clut888[offset + 1], + clut888[offset + 2]); +#else + clut[n] = (uint32_t)DMA2D_CLUT_RED(cmap->transp[n]) | + (uint32_t)DMA2D_CLUT_GREEN(cmap->red[n]) | + (uint32_t)DMA2D_CLUT_GREEN(cmap->green[n]) | + (uint32_t)DMA2D_CLUT_BLUE(cmap->blue[n]); + + reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, + DMA2D_CLUT_ALPHA(cmap->alpha[n]), + DMA2D_CLUT_RED(cmap->red[n]), + DMA2D_CLUT_GREEN(cmap->green[n]), + DMA2D_CLUT_BLUE(cmap->blue[n])); +#endif + } + + + ret = OK; + } + + sem_post(priv->lock); + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_dma2dgetclut + * + * Description: + * Get configured layer clut (color lookup table). + * + * Parameter: + * layer - Reference to the layer structure + * cmap - Reference to valid color lookup table accept up the 256 color + * entries + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer, + FAR struct fb_cmap_s *cmap) +{ + int ret; + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, cmap=%p\n", layer, cmap); + + if (stm32_dma2d_lvalidate(priv) && cmap) + { + sem_wait(priv->lock); + + if (priv->fmt != DMA2D_PF_L8) + { + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->vinfo.fmt); + ret = -EINVAL; + } + else if (cmap->first >= STM32_DMA2D_NCLUT) + { + lcderr("ERROR: only %d color table entries supported\n", + STM32_DMA2D_NCLUT); + ret = -EINVAL; + } + else + { + /* Copy from the layer clut */ + + uint32_t *clut; + int n; + + clut = priv->clut; + + for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++) + { +#ifndef CONFIG_FB_TRANSPARENCY + uint8_t *clut888 = (uint8_t *)clut; + uint16_t offset = 3 * n; + + cmap->blue[n] = clut888[offset]; + cmap->green[n] = clut888[offset + 1]; + cmap->red[n] = clut888[offset + 2]; + + reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, + clut888[offset], clut888[offset + 1], + clut888[offset + 2]); +#else + cmap->transp[n] = (uint8_t)DMA2D_CMAP_ALPHA(clut[n]); + cmap->red[n] = (uint8_t)DMA2D_CMAP_RED(clut[n]); + cmap->green[n] = (uint8_t)DMA2D_CMAP_GREEN(clut[n]); + cmap->blue[n] = (uint8_t)DMA2D_CMAP_BLUE(clut[n]); + + reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, + DMA2D_CMAP_ALPHA(clut[n]), DMA2D_CMAP_RED(clut[n]), + DMA2D_CMAP_GREEN(clut[n]), DMA2D_CMAP_BLUE(clut[n])); +#endif + } + + ret = OK; + } + + sem_post(priv->lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} +#endif + +/**************************************************************************** + * Name: stm32_dma2dsetalpha + * + * Description: + * Configure layer alpha value factor into blend operation. + * During the layer blend operation the source alpha value is multiplied + * with this alpha value. If the source color format doesn't support alpha + * channel (e.g. non ARGB8888) this alpha value will be used as constant + * alpha value for blend operation. + * Default value during initializing: 0xff + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, alpha=%02x\n", layer, alpha); + + if (stm32_dma2d_lvalidate(priv)) + { + sem_wait(priv->lock); + priv->alpha = alpha; + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_dma2dgetalpha + * + * Description: + * Get configured layer alpha value factor for blend operation. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Reference to store the alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, alpha=%p\n", layer, alpha); + + if (stm32_dma2d_lvalidate(priv)) + { + sem_wait(priv->lock); + *alpha = priv->alpha; + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_dma2dsetblendmode + * + * Description: + * Configure blend mode of the layer. + * Default mode during initializing: DMA2D_BLEND_NONE + * Blendmode is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Blend mode (see DMA2D_BLEND_*) + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure information: + * DMA2D_BLEND_NONE: + * Informs the driver to disable all blend operation for the given layer. + * That means the layer is opaque. + * + * DMA2D_BLEND_ALPHA: + * Informs the driver to enable alpha blending for the given layer. + * + * DMA2D_BLEND_PIXELALPHA: + * Informs the driver to use the pixel alpha value of the layer instead + * the constant alpha value. This is only useful for ARGB8888 + * color format. + * + ****************************************************************************/ + +static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer, + uint32_t mode) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, mode=%08x\n", layer, mode); + + if (stm32_dma2d_lvalidate(priv)) + { + sem_wait(priv->lock); + priv->blendmode = mode; + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getblendmode + * + * Description: + * Get configured blend mode of the layer. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Reference to store the blend mode + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer, + uint32_t *mode) +{ + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, mode=%p\n", layer, mode); + + if (stm32_dma2d_lvalidate(priv) && mode) + { + sem_wait(priv->lock); + *mode = priv->blendmode; + sem_post(priv->lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_dma2dblit + * + * Description: + * Copy selected area from a source layer to selected position of the + * destination layer. + * + * Parameter: + * dest - Valid reference to the destination layer + * destxpos - Valid selected x position of the destination layer + * destypos - Valid selected y position of the destination layer + * src - Valid reference to the source layer + * srcarea - Valid reference to the selected area of the source layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * -ECANCELED - Operation cancelled, something goes wrong. + * + ****************************************************************************/ + +static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea) +{ + uint32_t mode; + int ret; + FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest; + FAR struct stm32_dma2d_s * srclayer = (FAR struct stm32_dma2d_s *)src; + + lcdinfo("dest=%p, destxpos=%d, destypos=%d, src=%p, srcarea=%p\n", + dest, destxpos, destypos, src, srcarea); + + if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, srcarea) && + stm32_dma2d_lvalidatesize(srclayer, srcarea->xpos, + srcarea->ypos, srcarea)) + { + sem_wait(destlayer->lock); + + /* Set output pfc */ + + ret = stm32_dma2d_loutpfc(destlayer); + + if (ret == OK) + { + /* Set foreground pfc */ + + stm32_dma2d_lpfc(srclayer, DMA2D_LAYER_LFORE, DMA2D_BLEND_NONE); + + /* Set foreground fifo */ + + stm32_dma2d_lfifo(srclayer, DMA2D_LAYER_LFORE, + srcarea->xpos, srcarea->ypos, srcarea); + + /* Set output fifo */ + + stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT, + destxpos, destypos, srcarea); + + /* Set number of lines and pixel per line */ + + stm32_dma2d_llnr(destlayer, srcarea); + + /* Set dma2d mode for blit operation */ + + if (destlayer->fmt == srclayer->fmt) + { + /* Blit without pfc */ + + mode = STM32_DMA2D_CR_MODE_BLIT; + } + else + { + /* Blit with pfc */ + + mode = STM32_DMA2D_CR_MODE_BLITPFC; + } + + stm32_dma2d_control(mode, STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); + + if (ret != OK) + { + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); + } + } + + sem_post(destlayer->lock); + } + else + { + ret = -EINVAL; + lcderr("ERROR: Returning EINVAL\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_dma2dblend + * + * Description: + * Blends the selected area from a background layer with selected position + * of the foreground layer. Copies the result to the selected position of + * the destination layer. Note! The content of the foreground and background + * layer keeps unchanged as long destination layer is unequal to the + * foreground and background layer. + * + * Parameter: + * dest - Reference to the destination layer + * fore - Reference to the foreground layer + * forexpos - Selected x target position of the foreground layer + * foreypos - Selected y target position of the foreground layer + * back - Reference to the background layer + * backarea - Reference to the selected area of the background layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * -ECANCELED - Operation cancelled, something goes wrong. + * + ****************************************************************************/ + +static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea) +{ + int ret; + FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest; + FAR struct stm32_dma2d_s * forelayer = (FAR struct stm32_dma2d_s *)fore; + FAR struct stm32_dma2d_s * backlayer = (FAR struct stm32_dma2d_s *)back; + + lcdinfo("dest=%p, destxpos=%d, destypos=%d, " + "fore=%p, forexpos=%d, foreypos=%d, " + "back=%p, backarea=%p\n", + dest, destxpos, destypos, fore, forexpos, foreypos, back, backarea); + + if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, backarea) && + stm32_dma2d_lvalidatesize(forelayer, forexpos, foreypos, backarea) && + stm32_dma2d_lvalidatesize(backlayer, backarea->xpos, + backarea->ypos, backarea)) + { + + sem_wait(destlayer->lock); + + /* Set output pfc */ + + ret = stm32_dma2d_loutpfc(destlayer); + + if (ret == OK) + { + /* Set background pfc */ + + stm32_dma2d_lpfc(backlayer, DMA2D_LAYER_LBACK, backlayer->blendmode); + + /* Set foreground pfc */ + + stm32_dma2d_lpfc(forelayer, DMA2D_LAYER_LFORE, forelayer->blendmode); + + /* Set background fifo */ + + stm32_dma2d_lfifo(backlayer, DMA2D_LAYER_LBACK, + backarea->xpos, backarea->ypos, backarea); + + /* Set foreground fifo */ + + stm32_dma2d_lfifo(forelayer, DMA2D_LAYER_LFORE, + forexpos, foreypos, backarea); + + /* Set output fifo */ + + stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT, + destxpos, destypos, backarea); + + /* Set number of lines and pixel per line */ + + stm32_dma2d_llnr(destlayer, backarea); + + /* Set watermark */ + + /* Enable DMA2D blender */ + + stm32_dma2d_control(STM32_DMA2D_CR_MODE_BLEND, + STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); + + if (ret != OK) + { + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); + } + } + + sem_post(destlayer->lock); + } + else + { + ret = -EINVAL; + lcderr("ERROR: Returning EINVAL\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_dma2dfillarea + * + * Description: + * Fill the selected area of the whole layer with a specific color. + * + * Parameter: + * layer - Reference to the layer structure + * area - Reference to the valid area structure select the area + * color - Color to fill the selected area. Color must be formatted + * according to the layer pixel format. + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * area outside the visible area of the layer. + * -ECANCELED - Operation cancelled, something goes wrong. + * + ****************************************************************************/ + +static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer, + FAR const struct ltdc_area_s *area, + uint32_t color) +{ + int ret; + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + lcdinfo("layer=%p, area=%p, color=%08x\n", layer, area, color); + + if (stm32_dma2d_lvalidatesize(priv, area->xpos, area->ypos, area)) + { + + sem_wait(priv->lock); + + /* Set output pfc */ + + ret = stm32_dma2d_loutpfc(priv); + + if (ret == OK) + { + /* Set output fifo */ + + stm32_dma2d_lfifo(priv, DMA2D_LAYER_LOUT, + area->xpos, area->ypos, area); + + /* Set the output color register */ + + stm32_dma2d_lcolor(priv, DMA2D_LAYER_LOUT, color); + + /* Set number of lines and pixel per line */ + + stm32_dma2d_llnr(priv, area); + + /* Set register to memory transfer */ + + stm32_dma2d_control(STM32_DMA2D_CR_MODE_COLOR, + STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); + + if (ret != OK) + { + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); + } + } + + sem_post(priv->lock); + } + else + { + ret = -EINVAL; + lcderr("ERROR: Returning EINVAL\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: up_dma2dgetlayer + * + * Description: + * Get a dma2d layer structure by the layer identifier + * + * Parameter: + * lid - Layer identifier + * + * Return: + * Reference to the dma2d layer control structure on success or Null if no + * related exist. + * + ****************************************************************************/ + +FAR struct dma2d_layer_s * up_dma2dgetlayer(int lid) +{ + if (lid < DMA2D_LAYER_NSIZE) + { + FAR struct stm32_dma2d_s *priv; + sem_wait(&g_lock); + priv = g_layers[lid]; + sem_post(&g_lock); + + return &priv->dma2d; + } + + lcderr("ERROR: EINVAL, Unknown layer identifier\n"); + errno = EINVAL; + return NULL; +} + +/**************************************************************************** + * Name: up_dma2dcreatelayer + * + * Description: + * Create a new dma2d layer object to interact with the dma2d controller + * + * Parameter: + * width - Layer width + * height - Layer height + * fmt - Pixel format of the layer + * + * Return: + * On success - A valid dma2d layer reference + * On error - NULL and errno is set to + * -EINVAL if one of the parameter is invalid + * -ENOMEM if no memory available or exceeds + * CONFIG_STM32F7_DMA2D_NLAYERS + * + ****************************************************************************/ + +FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width, + fb_coord_t height, + uint8_t fmt) +{ + int ret; + int lid; + uint8_t fmtmap; + uint8_t bpp = 0; + FAR struct stm32_dma2d_s *layer = NULL; + + lcdinfo("width=%d, height=%d, fmt=%02x \n", width, height, fmt); + + /* Validate if pixel format supported */ + + ret = stm32_dma2d_pixelformat(fmt, &fmtmap); + + if (ret != OK) + { + errno = -ret; + return NULL; + } + + ret = stm32_dma2d_bpp(fmt, &bpp); + + sem_wait(&g_lock); + + /* Get a free layer identifier */ + + lid = stm32_dma2d_lfreelid(); + + if (lid >= 0) + { + layer = stm32_dma2d_lalloc(); + + if (layer) + { + uint32_t fblen; + void *fbmem; + fb_coord_t stride; + + /* Stride calculation for the supported formats */ + + stride = width * bpp / 8; + + /* Calculate buffer size */ + + fblen = stride * height; + + /* Allocate 32-bit aligned memory for the layer buffer. As reported in + * mm_memalign 8-byte alignment is guaranteed by normal malloc calls. + * We have also ensure memory is allocated from the SRAM1/2/3 block. + */ + + fbmem = kmm_zalloc(fblen); /* STM32F7: Should use DTCM ? */ + + if (fbmem) + { + FAR struct fb_videoinfo_s *vinfo = &layer->vinfo; + FAR struct fb_planeinfo_s *pinfo = &layer->pinfo; + + /* Initialize dma2d structure */ + + stm32_dma2d_linit(layer, lid, fmtmap); + + /* Initialize the videoinfo structure */ + + vinfo->fmt = fmt; + vinfo->xres = width; + vinfo->yres = height; + vinfo->nplanes = 1; + + /* Initialize the planeinfo structure */ + + pinfo->fbmem = fbmem; + pinfo->fblen = fblen; + pinfo->stride = stride; + pinfo->display = 0; + pinfo->bpp = bpp; + + /* Bind the layer to the identifier */ + + g_layers[lid] = layer; + } + else + { + /* free the layer struture */ + + kmm_free(layer); + layer = NULL; + lcderr("ERROR: ENOMEM, Unable to allocate layer buffer\n"); + errno = ENOMEM; + } + } + else + { + lcderr("ERROR: ENOMEM, unable to allocate layer structure\n"); + errno = ENOMEM; + } + } + else + { + lcderr("ERROR: EINVAL, no free layer available\n"); + errno = EINVAL; + } + + sem_post(&g_lock); + return (FAR struct dma2d_layer_s *)layer; +} + +/**************************************************************************** + * Name: up_dma2dremovelayer + * + * Description: + * Remove and deallocate the dma2d layer + * + * Parameter: + * layer - Reference to the layer to remove + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer) +{ + int ret = -EINVAL; + FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + + /* Check if the layer is valid and unlike a ltdc related layer */ + + if (stm32_dma2d_lvalidate(priv) && priv->lid >= DMA2D_SHADOW_LAYER) + { + sem_wait(priv->lock); + + /* Check also if the layer id is valid to the layer reference */ + + if (priv == g_layers[priv->lid]) + { + int lid = priv->lid; + + kmm_free(priv->pinfo.fbmem); + stm32_dma2d_lfree(priv); + + g_layers[lid] = NULL; + ret = OK; + } + + sem_post(priv->lock); + } + + return ret; +} + +/**************************************************************************** + * Name: up_dma2dinitialize + * + * Description: + * Initialize the dma2d controller + * + * Return: + * OK - On success + * An error if initializing failed. + * + ****************************************************************************/ + +int up_dma2dinitialize(void) +{ + lcdinfo("Initialize DMA2D driver\n"); + + if (g_initialized == false) + { + /* Abort current dma2d data transfer */ + + up_dma2duninitialize(); + + /* Enable dma2d is done in rcc_enableahb1, see + * arch/arm/src/stm32/stm32f40xxx_rcc.c + */ + + /* Initialize the DMA2D semaphore that enforces mutually exclusive access + * to the driver + */ + + sem_init(&g_lock, 0, 1); + + /* Initialize the semaphore for interrupt handling. This waitsem + * semaphore is used for signaling and, hence, should not have + * priority inheritance enabled. + */ + + sem_init(g_interrupt.sem, 0, 0); + sem_setprotocol(g_interrupt.sem, SEM_PRIO_NONE); + +#ifdef CONFIG_STM32F7_DMA2D_L8 + /* Enable dma2d transfer and clut loading interrupts only */ + + stm32_dma2d_control(DMA2D_CR_TCIE | DMA2D_CR_CTCIE, DMA2D_CR_TEIE | + DMA2D_CR_TWIE | DMA2D_CR_CAEIE | DMA2D_CR_CEIE); +#else + /* Enable dma transfer interrupt only */ + + stm32_dma2d_control(DMA2D_CR_TCIE, DMA2D_CR_TEIE | DMA2D_CR_TWIE | + DMA2D_CR_CAEIE | DMA2D_CR_CTCIE | DMA2D_CR_CEIE); +#endif + + /* Attach DMA2D interrupt vector */ + + (void)irq_attach(g_interrupt.irq, stm32_dma2dirq, NULL); + + /* Enable the IRQ at the NVIC */ + + up_enable_irq(g_interrupt.irq); + + /* Initialize the dma2d layer for ltdc binding */ + +#ifdef DMA2D_SHADOW_LAYER_L1 + g_layers[DMA2D_SHADOW_LAYER_L1] = + &g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].dma2ddev; +#endif +#ifdef DMA2D_SHADOW_LAYER_L2 + g_layers[DMA2D_SHADOW_LAYER_L2] = + &g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L2].dma2ddev; +#endif + /* Set initialized state */ + + g_initialized = true; + } + + return OK; +} + +/**************************************************************************** + * Name: up_dma2duninitialize + * + * Description: + * Uninitialize the dma2d controller + * + ****************************************************************************/ + +void up_dma2duninitialize(void) +{ + /* Disable DMA2D interrupts */ + + up_disable_irq(g_interrupt.irq); + irq_detach(g_interrupt.irq); + + /* Cleanup all layers */ + + stm32_dma2d_llayerscleanup(); + + /* Abort current dma2d transfer */ + + stm32_dma2d_control(DMA2D_CR_ABORT, 0); + + /* Set initialized state */ + + g_initialized = false; +} + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +/**************************************************************************** + * Name: stm32_dma2dinitltdc + * + * Description: + * Get a reference to the dma2d layer coupled with the ltdc layer. + * It not intends to use this by user space applications. + * It resolves the following requirements: + * 1. Share the color lookup table + * 2. Share the planeinfo information + * 3. Share the videoinfo information + * + * Parameter: + * layer - a valid reference to the low level ltdc layer structure + * clut - a pointer to a valid memory region to hold 256 clut colors + * + * Return: + * On success - A valid dma2d layer reference + * On error - NULL and errno is set to + * -EINVAL if one of the parameter is invalid + * + ****************************************************************************/ + +FAR struct dma2d_layer_s * stm32_dma2dinitltdc(FAR struct stm32_ltdc_s *layer) +{ + int ret; + uint8_t fmt = 0; + FAR struct stm32_ltdc_dma2d_s *priv; + + lcdinfo("layer=%p\n", layer); + DEBUGASSERT(layer && layer->lid >= 0 && layer->lid < DMA2D_SHADOW_LAYER); + + ret = stm32_dma2d_pixelformat(layer->vinfo.fmt, &fmt); + + if (ret != OK) + { + lcderr("ERROR: Returning -EINVAL, unsupported pixel format: %d\n", + layer->vinfo.fmt); + errno = -EINVAL; + return NULL; + } + + priv = &g_ltdc_layer.layer[layer->lid]; + + stm32_dma2d_linit(&priv->dma2ddev, layer->lid, fmt); + + memcpy(&priv->dma2ddev.vinfo, &layer->vinfo, sizeof(struct fb_videoinfo_s)); + memcpy(&priv->dma2ddev.pinfo, &layer->pinfo, sizeof(struct fb_planeinfo_s)); + +#ifdef CONFIG_STM32F7_DMA2D_L8 + /* Verifies that the ltdc layer has a clut. This ensures that DMA2D driver can + * support clut format but the LTDC driver does not and vice versa. + */ + + if (layer->vinfo.fmt == FB_FMT_RGB8) + { + priv->dma2ddev.clut = layer->clut; + priv->ltdc = stm32_ltdcgetlayer(layer->lid); + DEBUGASSERT(priv->ltdc != NULL); + } +#endif + + return &priv->dma2ddev.dma2d; +} +#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ diff --git a/arch/arm/src/stm32f7/stm32_dma2d.h b/arch/arm/src/stm32f7/stm32_dma2d.h new file mode 100644 index 00000000000..e7bfa12fccc --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_dma2d.h @@ -0,0 +1,92 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_dma2d.h + * + * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32F7_STM32_DMA2D_H +#define __ARCH_ARM_SRC_STM32F7_STM32_DMA2D_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_STM32F7_DMA2D +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +# ifdef CONFIG_STM32F7_LTDC_INTERFACE +/**************************************************************************** + * Name: stm32_dma2dinitltdc + * + * Description: + * Get a reference to the dma2d layer coupled with the ltdc layer. + * It not intends to use this function by user space applications. + * It resolves the following requirements: + * 1. Share the color lookup table + * 2. Share the planeinfo information + * 3. Share the videoinfo information + * + * Parameter: + * layer - a valid reference to the low level ltdc layer structure + * + * Return: + * On success - A valid dma2d layer reference + * On error - NULL and errno is set to + * -EINVAL if one of the parameter is invalid + * + ****************************************************************************/ + +struct stm32_ltdc_s; // fwd decl + +FAR struct dma2d_layer_s *stm32_dma2dinitltdc(FAR struct stm32_ltdc_s *layer); +# endif /* CONFIG_STM32F7_LTDC_INTERFACE */ + +#endif /* CONFIG_STM32F7_DMA2D */ +#endif /* __ARCH_ARM_SRC_STM32F7_STM32_DMA2D_H */ diff --git a/arch/arm/src/stm32f7/stm32_ltdc.c b/arch/arm/src/stm32f7/stm32_ltdc.c new file mode 100644 index 00000000000..4b3121bb6b4 --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_ltdc.c @@ -0,0 +1,3635 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_ltdc.c + * + * Copyright (C) 2013-2015 Ken Pettit. All rights reserved. + * Authors: Ken Pettit + * Marco Krahl + * + * References: + * STM32F429 Technical Reference Manual and Data Sheet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +// #include "stm32.h" +#include "chip/stm32_ltdc.h" +#include "stm32_ltdc.h" +#include "stm32_dma2d.h" +#include "stm32_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register definition ******************************************************/ + +#ifndef BOARD_LTDC_WIDTH +# error BOARD_LTDC_WIDTH must be defined in the board.h header file +#endif + +#ifndef BOARD_LTDC_HEIGHT +# error BOARD_LTDC_HEIGHT must be defined in the board.h header file +#endif + +#define STM32_LTDC_HEIGHT BOARD_LTDC_HEIGHT +#define STM32_LTDC_WIDTH BOARD_LTDC_WIDTH + +/* Configure LTDC register */ + +/* LTDC_LxWHPCR register */ + +#define STM32_LTDC_LxWHPCR_WHSTPOS (BOARD_LTDC_HSYNC + BOARD_LTDC_HBP - 1) +#define STM32_LTDC_LxWHPCR_WHSPPOS (BOARD_LTDC_HSYNC + BOARD_LTDC_HBP + \ + STM32_LTDC_WIDTH - 1) + +/* LTDC_LxWVPCR register */ + +#define STM32_LTDC_LxWVPCR_WVSTPOS (BOARD_LTDC_VSYNC + BOARD_LTDC_VBP - 1) +#define STM32_LTDC_LxWVPCR_WVSPPOS (BOARD_LTDC_VSYNC + BOARD_LTDC_VBP + \ + STM32_LTDC_HEIGHT - 1) + +/* LTDC_SSCR register */ + +#define STM32_LTDC_SSCR_VSH LTDC_SSCR_VSH(BOARD_LTDC_VSYNC - 1) +#define STM32_LTDC_SSCR_HSW LTDC_SSCR_HSW(BOARD_LTDC_HSYNC - 1) + +/* LTDC_BPCR register */ + +#define STM32_LTDC_BPCR_AVBP LTDC_BPCR_AVBP(STM32_LTDC_LxWVPCR_WVSTPOS) +#define STM32_LTDC_BPCR_AHBP LTDC_BPCR_AHBP(STM32_LTDC_LxWHPCR_WHSTPOS) + +/* LTDC_AWCR register */ + +#define STM32_LTDC_AWCR_AAH LTDC_AWCR_AAH(STM32_LTDC_LxWVPCR_WVSPPOS) +#define STM32_LTDC_AWCR_AAW LTDC_AWCR_AAW(STM32_LTDC_LxWHPCR_WHSPPOS) + +/* LTDC_TWCR register */ + +#define STM32_LTDC_TWCR_TOTALH LTDC_TWCR_TOTALH(BOARD_LTDC_VSYNC + \ + BOARD_LTDC_VBP + \ + STM32_LTDC_HEIGHT + BOARD_LTDC_VFP - 1) +#define STM32_LTDC_TWCR_TOTALW LTDC_TWCR_TOTALW(BOARD_LTDC_HSYNC + \ + BOARD_LTDC_HBP + \ + STM32_LTDC_WIDTH + BOARD_LTDC_HFP - 1) + +/* Global GCR register */ + +/* Synchronisation and Polarity */ + +#define STM32_LTDC_GCR_PCPOL BOARD_LTDC_GCR_PCPOL +#define STM32_LTDC_GCR_DEPOL BOARD_LTDC_GCR_DEPOL +#define STM32_LTDC_GCR_VSPOL BOARD_LTDC_GCR_VSPOL +#define STM32_LTDC_GCR_HSPOL BOARD_LTDC_GCR_HSPOL + +/* Dither */ + +#define STM32_LTDC_GCR_DEN BOARD_LTDC_GCR_DEN +#define STM32_LTDC_GCR_DBW LTDC_GCR_GBW(BOARD_LTDC_GCR_DBW) +#define STM32_LTDC_GCR_DGW LTDC_GCR_DGW(BOARD_LTDC_GCR_DGW) +#define STN32_LTDC_GCR_DRW LTDC_GCR_DBW(BOARD_LTDC_GCR_DRW) + +/* LIPCR register */ + +#define STM32_LTDC_LIPCR_LIPOS LTDC_LIPCR_LIPOS(STM32_LTDC_TWCR_TOTALW) + +/* Configuration ************************************************************/ + +#ifndef CONFIG_STM32F7_LTDC_DEFBACKLIGHT +# define CONFIG_STM32F7_LTDC_DEFBACKLIGHT 0xf0 +#endif +#define STM32_LTDC_BACKLIGHT_OFF 0x00 + +/* Color/video formats */ + +/* Layer 1 format */ + +#if defined(CONFIG_STM32F7_LTDC_L1_L8) +# define STM32_LTDC_L1_BPP 8 +# define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB8 +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_L8) +# define STM32_LTDC_L1CMAP +#elif defined(CONFIG_STM32F7_LTDC_L1_AL44) +# define STM32_LTDC_L1_BPP 8 +# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL44) +#elif defined(CONFIG_STM32F7_LTDC_L1_AL88) +# define STM32_LTDC_L1_BPP 16 +# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL88) +#elif defined(CONFIG_STM32F7_LTDC_L1_ARGB4444) +# define STM32_LTDC_L1_BPP 16 +# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB4444) +#elif defined(CONFIG_STM32F7_LTDC_L1_RGB565) +# define STM32_LTDC_L1_BPP 16 +# define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB16_565 +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB565) +#elif defined(CONFIG_STM32F7_LTDC_L1_ARGB1555) +# define STM32_LTDC_L1_BPP 16 +# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB1555) +#elif defined(CONFIG_STM32F7_LTDC_L1_RGB888) +# define STM32_LTDC_L1_BPP 24 +# define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB24 +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB888) +#elif defined(CONFIG_STM32F7_LTDC_L1_ARGB8888) +# define STM32_LTDC_L1_BPP 32 +# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB8888) +#endif + +/* Layer 2 format */ + +#if defined(CONFIG_STM32F7_LTDC_L2_L8) +# define STM32_LTDC_L2_BPP 8 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB8 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_L8) +# define STM32_LTDC_L2CMAP +#elif defined(CONFIG_STM32F7_LTDC_L2_AL44) +# define STM32_LTDC_L2_BPP 8 +# define STM32_LTDC_L2_COLOR_FMT ??? +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL44) +#elif defined(CONFIG_STM32F7_LTDC_L2_AL88) +# define STM32_LTDC_L2_BPP 16 +# define STM32_LTDC_L2_COLOR_FMT ??? +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL88) +#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB4444) +# define STM32_LTDC_L2_BPP 16 +# define STM32_LTDC_L2_COLOR_FMT ??? +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB4444) +#elif defined(CONFIG_STM32F7_LTDC_L2_RGB565) +# define STM32_LTDC_L2_BPP 16 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB16_565 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB565) +#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB1555) +# define STM32_LTDC_L2_BPP 16 +# define STM32_LTDC_L2_COLOR_FMT ??? +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB1555) +#elif defined(CONFIG_STM32F7_LTDC_L2_RGB888) +# define STM32_LTDC_L2_BPP 24 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB24 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB888) +#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB8888) +# define STM32_LTDC_L2_BPP 32 +# define STM32_LTDC_L2_COLOR_FMT ??? +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB8888) +#endif + +/* Framebuffer sizes in bytes */ + +#if STM32_LTDC_L1_BPP == 8 +# define STM32_L1_STRIDE (STM32_LTDC_WIDTH) +#elif STM32_LTDC_L1_BPP == 16 +# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 16 + 7) / 8) +#elif STM32_LTDC_L1_BPP == 24 +# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 24 + 7) / 8) +#elif STM32_LTDC_L1_BPP == 32 +# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 32 + 7) / 8) +#else +# error Undefined or unrecognized base resolution +#endif + +/* LTDC only supports 8 bit per pixel overal */ + +#define STM32_LTDC_Lx_BYPP(n) ((n) / 8) + +#define STM32_L1_FBSIZE (STM32_L1_STRIDE * STM32_LTDC_HEIGHT) + +#ifdef CONFIG_STM32F7_LTDC_L2 +# ifndef CONFIG_STM32F7_LTDC_L2_WIDTH +# define CONFIG_STM32F7_LTDC_L2_WIDTH STM32_LTDC_WIDTH +# endif + +# if CONFIG_STM32F7_LTDC_L2_WIDTH > STM32_LTDC_WIDTH +# error Width of Layer 2 exceeds the width of the display +# endif + +# ifndef CONFIG_STM32F7_LTDC_L2_HEIGHT +# define CONFIG_STM32F7_LTDC_L2_HEIGHT STM32_LTDC_HEIGHT +# endif + +# if CONFIG_STM32F7_LTDC_L2_HEIGHT > STM32_LTDC_HEIGHT +# error Height of Layer 2 exceeds the height of the display +# endif + +# if STM32_LTDC_L2_BPP == 8 +# define STM32_L2_STRIDE (CONFIG_STM32F7_LTDC_L2_WIDTH) +# elif STM32_LTDC_L2_BPP == 16 +# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 16 + 7) / 8) +# elif STM32_LTDC_L2_BPP == 24 +# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 24 + 7) / 8) +# elif STM32_LTDC_L2_BPP == 32 +# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 32 + 7) / 8) +# else +# error Undefined or unrecognized base resolution +# endif + +# define STM32_L2_FBSIZE (STM32_L2_STRIDE * CONFIG_STM32F7_LTDC_L2_HEIGHT) + +#else +# define STM32_L2_FBSIZE (0) +#endif + +/* Total memory used for framebuffers */ + +#define STM32_TOTAL_FBSIZE (STM32_L1_FBSIZE + STM32_L2_FBSIZE) + +/* Debug option */ + +#ifdef CONFIG_STM32F7_LTDC_REGDEBUG +# define regerr lcderr +# define reginfo lcdinfo +#else +# define regerr(x...) +# define reginfo(x...) +#endif + +/* Preallocated LTDC framebuffers */ + +/* Position the framebuffer memory in the center of the memory set aside. We + * will use any skirts before or after the framebuffer memory as a guard against + * wild framebuffer writes. + */ + +#define STM32_LTDC_BUFFER_SIZE CONFIG_STM32F7_LTDC_FB_SIZE +#define STM32_LTDC_BUFFER_FREE (STM32_LTDC_BUFFER_SIZE - STM32_TOTAL_FBSIZE) +#define STM32_LTDC_BUFFER_START (CONFIG_STM32F7_LTDC_FB_BASE + \ + STM32_LTDC_BUFFER_FREE/2) + +#if STM32_LTDC_BUFFER_FREE < 0 +# error "STM32_LTDC_BUFFER_SIZE not large enough for frame buffers" +#endif + +/* Layer frame buffer */ + +#define STM32_LTDC_BUFFER_L1 STM32_LTDC_BUFFER_START +#define STM32_LTDC_ENDBUF_L1 (STM32_LTDC_BUFFER_L1 + STM32_L1_FBSIZE) + +#ifdef CONFIG_STM32F7_LTDC_L2 +# define STM32_LTDC_BUFFER_L2 STM32_LTDC_ENDBUF_L1 +# define STM32_LTDC_ENDBUF_L2 (STM32_LTDC_BUFFER_L2 + STM32_L2_FBSIZE) +#else +# define STM32_LTDC_ENDBUF_L2 STM32_LTDC_ENDBUF_L1 +#endif + +/* Layer helpers */ + +#ifdef CONFIG_STM32F7_LTDC_L2 +# define LTDC_NLAYERS 2 +#else +# define LTDC_NLAYERS 1 +#endif + +#define LAYER(i) g_ltdc.layer[i] +#define LAYER_L1 g_ltdc.layer[LTDC_LAYER_L1] +#define LAYER_L2 g_ltdc.layer[LTDC_LAYER_L2] + +/* Dithering */ + +#ifndef CONFIG_STM32F7_LTDC_DITHER_RED +# define STM32_LTDC_DITHER_RED 0 +#else +# define STM32_LTDC_DITHER_RED CONFIG_STM32F7_LTDC_DITHER_RED +#endif +#ifndef CONFIG_STM32F7_LTDC_DITHER_GREEN +# define STM32_LTDC_DITHER_GREEN 0 +#else +# define STM32_LTDC_DITHER_GREEN CONFIG_STM32F7_LTDC_DITHER_GREEN +#endif +#ifndef CONFIG_STM32F7_LTDC_DITHER_BLUE +# define STM32_LTDC_DITHER_BLUE 0 +#else +# define STM32_LTDC_DITHER_BLUE CONFIG_STM32F7_LTDC_DITHER_BLUE +#endif + +/* Background color */ + +#ifndef CONFIG_STM32F7_LTDC_BACKCOLOR +# define STM32_LTDC_BACKCOLOR 0 +#else +# define STM32_LTDC_BACKCOLOR CONFIG_STM32F7_LTDC_BACKCOLOR +#endif + +/* Internal operation flags */ + +#define LTDC_LAYER_SETAREA (1 << 0) /* Change visible area */ +#define LTDC_LAYER_SETALPHAVALUE (1 << 1) /* Change constant alpha value */ +#define LTDC_LAYER_SETBLENDMODE (1 << 2) /* Change blendmode */ +#define LTDC_LAYER_SETCOLORKEY (1 << 3) /* Change color key */ +#define LTDC_LAYER_ENABLECOLORKEY (1 << 4) /* Enable colorkey */ +#define LTDC_LAYER_SETCOLOR (1 << 5) /* Change default color */ +#define LTDC_LAYER_SETENABLE (1 << 6) /* Change enabled state */ +#define LTDC_LAYER_ENABLE (1 << 7) /* Enable the layer */ + +/* Layer initializing state */ + +#define LTDC_LAYER_INIT LTDC_LAYER_SETAREA | \ + LTDC_LAYER_SETALPHAVALUE | \ + LTDC_LAYER_SETBLENDMODE | \ + LTDC_LAYER_SETCOLORKEY | \ + LTDC_LAYER_SETCOLOR | \ + LTDC_LAYER_SETENABLE | \ + LTDC_LAYER_ENABLE + +/* Blendfactor reset values for flip operation */ + +#define STM32_LTDC_BF1_RESET 6 +#define STM32_LTDC_BF2_RESET 7 + +/* Check pixel format support by DMA2D driver */ + +#ifdef CONFIG_STM32F7_DMA2D +# if defined(CONFIG_STM32F7_LTDC_L1_L8) || \ + defined(CONFIG_STM32F7_LTDC_L2_L8) +# if !defined(CONFIG_STM32F7_DMA2D_L8) +# error "DMA2D must support FB_FMT_RGB8 pixel format" +# endif +# endif +# if defined(CONFIG_STM32F7_LTDC_L1_RGB565) || \ + defined(CONFIG_STM32F7_LTDC_L2_RGB565) +# if !defined(CONFIG_STM32F7_DMA2D_RGB565) +# error "DMA2D must support FB_FMT_RGB16_565 pixel format" +# endif +# endif +# if defined(CONFIG_STM32F7_LTDC_L1_RGB888) || \ + defined(CONFIG_STM32F7_LTDC_L2_RGB888) +# if !defined(CONFIG_STM32F7_DMA2D_RGB888) +# error "DMA2D must support FB_FMT_RGB24 pixel format" +# endif +# endif +#endif + +/* Calculate the size of the layers clut table */ + +#ifdef CONFIG_FB_CMAP +# if defined(CONFIG_STM32F7_DMA2D) && !defined(CONFIG_STM32F7_DMA2D_L8) +# error "DMA2D must also support L8 CLUT pixel format if supported by LTDC" +# endif +# ifdef STM32_LTDC_L1CMAP +# ifdef CONFIG_FB_TRANSPARENCY +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) +# else +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) +# endif +# endif +# ifdef STM32_LTDC_L2CMAP +# undef STM32_LAYER_CLUT_SIZE +# ifdef CONFIG_FB_TRANSPARENCY +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) * 2 +# else +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) * 2 +# endif +# endif +#endif + +#ifndef CONFIG_FB_CMAP +# if defined(STM32_LTDC_L1CMAP) || defined(STM32_LTDC_L2CMAP) +# undef STM32_LTDC_L1CMAP +# undef STM32_LTDC_L2CMAP +# error "Enable cmap to support the configured layer format!" +# endif +#endif + +/* Layer clut rgb value positioning */ + +#define LTDC_L1CLUT_REDOFFSET 0 +#define LTDC_L1CLUT_GREENOFFSET 256 +#define LTDC_L1CLUT_BLUEOFFSET 512 +#define LTDC_L2CLUT_REDOFFSET 768 +#define LTDC_L2CLUT_GREENOFFSET 1024 +#define LTDC_L2CLUT_BLUEOFFSET 1280 + +/* Layer argb clut register position */ + +#define LTDC_CLUT_ADD(n) ((uint32_t)(n) << 24) +#define LTDC_CLUT_ALPHA(n) LTDC_CLUT_ADD(n) +#define LTDC_CLUT_RED(n) ((uint32_t)(n) << 16) +#define LTDC_CLUT_GREEN(n) ((uint32_t)(n) << 8) +#define LTDC_CLUT_BLUE(n) ((uint32_t)(n) << 0) +#define LTDC_CLUT_RGB888_MASK 0xffffff + +/* Layer argb cmap conversion */ + +#define LTDC_CMAP_ALPHA(n) ((uint32_t)(n) >> 24) +#define LTDC_CMAP_RED(n) ((uint32_t)(n) >> 16) +#define LTDC_CMAP_GREEN(n) ((uint32_t)(n) >> 8) +#define LTDC_CMAP_BLUE(n) ((uint32_t)(n) >> 0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This enumeration names each layer supported by the hardware */ + +enum stm32_layer_e +{ + LTDC_LAYER_L1 = 0, /* LCD Layer 1 */ + LTDC_LAYER_L2, /* LCD Layer 2 */ +}; + +/* LTDC General layer information */ + +struct stm32_layer_s +{ +#ifdef CONFIG_STM32F7_LTDC_INTERFACE + /* LTDC interface */ + + struct ltdc_layer_s ltdc; /* Layer control structure */ +#endif + + struct stm32_ltdc_s state; /* Layer state structure */ + + /* Blending */ + + uint8_t opac; /* Opacity value for blending */ + uint8_t bf1; /* Blend factor 1 */ + uint8_t bf2; /* Blend factor 2 */ + + /* Operation */ + + uint8_t operation; /* Operation flags */ +#ifdef CONFIG_STM32F7_DMA2D + FAR struct dma2d_layer_s *dma2d; /* dma2d interface */ +#endif +}; + +/* This structure provides the state of each LTDC layer */ + +struct stm32_state_s +{ + /* Layer state */ + + struct stm32_ltdc_s state[LTDC_NLAYERS]; +}; + +/* This structure provides the overall state of the LTDC layer */ + +struct stm32_ltdcdev_s +{ + /* Layer information */ + + struct stm32_layer_s layer[LTDC_NLAYERS]; +}; + +/* Layer cmap table description */ + +#ifdef STM32_LAYER_CLUT_SIZE +enum stm32_clut_e +{ + LTDC_L1CLUT_OFFSET = 0, + LTDC_L2CLUT_OFFSET = STM32_LTDC_NCLUT * sizeof(uint32_t) +}; +#endif + +/* Interrupt handling */ + +struct stm32_interrupt_s +{ + bool wait; /* Informs that the task is waiting for the irq */ + bool handled; /* Informs that an irq was handled */ + int irq; /* irq number */ + sem_t *sem; /* Semaphore for waiting for irq */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Global register operation */ + +static void stm32_lcd_enable(bool enable); +#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) +static void stm32_ltdc_gpioconfig(void); +#endif +static void stm32_ltdc_periphconfig(void); +static void stm32_ltdc_bgcolor(uint32_t rgb); +static void stm32_ltdc_dither(bool enable, uint8_t red, + uint8_t green, uint8_t blue); +static int stm32_ltdcirq(int irq, void *context, FAR void *arg); +static int stm32_ltdc_waitforirq(void); +static int stm32_ltdc_reload(uint8_t value, bool waitvblank); + +/* Layer and layer register operation */ + +static inline void stm32_ltdc_lsetopac(FAR struct stm32_layer_s *layer); +static inline void stm32_ltdc_lunsetopac(FAR struct stm32_layer_s *layer); +static inline uint8_t stm32_ltdc_lgetopac(FAR struct stm32_layer_s *layer); +static inline bool stm32_ltdc_lvalidate(FAR const struct stm32_layer_s *layer); +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +static int stm32_ltdc_lvalidatearea(FAR struct stm32_layer_s *layer, + fb_coord_t xpos, fb_coord_t ypos, + fb_coord_t xres, fb_coord_t yres, + fb_coord_t srcxpos, fb_coord_t srcypos); +#endif +static void stm32_ltdc_lupdate(FAR struct stm32_layer_s *layer); + +static void stm32_ltdc_lpixelformat(FAR struct stm32_layer_s *layer); +static inline void stm32_ltdc_lframebuffer(FAR struct stm32_layer_s *layer); +static void stm32_ltdc_larea(FAR struct stm32_layer_s *layer); +static void stm32_ltdc_lcolor(FAR struct stm32_layer_s *layer, uint32_t argb); +static void stm32_ltdc_lcolorkey(FAR struct stm32_layer_s *layer); +static void stm32_ltdc_lalpha(FAR struct stm32_layer_s *layer); +static void stm32_ltdc_lblendmode(FAR struct stm32_layer_s *layer, + uint8_t bf1, uint8_t bf2); + +#ifdef STM32_LAYER_CLUT_SIZE +static void stm32_ltdc_lclut(FAR struct stm32_layer_s *layer, + FAR const struct fb_cmap_s *cmap); +static void stm32_ltdc_lclutenable(FAR struct stm32_layer_s *layer, + bool enable); +#endif +static void stm32_ltdc_linit(int lid); +static void stm32_ltdc_lenable(FAR struct stm32_layer_s *layer); +static void stm32_ltdc_lclear(FAR struct stm32_layer_s *layer, + nxgl_mxpixel_t color); + +/* Generic frame buffer interface */ + +static int stm32_getvideoinfo(FAR struct fb_vtable_s *vtable, + struct fb_videoinfo_s *vinfo); +static int stm32_getplaneinfo(FAR struct fb_vtable_s *vtable, + int planeno, struct fb_planeinfo_s *pinfo); + +/* The following is provided only if the video hardware supports RGB color + * mapping + */ + +#ifdef STM32_LAYER_CLUT_SIZE +static int stm32_getcmap(struct fb_vtable_s *vtable, + struct fb_cmap_s *cmap); +static int stm32_putcmap(struct fb_vtable_s *vtable, + const struct fb_cmap_s *cmap); +#endif + +/* ltdc interface */ + +#ifdef STM32_LAYER_CLUT_SIZE +static int stm32_setclut(struct ltdc_layer_s *layer, + const struct fb_cmap_s *cmap); +static int stm32_getclut(struct ltdc_layer_s *layer, + struct fb_cmap_s *cmap); +#endif +static int stm32_lgetvideoinfo(struct ltdc_layer_s *layer, + struct fb_videoinfo_s *vinfo); +static int stm32_lgetplaneinfo(struct ltdc_layer_s *layer, int planeno, + struct fb_planeinfo_s *pinfo); + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +static int stm32_getlid(FAR struct ltdc_layer_s *layer, + int *lid, uint32_t flag); +static int stm32_setcolor(FAR struct ltdc_layer_s *layer, uint32_t argb); +static int stm32_getcolor(FAR struct ltdc_layer_s *layer, uint32_t *argb); +static int stm32_setcolorkey(FAR struct ltdc_layer_s *layer, uint32_t argb); +static int stm32_getcolorkey(FAR struct ltdc_layer_s *layer, uint32_t *argb); +static int stm32_setalpha(FAR struct ltdc_layer_s *layer, uint8_t alpha); +static int stm32_getalpha(FAR struct ltdc_layer_s *layer, uint8_t *alpha); +static int stm32_setblendmode(FAR struct ltdc_layer_s *layer, uint32_t mode); +static int stm32_getblendmode(FAR struct ltdc_layer_s *layer, uint32_t *mode); +static int stm32_setarea(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + fb_coord_t srcxpos, fb_coord_t srcypos); +static int stm32_getarea(FAR struct ltdc_layer_s *layer, + FAR struct ltdc_area_s *area, + fb_coord_t *srcxpos, fb_coord_t *srcypos); +static int stm32_update(FAR struct ltdc_layer_s *layer, uint32_t mode); + +#ifdef CONFIG_STM32F7_DMA2D +static int stm32_blit(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea); +static int stm32_blend(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea); +static int stm32_fillarea(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + uint32_t color); +#endif +#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) +/* PIO pin configurations */ + +static const uint32_t g_ltdcpins[] = +{ + GPIO_LTDC_R4, GPIO_LTDC_R5, GPIO_LTDC_R6, GPIO_LTDC_R7, + GPIO_LTDC_G4, GPIO_LTDC_G5, GPIO_LTDC_G6, GPIO_LTDC_G7, + GPIO_LTDC_B4, GPIO_LTDC_B5, GPIO_LTDC_B6, GPIO_LTDC_B7, +#if BOARD_LTDC_OUTPUT_BPP > 12 + GPIO_LTDC_R3, GPIO_LTDC_G2, GPIO_LTDC_G3, GPIO_LTDC_B3, +# if BOARD_LTDC_OUTPUT_BPP > 16 + GPIO_LTDC_R2, GPIO_LTDC_B2, +# if BOARD_LTDC_OUTPUT_BPP > 18 + GPIO_LTDC_R0, GPIO_LTDC_R1, GPIO_LTDC_G0, GPIO_LTDC_G1, + GPIO_LTDC_B0, GPIO_LTDC_B1, +# endif +# endif +#endif + GPIO_LTDC_VSYNC, GPIO_LTDC_HSYNC, GPIO_LTDC_DE, GPIO_LTDC_CLK +}; + +#define STM32_LTDC_NPINCONFIGS (sizeof(g_ltdcpins) / sizeof(uint32_t)) +#endif /* !CONFIG_STM32F7_LTDC_USE_DSI */ + +/* This structure provides the base layer interface */ + +static const struct fb_vtable_s g_vtable = +{ + .getvideoinfo = stm32_getvideoinfo, + .getplaneinfo = stm32_getplaneinfo +#ifdef STM32_LAYER_CLUT_SIZE + , + .getcmap = stm32_getcmap, + .putcmap = stm32_putcmap +#endif +}; + +/* The LTDC semaphore that enforces mutually exclusive access */ + +static sem_t g_lock; + +/* The semaphore for interrupt handling */ + +static sem_t g_semirq; + +/* This structure provides irq handling */ + +static struct stm32_interrupt_s g_interrupt = +{ + .wait = false, + .handled = true, + .irq = STM32_IRQ_LTDCINT, + .sem = &g_semirq +}; + +/* The layer active state */ + +static uint8_t g_lactive; + +#ifdef STM32_LAYER_CLUT_SIZE +/* The layers clut table entries */ + +static uint32_t g_clut[STM32_LAYER_CLUT_SIZE]; +#endif + +/* The initialized state of the overall LTDC layers */ + +static struct stm32_ltdcdev_s g_ltdc = +{ + .layer[LTDC_LAYER_L1] = + { + .state = + { + .lid = LTDC_LAYER_L1, + .pinfo = + { + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L1, + .fblen = STM32_L1_FBSIZE, + .stride = STM32_L1_STRIDE, + .display = 0, + .bpp = STM32_LTDC_L1_BPP + }, + .vinfo = + { + .fmt = STM32_LTDC_L1_COLOR_FMT, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .nplanes = 1 + } +#ifdef STM32_LTDC_L1CMAP + , .clut = &g_clut[LTDC_L1CLUT_OFFSET] +#endif + } + } +#ifdef CONFIG_STM32F7_LTDC_L2 + , + .layer[LTDC_LAYER_L2] = + { + .state = + { + .lid = LTDC_LAYER_L2, + .pinfo = + { + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L2, + .fblen = STM32_L2_FBSIZE, + .stride = STM32_L2_STRIDE, + .display = 1, + .bpp = STM32_LTDC_L2_BPP + }, + .vinfo = + { + .fmt = STM32_LTDC_L2_COLOR_FMT, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .nplanes = 1 + } +#ifdef STM32_LTDC_L2CMAP + , .clut = &g_clut[LTDC_L2CLUT_OFFSET] +#endif + } + } +#endif +}; + +/* Pixel format lookup table */ + +static const uint32_t stm32_fmt_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1PFCR_PF +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2PFCR_PF +#endif +}; + +/* Register lookup tables */ + +/* LTDC_LxCR */ + +static const uintptr_t stm32_cr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CR +#endif +}; + +/* LTDC_LxWHPCR */ + +static const uintptr_t stm32_whpcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1WHPCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2WHPCR +#endif +}; + +/* LTDC_LxWVPCR */ + +static const uintptr_t stm32_wvpcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1WVPCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2WVPCR +#endif +}; + +/* LTDC_LxPFCR */ + +static const uintptr_t stm32_pfcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1PFCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2PFCR +#endif +}; + +/* LTDC_LxDCCR */ + +static const uintptr_t stm32_dccr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1DCCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2DCCR +#endif +}; + +/* LTDC_LxCKCR */ + +static const uintptr_t stm32_ckcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CKCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CKCR +#endif +}; + +/* LTDC_LxCACR */ + +static const uintptr_t stm32_cacr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CACR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CACR +#endif +}; + +/* LTDC_LxBFCR */ + +static const uintptr_t stm32_bfcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1BFCR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2BFCR +#endif +}; + +/* LTDC_LxCFBAR */ + +static const uintptr_t stm32_cfbar_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBAR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CFBAR +#endif +}; + +/* LTDC_LxCFBLR */ + +static const uintptr_t stm32_cfblr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBLR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CFBLR +#endif +}; + +/* LTDC_LxCFBLNR */ + +static const uintptr_t stm32_cfblnr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBLNR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CFBLNR +#endif +}; + +/* LTDC_LxCLUTWR */ + +#ifdef STM32_LAYER_CLUT_SIZE +static const uintptr_t stm32_clutwr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CLUTWR +# ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2CLUTWR +# endif +}; +#endif + +/* The initialized state of the driver */ + +static bool g_initialized; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Configure global register + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ltdc_gpioconfig + * + * Description: + * Configure GPIO pins for use with the LTDC + * + ****************************************************************************/ + +#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) +static void stm32_ltdc_gpioconfig(void) +{ + int i; + + lcdinfo("Configuring pins\n"); + + /* Configure each pin */ + + for (i = 0; i < STM32_LTDC_NPINCONFIGS; i++) + { + reginfo("set gpio%d = %08x\n", i, g_ltdcpins[i]); + stm32_configgpio(g_ltdcpins[i]); + } +} +#endif + +/**************************************************************************** + * Name: stm32_ltdc_periphconfig + * + * Description: + * Configures the synchronous timings + * Configures the synchronous signals and clock polarity + * + ****************************************************************************/ + +static void stm32_ltdc_periphconfig(void) +{ + uint32_t regval; + +#if defined(CONFIG_STM32F7_LTDC_USE_DSI) + /* work in progress; maybe move to lcdinfo when everything is OK. */ + lcdwarn("LTDC: Expecting preconfigured DSI; not configuring pins for LCD interface\n"); +#else + /* Configure GPIO's */ + stm32_ltdc_gpioconfig(); +#endif + + /* Configure APB2 LTDC clock external */ + + reginfo("configured RCC_APB2ENR=%08x\n", getreg32(STM32_RCC_APB2ENR)); + + /* Configure the SAI PLL external to provide the LCD_CLK */ + + reginfo("configured RCC_PLLSAI=%08x\n", getreg32(STM32_RCC_PLLSAICFGR)); + + /* Configure dedicated clock external */ + + reginfo("configured RCC_DCKCFGR=%08x\n", getreg32(STM32_RCC_DCKCFGR)); + + /* Configure LTDC_SSCR */ + + regval = (STM32_LTDC_SSCR_VSH | STM32_LTDC_SSCR_HSW); + reginfo("set LTDC_SSCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_SSCR); + reginfo("configured LTDC_SSCR=%08x\n", getreg32(STM32_LTDC_SSCR)); + + /* Configure LTDC_BPCR */ + + regval = (STM32_LTDC_BPCR_AVBP | STM32_LTDC_BPCR_AHBP); + reginfo("set LTDC_BPCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_BPCR); + reginfo("configured LTDC_BPCR=%08x\n", getreg32(STM32_LTDC_BPCR)); + + /* Configure LTDC_AWCR */ + + regval = (STM32_LTDC_AWCR_AAH | STM32_LTDC_AWCR_AAW); + reginfo("set LTDC_AWCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_AWCR); + reginfo("configured LTDC_AWCR=%08x\n", getreg32(STM32_LTDC_AWCR)); + + /* Configure LTDC_TWCR */ + + regval = (STM32_LTDC_TWCR_TOTALH | STM32_LTDC_TWCR_TOTALW); + reginfo("set LTDC_TWCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_TWCR); + reginfo("configured LTDC_TWCR=%08x\n", getreg32(STM32_LTDC_TWCR)); + + /* Configure LTDC_GCR */ + + regval = (STM32_LTDC_GCR_PCPOL | STM32_LTDC_GCR_DEPOL + | STM32_LTDC_GCR_VSPOL | STM32_LTDC_GCR_HSPOL); + reginfo("set LTDC_GCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_GCR); + reginfo("configured LTDC_GCR=%08x\n", getreg32(STM32_LTDC_GCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_bgcolor + * + * Description: + * Configures background color of the LCD controller. + * + * Parameter: + * rgb - RGB888 background color + * + ****************************************************************************/ + +static void stm32_ltdc_bgcolor(uint32_t rgb) +{ + reginfo("set LTDC_BCCR=%08x\n", rgb); + putreg32(rgb, STM32_LTDC_BCCR); + reginfo("configured LTDC_BCCR=%08x\n", getreg32(STM32_LTDC_BCCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_dither + * + * Description: + * Configures dither settings of the LCD controller. + * + * Parameter: + * enable - Enable dithering + * red - Red dither width + * green - Green dither width + * blue - Blue dither width + * + ****************************************************************************/ + +static void stm32_ltdc_dither(bool enable, + uint8_t red, + uint8_t green, + uint8_t blue) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_GCR); + + if (enable == true) + { + regval |= LTDC_GCR_DEN; + } + else + { + regval &= ~LTDC_GCR_DEN; + } + + regval &= ~(!LTDC_GCR_DEN | LTDC_GCR_DRW(0) | + LTDC_GCR_DGW(0) | LTDC_GCR_DBW(0)); + regval |= (LTDC_GCR_DRW(red) | LTDC_GCR_DGW(green) | LTDC_GCR_DBW(blue)); + + reginfo("set LTDC_GCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_GCR); + reginfo("configured LTDC_GCR=%08x\n", getreg32(STM32_LTDC_GCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_linepos + * + * Description: + * Configures line position register + * + ****************************************************************************/ + +static void stm32_ltdc_linepos(void) +{ + /* Configure LTDC_LIPCR */ + + reginfo("set LTDC_LIPCR=%08x\n", STM32_LTDC_LIPCR_LIPOS); + putreg32(STM32_LTDC_LIPCR_LIPOS, STM32_LTDC_LIPCR); + reginfo("configured LTDC_LIPCR=%08x\n", getreg32(STM32_LTDC_LIPCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_irqctrl + * + * Description: + * Control interrupts generated by the ltdc controller + * + * Parameter: + * setirqs - set interrupt mask + * clrirqs - clear interrupt mask + * + ****************************************************************************/ + +static void stm32_ltdc_irqctrl(uint32_t setirqs, uint32_t clrirqs) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_IER); + regval &= ~clrirqs; + regval |= setirqs; + reginfo("set LTDC_IER=%08x\n", regval); + putreg32(regval, STM32_LTDC_IER); + reginfo("configured LTDC_IER=%08x\n", getreg32(STM32_LTDC_IER)); +} + +/**************************************************************************** + * Name: stm32_ltdcirq + * + * Description: + * LTDC interrupt handler + * + ****************************************************************************/ + +static int stm32_ltdcirq(int irq, void *context, FAR void *arg) +{ + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + uint32_t regval = getreg32(STM32_LTDC_ISR); + + reginfo("irq = %d, regval = %08x\n", irq, regval); + + if (regval & LTDC_ISR_RRIF) + { + /* Register reload interrupt */ + + /* Clear the interrupt status register */ + + putreg32(LTDC_ICR_CRRIF, STM32_LTDC_ICR); + + /* Update the handled flag */ + + priv->handled = true; + + /* Unlock the semaphore if locked */ + + if (priv->wait) + { + int ret = sem_post(priv->sem); + + if (ret != OK) + { + lcderr("ERROR: sem_post() failed\n"); + return ret; + } + } + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_ltdc_waitforirq + * + * Description: + * Helper waits until the ltdc irq occurs. In the current design That means + * that a register reload was been completed. + * Note! The caller must use this function within a critical section. + * + * Return: + * OK - On success otherwise ERROR + * + ****************************************************************************/ + +static int stm32_ltdc_waitforirq(void) +{ + int ret = OK; + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + irqstate_t flags; + + flags = enter_critical_section(); + + /* Only waits if last enabled interrupt is currently not handled */ + + if (!priv->handled) + { + /* Inform the irq handler the task is able to wait for the irq */ + + priv->wait = true; + + ret = sem_wait(priv->sem); + + /* irq or an error occurs, reset the wait flag */ + + priv->wait = false; + + if (ret != OK) + { + lcderr("ERROR: sem_wait() failed\n"); + } + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: stm32_ltdc_reload + * + * Description: + * Reload the layer shadow register and make layer changes visible. + * Note! The caller must ensure that a previous register reloading has been + * completed. + * + * Parameter: + * value - Reload flag (e.g. upon vertical blank or immediately) + * waitvblank - Wait until register reload is finished + * + ****************************************************************************/ + +static int stm32_ltdc_reload(uint8_t value, bool waitvblank) +{ + int ret = OK; + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + if (value == LTDC_SRCR_VBR) + { + irqstate_t flags; + + /* Prepare shadow register reload for later detection by the task. + * At this point the last register reload must be completed. This is done + * in stm32_update before the next operation is triggered and manipulates + * the shadow register. This handling is only neccessary in the case of + * the application causes shadow register reload. + */ + + flags = enter_critical_section(); + + ASSERT(priv->handled == true); + + /* Reset the handled flag */ + + priv->handled = false; + leave_critical_section(flags); + } + + /* Reloads the shadow register. + * Note! This will not trigger an register reload interrupt if + * immediately reload is set. + */ + + reginfo("set LTDC_SRCR=%08x\n", value); + putreg32(value, STM32_LTDC_SRCR); + reginfo("configured LTDC_SRCR=%08x\n", getreg32(STM32_LTDC_SRCR)); + + if (waitvblank & (value == LTDC_SRCR_VBR)) + { + /* Wait upon vertical blanking period */ + + ret = stm32_ltdc_waitforirq(); + } + + /* Otherwise check if reload is completed before the next operation */ + + return ret; +} + +/**************************************************************************** + * Name: stm32_global_configure + * + * Description: + * Configure background color + * Configure interrupts + * Configure dithering + * + ****************************************************************************/ + +static void stm32_global_configure(void) +{ + /* Initialize the LTDC semaphore that enforces mutually exclusive access */ + + sem_init(&g_lock, 0, 1); + + /* Initialize the semaphore for interrupt handling. This waitsem + * semaphore is used for signaling and, hence, should not have priority + * inheritance enabled. + */ + + sem_init(g_interrupt.sem, 0, 0); + sem_setprotocol(g_interrupt.sem, SEM_PRIO_NONE); + + /* Attach LTDC interrupt vector */ + + (void)irq_attach(g_interrupt.irq, stm32_ltdcirq, NULL); + + /* Enable the IRQ at the NVIC */ + + up_enable_irq(g_interrupt.irq); + + /* Enable register reload interrupt only */ + + stm32_ltdc_irqctrl(LTDC_IER_RRIE, LTDC_IER_TERRIE | LTDC_IER_FUIE | LTDC_IER_LIE); + + /* Configure line interrupt */ + + stm32_ltdc_linepos(); + + /* Set the default active layer */ + +#ifndef CONFIG_STM32F7_LTDC_L2 + g_lactive = LTDC_LAYER_L1; +#else + g_lactive = LTDC_LAYER_L2; +#endif + +#ifdef STM32_LAYER_CLUT_SIZE + /* cleanup clut */ + + memset(g_clut, 0, sizeof(g_clut)); +#endif + + /* Configure dither */ + + stm32_ltdc_dither( +#ifdef CONFIG_STM32F7_LTDC_DITHER + true, +#else + false, +#endif + STM32_LTDC_DITHER_RED, + STM32_LTDC_DITHER_GREEN, + STM32_LTDC_DITHER_BLUE); + + /* Configure background color of the controller */ + + stm32_ltdc_bgcolor(STM32_LTDC_BACKCOLOR); +} + +/**************************************************************************** + * Name: stm32_lcd_enable + * + * Description: + * Disable the LCD peripheral + * + * Parameter: + * enable - Enable or disable + * + ****************************************************************************/ + +static void stm32_lcd_enable(bool enable) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_GCR); + reginfo("get LTDC_GCR=%08x\n", regval); + + if (enable == true) + { + regval |= LTDC_GCR_LTDCEN; + } + else + { + regval &= ~LTDC_GCR_LTDCEN; + } + + reginfo("set LTDC_GCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_GCR); + reginfo("configured LTDC_GCR=%08x\n", getreg32(STM32_LTDC_GCR)); +} + +/**************************************************************************** + * Configure layer register + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ltdc_lclutenable + * + * Description: + * Disable or enable the layer clut support + * + * Parameter: + * layer - Reference to the layer control structure + * enable - Enable or disable + * + ****************************************************************************/ + +#ifdef STM32_LAYER_CLUT_SIZE +static void stm32_ltdc_lclutenable(FAR struct stm32_layer_s *layer, bool enable) +{ + uint32_t regval; + + regval = getreg32(stm32_cr_layer_t[layer->state.lid]); + reginfo("get LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); + + /* Disable the clut support during update the color table */ + + if (enable == true) + { + regval |= LTDC_LxCR_CLUTEN; + } + else + { + regval &= ~LTDC_LxCR_CLUTEN; + } + + reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); + putreg32(regval, stm32_cr_layer_t[layer->state.lid]); +} +#endif + +/**************************************************************************** + * Name: stm32_ltdc_lsetopac + * + * Description: + * Helper to set the layer to opac + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static inline void stm32_ltdc_lsetopac(FAR struct stm32_layer_s *layer) +{ + layer->opac = 0xff; +} + +/**************************************************************************** + * Name: stm32_ltdc_lunsetopac + * + * Description: + * Helper to set the layer opacity to the alpha value + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static inline void stm32_ltdc_lunsetopac(FAR struct stm32_layer_s *layer) +{ + layer->opac = 0; +} + +/**************************************************************************** + * Name: stm32_ltdc_lgetopac + * + * Description: + * Helper to get the configured layer opacity + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static inline uint8_t stm32_ltdc_lgetopac(FAR struct stm32_layer_s *layer) +{ + return layer->opac | layer->state.alpha; +} + +/**************************************************************************** + * Name: stm32_ltdc_lvalidate + * + * Description: + * Helper to check if the layer is an valid ltdc layer + * + * Parameter: + * layer - Reference to the layer control structure + * + * Return: + * true - layer valid + * false - layer invalid + * + ****************************************************************************/ + +static inline bool stm32_ltdc_lvalidate(FAR const struct stm32_layer_s *layer) +{ +#ifdef CONFIG_STM32F7_LTDC_L2 + return layer == &LAYER_L1 || layer == &LAYER_L2; +#else + return layer == &LAYER_L1; +#endif +} + +/**************************************************************************** + * Name: stm32_ltdc_lvalidatearea + * + * Description: + * Check if layer coordinates out of valid area. + * + * Parameter: + * layer - Reference to the layer control structure + * xpos - top left x position of the active area + * ypos - top left y position of the active area + * xres - width of the active area + * yres - height of teh active area + * srcxpos - Top left x position from where data visible in the active area + * srcypos - Top left y position from where data visible in the active area + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +static int stm32_ltdc_lvalidatearea(FAR struct stm32_layer_s *layer, + fb_coord_t xpos, fb_coord_t ypos, + fb_coord_t xres, fb_coord_t yres, + fb_coord_t srcxpos, fb_coord_t srcypos) +{ + FAR const struct fb_videoinfo_s *vinfo = &layer->state.vinfo; + + if ((xpos > vinfo->xres - 1) || + (ypos > vinfo->yres -1) || + (xres > vinfo->xres - xpos) || + (yres > vinfo->yres - ypos) || + (srcxpos > xpos + xres - 1) || + (srcypos > ypos + yres - 1)) + + { + lcderr("ERROR: layer coordinates out of valid area: xpos = %d > %d, \ + ypos = %d > %d, width = %d > %d, height = %d > %d, \ + srcxpos = %d > %d, srcypos = %d > %d", + xpos, vinfo->xres - 1, + ypos, vinfo->yres - 1, + xres, vinfo->xres - xpos, + yres, vinfo->yres - ypos, + srcxpos, xpos + xres - 1, + srcypos, ypos + yres - 1); + + lcderr(" Returning EINVAL\n"); + return -EINVAL; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_ltdc_lupdate + * + * Description: + * Updates shadow register content depending on the layer operation flag. + * This made changes for the given layer visible after the next shadow + * register reload. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lupdate(FAR struct stm32_layer_s *layer) +{ + if (layer->operation & LTDC_LAYER_SETAREA) + { + /* Updates the layer horizontal and vertical position register */ + + stm32_ltdc_larea(layer); + } + + if (layer->operation & LTDC_LAYER_SETALPHAVALUE) + { + /* Updates the constant alpha register */ + + stm32_ltdc_lalpha(layer); + } + + if (layer->operation & LTDC_LAYER_SETBLENDMODE) + { + /* Update blendfactor 1 and 2 register */ + + stm32_ltdc_lblendmode(layer, layer->bf1, layer->bf2); + } + + if (layer->operation & LTDC_LAYER_SETCOLORKEY) + { + /* Update layer colorkey register */ + + stm32_ltdc_lcolorkey(layer); + } + + if (layer->operation & LTDC_LAYER_SETCOLOR) + { + /* Update layer color register */ + + stm32_ltdc_lcolor(layer, layer->state.color); + } + + if (layer->operation & LTDC_LAYER_SETENABLE) + { + /* Enable the layer */ + + stm32_ltdc_lenable(layer); + } +} + +/**************************************************************************** + * Name: stm32_ltdc_larea + * + * Description: + * Change the active area of the layer + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_larea(struct stm32_layer_s *layer) +{ + uint32_t lxpos; + uint32_t lypos; + uint32_t whpcr; + uint32_t wvpcr; + FAR struct stm32_ltdc_s *priv = &layer->state; + FAR struct ltdc_area_s *area = &priv->area; + + reginfo("xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area->xpos, area->ypos, area->xres, area->yres); + + lxpos = area->xpos + (STM32_LTDC_LxWHPCR_WHSTPOS + 1); + lypos = area->ypos + (STM32_LTDC_LxWVPCR_WVSTPOS + 1); + + /* Accumulate horizontal position */ + + whpcr = LTDC_LxWHPCR_WHSTPOS(lxpos); + whpcr |= LTDC_LxWHPCR_WHSPPOS(lxpos + area->xres - 1); + + /* Accumulate vertical position */ + + wvpcr = LTDC_LxWVPCR_WVSTPOS(lypos); + wvpcr |= LTDC_LxWVPCR_WVSPPOS(lypos + area->yres - 1); + + /* Configure LxWHPCR / LxWVPCR register */ + + reginfo("set LTDC_L%dWHPCR=%08x\n", priv->lid + 1, whpcr); + putreg32(whpcr, stm32_whpcr_layer_t[priv->lid]); + reginfo("set LTDC_L%dWVPCR=%08x\n", priv->lid + 1, wvpcr); + putreg32(wvpcr, stm32_wvpcr_layer_t[priv->lid]); + + /* Configure framebuffer */ + + stm32_ltdc_lframebuffer(layer); + + /* Clear area operation flag */ + + layer->operation &= ~LTDC_LAYER_SETAREA; +} + +/**************************************************************************** + * Name: stm32_ltdc_lpixelformat + * + * Description: + * Set the layer pixel format. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lpixelformat(FAR struct stm32_layer_s *layer) +{ + /* Configure PFCR register */ + + reginfo("set LTDC_L%dPFCR=%08x\n", layer->state.lid + 1, + stm32_fmt_layer_t[layer->state.lid]); + putreg32(stm32_fmt_layer_t[layer->state.lid], + stm32_pfcr_layer_t[layer->state.lid]); +} + +/**************************************************************************** + * Name: stm32_ltdc_framebuffer + * + * Description: + * Change layer framebuffer offset. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * Reference to the layer control structure + * + ****************************************************************************/ + +static inline void stm32_ltdc_lframebuffer(FAR struct stm32_layer_s *layer) +{ + uint32_t offset; + uint32_t cfblr; + FAR struct stm32_ltdc_s *priv = &layer->state; + FAR struct ltdc_area_s *area = &priv->area; + FAR const struct fb_planeinfo_s *pinfo = &priv->pinfo; + + /* Configure LxCFBAR register */ + + /* Calculate offset position in the framebuffer */ + + offset = priv->xpos * STM32_LTDC_Lx_BYPP(pinfo->bpp) + + pinfo->stride * priv->ypos; + + reginfo("set LTDC_L%dCFBAR=%08x\n", priv->lid + 1, pinfo->fbmem + offset); + putreg32((uint32_t)pinfo->fbmem + offset, stm32_cfbar_layer_t[priv->lid]); + + /* Configure LxCFBLR register */ + + /* Calculate line length */ + + cfblr = LTDC_LxCFBLR_CFBP(pinfo->stride) | + LTDC_LxCFBLR_CFBLL(area->xres * STM32_LTDC_Lx_BYPP(pinfo->bpp) + 3); + + reginfo("set LTDC_L%dCFBLR=%08x\n", priv->lid + 1, cfblr); + putreg32(cfblr, stm32_cfblr_layer_t[priv->lid]); + + /* Configure LxCFBLNR register */ + + reginfo("set LTDC_L%dCFBLNR=%08x\n", priv->lid + 1, area->yres); + putreg32(area->yres, stm32_cfblnr_layer_t[priv->lid]); +} + +/**************************************************************************** + * Name: stm32_ltdc_lalpha + * + * Description: + * Change the layer alpha value and clear the alpha operation flag. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lalpha(FAR struct stm32_layer_s *layer) +{ + uint8_t opac = stm32_ltdc_lgetopac(layer); + reginfo("set LTDC_L%dCACR=%02x\n", layer->state.lid + 1, opac); + putreg32(opac, stm32_cacr_layer_t[layer->state.lid]); + + /* Clear the constant alpha operation flag */ + + layer->operation &= ~LTDC_LAYER_SETALPHAVALUE; +} + +/**************************************************************************** + * Name: stm32_ltdc_blendfactor + * + * Description: + * Change layer blend factors used for blend operation and clear the + * blendmode operation flag. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * layer - Reference to the laxer control structure + * bf1 - Value of blend factor 1 + * bf2 - Value of blend factor 2 + * + ****************************************************************************/ + +static void stm32_ltdc_lblendmode(FAR struct stm32_layer_s *layer, + uint8_t bf1, uint8_t bf2) +{ + reginfo("set LTDC_L%dBFCR=%08x\n", layer->state.lid + 1, + (LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2))); + putreg32((LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2)), + stm32_bfcr_layer_t[layer->state.lid]); + + /* Clear the blendmode operation flag */ + + layer->operation &= ~LTDC_LAYER_SETBLENDMODE; +} + +/**************************************************************************** + * Name: stm32_ltdc_lcolor + * + * Description: + * Change layer default color and clear the color operation flag. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lcolor(FAR struct stm32_layer_s *layer, uint32_t argb) +{ + reginfo("set LTDC_L%dDCCR=%08x\n", layer->state.lid + 1, argb); + putreg32(argb, stm32_dccr_layer_t[layer->state.lid]); + + /* Clear the color operation flag */ + + layer->operation &= ~LTDC_LAYER_SETCOLOR; +} + +/**************************************************************************** + * Name: stm32_ltdc_lcolorkey + * + * Description: + * Change layer colorkey and clear the colorkey operation flag. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lcolorkey(FAR struct stm32_layer_s *layer) +{ + uint32_t regval; + + regval = getreg32(stm32_cr_layer_t[layer->state.lid]); + + if (layer->operation & LTDC_LAYER_ENABLECOLORKEY) + { + /* Set colorkey */ + + reginfo("set LTDC_L%dCKCR=%08x\n", + layer->state.lid + 1, layer->state.colorkey); + putreg32(layer->state.colorkey, stm32_ckcr_layer_t[layer->state.lid]); + + /* Enable colorkey */ + + regval |= LTDC_LxCR_COLKEN; + } + else + { + /* Disable colorkey */ + + regval &= ~LTDC_LxCR_COLKEN; + } + + reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); + putreg32(regval, stm32_cr_layer_t[layer->state.lid]); + + /* Clear the colorkey operation flag */ + + layer->operation &= ~LTDC_LAYER_SETCOLORKEY; +} + +/**************************************************************************** + * Name: stm32_ltdc_lclut + * + * Description: + * Update the clut layer register during blank period. + * Note! The clut register are no shadow register. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +#ifdef STM32_LAYER_CLUT_SIZE +static void stm32_ltdc_lclut(FAR struct stm32_layer_s *layer, + FAR const struct fb_cmap_s *cmap) +{ + int n; + uint32_t regval; + uint32_t *clut; + irqstate_t flags; + + /* Disable clut during register update */ + + stm32_ltdc_lclutenable(layer, false); + + /* Set the clut memory address */ + + clut = layer->state.clut; + + /* Reload shadow control register. + * This never changed any layer setting as long the layer register not up to + * date. This is what stm32_update does. + */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); + + flags = enter_critical_section(); + + /* Update the clut registers */ + + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) + { + /* Update the layer clut entry */ +#ifndef CONFIG_FB_TRANSPARENCY + uint8_t *clut888 = (uint8_t *)clut; + uint16_t offset = 3 * n; + + clut888[offset] = cmap->blue[n]; + clut888[offset + 1] = cmap->green[n]; + clut888[offset + 2] = cmap->red[n]; + + regval = (uint32_t)LTDC_CLUT_BLUE(clut888[offset]) | + (uint32_t)LTDC_CLUT_GREEN(clut888[offset + 1]) | + (uint32_t)LTDC_CLUT_RED(clut888[offset + 2]) | + (uint32_t)LTDC_CLUT_ADD(n); +#else + clut[n] = (uint32_t)LTDC_CLUT_ALPHA(cmap->transp[n]) | + (uint32_t)LTDC_CLUT_RED(cmap->red[n]) | + (uint32_t)LTDC_CLUT_GREEN(cmap->green[n]) | + (uint32_t)LTDC_CLUT_BLUE(cmap->blue[n]); + regval = (uint32_t)LTDC_CLUT_ADD(n) | (clut[n] & LTDC_CLUT_RGB888_MASK); +#endif + + + reginfo("set LTDC_L%dCLUTWR = %08x, cmap->first = %d, cmap->len = %d\n", + layer->state.lid + 1, regval, cmap->first, cmap->len); + putreg32(regval, stm32_clutwr_layer_t[layer->state.lid]); + } + + leave_critical_section(flags); + + /* Enable clut */ + + stm32_ltdc_lclutenable(layer, true); + + /* Reload shadow control register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} +#endif + +/**************************************************************************** + * Name: stm32_ltdc_lenable + * + * Description: + * Disable or enable specific layer. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Parameter: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lenable(FAR struct stm32_layer_s *layer) +{ + uint32_t regval; + + /* Enable or disable layer */ + + regval = getreg32(stm32_cr_layer_t[layer->state.lid]); + + if (layer->operation & LTDC_LAYER_ENABLE) + { + regval |= LTDC_LxCR_LEN; + } + else + { + regval &= ~LTDC_LxCR_LEN; + } + + reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); + putreg32(regval, stm32_cr_layer_t[layer->state.lid]); + + /* Clear the enable operation flag */ + + layer->operation &= ~LTDC_LAYER_SETENABLE; +} + +/**************************************************************************** + * Name stm32_ltdc_lclear + * + * Description: + * Clear the whole layer + * + * Parameter: + * layer - Reference to the layer control structure + * color - The color to clear + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid + * + ****************************************************************************/ + +static void stm32_ltdc_lclear(FAR struct stm32_layer_s *layer, + nxgl_mxpixel_t color) +{ + FAR struct stm32_ltdc_s *priv = &layer->state; + +#if STM32_LTDC_L1_BPP == 8 || STM32_LTDC_L2_BPP == 8 + if (priv->pinfo.bpp == 8) + { + uint8_t *dest = (uint8_t *)priv->pinfo.fbmem; + int i; + + lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", + priv->pinfo.bpp, color, dest, priv->pinfo.fblen); + + for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint8_t)) + { + *dest++ = (uint8_t)color; + } + + return; + } +#endif + +#if STM32_LTDC_L1_BPP == 16 || STM32_LTDC_L2_BPP == 16 + if (priv->pinfo.bpp == 16) + { + uint16_t *dest = (uint16_t *)priv->pinfo.fbmem; + int i; + + lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", + priv->pinfo.bpp, color, dest, priv->pinfo.fblen); + + for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint16_t)) + { + *dest++ = (uint16_t)color; + } + + return; + } +#endif + +#if STM32_LTDC_L1_BPP == 24 || STM32_LTDC_L2_BPP == 24 + if (priv->pinfo.bpp == 24) + { + uint8_t *dest = (uint8_t *)priv->pinfo.fbmem; + uint8_t r; + uint8_t g; + uint8_t b; + int i; + + lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", + priv->pinfo.bpp, color, dest, priv->pinfo.fblen); + + r = (uint8_t) color; + g = (uint8_t) (color >> 8); + b = (uint8_t) (color >> 16); + + for (i = 0; i < priv->pinfo.fblen; i += 3*sizeof(uint8_t)) + { + *dest++ = r; + *dest++ = g; + *dest++ = b; + } + + return; + } +#endif + +#if STM32_LTDC_L1_BPP == 32 || STM32_LTDC_L2_BPP == 32 + if (priv->pinfo.bpp == 32) + { + uint32_t *dest = (uint32_t *)priv->pinfo.fbmem; + int i; + + lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", + priv->pinfo.bpp, color, dest, priv->pinfo.fblen); + + for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint32_t)) + { + *dest++ = (uint32_t)color; + } + } +#endif +} + +/**************************************************************************** + * Name: stm32_ltdc_linit + * + * Description: + * Initialize layer to their default states. + * + * Initialize: + * - Reset layer + * - layer fram + * - Reset layerebuffers + * - layer position + * - layer pixelformat + * - layer color + * - layer colorkey + * - layer alpha + * - layer blendmode + * - layer dma2d interface binding + * + * Parameter + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_linit(int lid) +{ + /* Reset layer to their default state */ + + FAR struct stm32_layer_s *layer = &LAYER(lid); + FAR struct stm32_ltdc_s *state = &layer->state; +#ifdef CONFIG_STM32F7_LTDC_INTERFACE + FAR struct ltdc_layer_s *ltdc = &layer->ltdc; + + /* Initialize the ltdc interface */ + + ltdc->getlid = stm32_getlid; + ltdc->getvideoinfo = stm32_lgetvideoinfo; + ltdc->getplaneinfo = stm32_lgetplaneinfo; +# ifdef STM32_LAYER_CLUT_SIZE + ltdc->setclut = stm32_setclut; + ltdc->getclut = stm32_getclut; +#endif + ltdc->setcolor = stm32_setcolor; + ltdc->getcolor = stm32_getcolor; + ltdc->setcolorkey = stm32_setcolorkey; + ltdc->getcolorkey = stm32_getcolorkey; + ltdc->setalpha = stm32_setalpha; + ltdc->getalpha = stm32_getalpha; + ltdc->setblendmode = stm32_setblendmode; + ltdc->getblendmode = stm32_getblendmode; + ltdc->setarea = stm32_setarea; + ltdc->getarea = stm32_getarea; + ltdc->update = stm32_update; +#ifdef CONFIG_STM32F7_DMA2D + ltdc->blit = stm32_blit; + ltdc->blend = stm32_blend; + ltdc->fillarea = stm32_fillarea; +#endif +#endif + + /* Initialize the layer state */ + + state->area.xpos = 0; + state->area.ypos = 0; + state->area.xres = STM32_LTDC_WIDTH; + state->area.yres = STM32_LTDC_HEIGHT; + state->xpos = 0; + state->ypos = 0; + state->color = 0; + state->colorkey = 0; + state->alpha = 0xff; + state->blendmode = LTDC_BLEND_NONE; + state->lock = &g_lock; + + /* Initialize driver internals */ + + layer->opac = 0xff; + layer->bf1 = LTDC_BF1_CONST_ALPHA; + layer->bf2 = LTDC_BF2_CONST_ALPHA; + layer->operation = LTDC_LAYER_INIT; + + /* Clear the layer framebuffer */ + + stm32_ltdc_lclear(layer, 0); + + /* Set Pixel input format */ + + stm32_ltdc_lpixelformat(layer); + + /* Set position, color, colorkey, blendmode, alpha */ + + stm32_ltdc_lupdate(layer); + +#ifdef STM32_LAYER_CLUT_SIZE + /* Disable clut by default */ + + if (layer->state.vinfo.fmt == FB_FMT_RGB8) + { + stm32_ltdc_lclutenable(layer, false); + } +#endif + +#if defined(CONFIG_STM32F7_DMA2D) && defined(CONFIG_STM32F7_LTDC_INTERFACE) + /* Bind the dma2d interface */ + + layer->dma2d = stm32_dma2dinitltdc(state); + DEBUGASSERT(layer->dma2d); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_getvideoinfo + * + * Description: + * Get the videoinfo for the framebuffer + * + * Parameter: + * vtable - The framebuffer driver object + * vinfo - the videoinfo object + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getvideoinfo(struct fb_vtable_s *vtable, + struct fb_videoinfo_s *vinfo) +{ + lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo); + if (vtable) + { + FAR struct ltdc_layer_s *ltdc; +#ifdef CONFIG_STM32F7_LTDC_L2 + ltdc = (FAR struct ltdc_layer_s *)&LAYER_L2; +#else + ltdc = (FAR struct ltdc_layer_s *)&LAYER_L1; +#endif + return stm32_lgetvideoinfo(ltdc, vinfo); + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getplaneinfo + * + * Description: + * Get the planeinfo for the framebuffer + * + * Parameter: + * vtable - The framebuffer driver object + * pinfo - the planeinfo object + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getplaneinfo(struct fb_vtable_s *vtable, int planeno, + struct fb_planeinfo_s *pinfo) +{ + lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo); + if (vtable) + { + FAR struct ltdc_layer_s *ltdc; +#ifdef CONFIG_STM32F7_LTDC_L2 + ltdc = (FAR struct ltdc_layer_s *)&LAYER_L2; +#else + ltdc = (FAR struct ltdc_layer_s *)&LAYER_L1; +#endif + return stm32_lgetplaneinfo(ltdc, planeno, pinfo); + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getcmap + * + * Description: + * Get a range of CLUT values for the LCD + * + * Parameter: + * vtable - The framebuffer driver object + * cmap - the color table + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifdef STM32_LAYER_CLUT_SIZE +static int stm32_getcmap(struct fb_vtable_s *vtable, + struct fb_cmap_s *cmap) +{ +#ifdef CONFIG_STM32F7_LTDC_L2 + return stm32_getclut((FAR struct ltdc_layer_s *)&LAYER_L2, cmap); +#else + return stm32_getclut((FAR struct ltdc_layer_s *)&LAYER_L1, cmap); +#endif +} + +/**************************************************************************** + * Name: stm32_putcmap + * + * Description: + * Set a range of the CLUT values for the LCD + * + * Parameter: + * vtable - The framebuffer driver object + * cmap - the color table + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_putcmap(struct fb_vtable_s *vtable, + const struct fb_cmap_s *cmap) +{ +#ifdef CONFIG_STM32F7_LTDC_L2 + return stm32_setclut((FAR struct ltdc_layer_s *)&LAYER_L2, cmap); +#else + return stm32_setclut((FAR struct ltdc_layer_s *)&LAYER_L1, cmap); +#endif +} +#endif /* STM32_LAYER_CLUT_SIZE */ + +/**************************************************************************** + * Name: stm32_lgetvideoinfo + * + * Description: + * Get video information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * vinfo - Reference to the video info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_lgetvideoinfo(struct ltdc_layer_s *layer, + struct fb_videoinfo_s *vinfo) +{ + lcdinfo("layer=%p vinfo=%p\n", layer, vinfo); + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + if (stm32_ltdc_lvalidate(priv)) + { + memcpy(vinfo, &priv->state.vinfo, sizeof(struct fb_videoinfo_s)); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_lgetplaneinfo + * + * Description: + * Get plane information about the layer + * + * Parameter: + * layer - Reference to the layer control structure + * planeno - Number of the plane + * pinfo - Reference to the plane info structure + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_lgetplaneinfo(struct ltdc_layer_s *layer, int planeno, + struct fb_planeinfo_s *pinfo) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer=%p planeno=%d pinfo=%p\n", layer, planeno, pinfo); + if (stm32_ltdc_lvalidate(priv) && planeno == 0) + { + memcpy(pinfo, &priv->state.pinfo, sizeof(struct fb_planeinfo_s)); + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setclut + * + * Description: + * Configure layer clut (color lookup table). + * Non clut is defined during initializing. + * Clut is active during next vertical blank period. Do not need an update. + * + * Parameter: + * layer - Reference to the layer structure + * cmap - color lookup table with up the 256 entries + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifdef STM32_LAYER_CLUT_SIZE +static int stm32_setclut(struct ltdc_layer_s *layer, + const struct fb_cmap_s *cmap) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + int ret; + + lcdinfo("layer=%p cmap=%p\n", layer, cmap); + + if (stm32_ltdc_lvalidate(priv) && cmap) + { + sem_wait(priv->state.lock); + + if (priv->state.vinfo.fmt != FB_FMT_RGB8) + { + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->state.vinfo.fmt); + ret = -EINVAL; + } + else if (cmap->first >= STM32_LTDC_NCLUT) + { + lcderr("ERROR: only %d color table entries supported\n", + STM32_LTDC_NCLUT); + ret = -EINVAL; + } + else + { + /* Update layer clut and clut register */ + + stm32_ltdc_lclut(priv, cmap); + + ret = OK; + } + + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getclut + * + * Description: + * Get configured layer clut (color lookup table). + * + * Parameter: + * layer - Reference to the layer structure + * cmap - Reference to valid color lookup table accept up the 256 color + * entries + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getclut(struct ltdc_layer_s *layer, + struct fb_cmap_s *cmap) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + int ret; + + lcdinfo("layer=%p cmap=%p\n", layer, cmap); + + if (priv == &LAYER_L1 || priv == &LAYER_L2) + { + sem_wait(priv->state.lock); +#ifdef CONFIG_STM32F7_DMA2D + /* Note! We share the same color lookup table with the dma2d driver and + * the getclut implementation works in the same way. + * To prevent redundant code we simply call the getclut function of the + * dma2d interface. + */ + + ret = priv->dma2d->getclut(priv->dma2d, cmap); +#else + if (priv->state.vinfo.fmt != FB_FMT_RGB8) + { + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->state.vinfo.fmt); + ret = -EINVAL; + } + else if (cmap->first >= STM32_LTDC_NCLUT) + { + lcderr("ERROR: only %d color table entries supported\n", + STM32_LTDC_NCLUT); + ret = -EINVAL; + } + else + { + /* Copy from the layer clut */ + + uint32_t *clut; + int n; + + clut = priv->state.clut; + + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) + { +# ifndef CONFIG_FB_TRANSPARENCY + uint8_t *clut888 = (uint8_t *)clut; + uint16_t offset = 3 * n; + + cmap->blue[n] = clut888[offset]; + cmap->green[n] = clut888[offset + 1]; + cmap->red[n] = clut888[offset + 2]; + + reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, + clut888[offset], clut888[offset + 1], + clut888[offset + 2]); +# else + cmap->transp[n] = (uint8_t)LTDC_CMAP_ALPHA(clut[n]); + cmap->red[n] = (uint8_t)LTDC_CMAP_RED(clut[n]); + cmap->green[n] = (uint8_t)LTDC_CMAP_GREEN(clut[n]); + cmap->blue[n] = (uint8_t)LTDC_CMAP_BLUE(clut[n]); + + reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, + DMA2D_CMAP_ALPHA(clut[n]), DMA2D_CMAP_RED(clut[n]), + DMA2D_CMAP_GREEN(clut[n]), DMA2D_CMAP_BLUE(clut[n])); +# endif + } + + ret = OK; + } +#endif + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} +#endif /* STM32_LAYER_CLUT_SIZE */ + +#ifdef CONFIG_STM32F7_LTDC_INTERFACE +/**************************************************************************** + * Name: getlid + * + * Description: + * Get a specific layer identifier. + * + * Parameter: + * layer - Reference to the layer structure + * lid - Reference to store the layer id + * flag - Operation flag describe the layer identifier + * e.g. get the current active or inactive layer. + * See LTDC_LAYER_* for possible values + * + * Return: + * OK - On success + * Null if invalid flag + * + ****************************************************************************/ + +static int stm32_getlid(FAR struct ltdc_layer_s *layer, int *lid, + uint32_t flag) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("flag = %08x\n", flag); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret = OK; + + sem_wait(priv->state.lock); + + switch (flag) + { + case LTDC_LAYER_OWN: + *lid = priv->state.lid; + break; +#ifdef CONFIG_STM32F7_LTDC_L2 + case LTDC_LAYER_ACTIVE: + *lid = g_lactive; + break; + case LTDC_LAYER_INACTIVE: + *lid = !g_lactive; + break; + case LTDC_LAYER_TOP: + *lid = LTDC_LAYER_L2; + break; + case LTDC_LAYER_BOTTOM: + *lid = LTDC_LAYER_L1; + break; +#else + case LTDC_LAYER_ACTIVE: + case LTDC_LAYER_INACTIVE: + case LTDC_LAYER_TOP: + case LTDC_LAYER_BOTTOM: + *lid = LTDC_LAYER_L1; + break; +#endif +#ifdef CONFIG_STM32F7_DMA2D + case LTDC_LAYER_DMA2D: + ret = priv->dma2d->getlid(priv->dma2d, lid); + break; +#endif + default: + ret = EINVAL; + lcderr("ERROR: Returning EINVAL\n"); + break; + } + + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setcolor + * + * Description: + * Configure layer default color value for the non active layer area. + * Default value during initializing: 0x00000000 + * Color is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * argb - ARGB8888 color value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_setcolor(FAR struct ltdc_layer_s *layer, uint32_t argb) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, argb = %08x\n", layer, argb); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + priv->state.color = argb; + priv->operation |= LTDC_LAYER_SETCOLOR; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getcolor + * + * Description: + * Get configured layer color for the non active layer area. + * + * Parameter: + * layer - Reference to the layer structure + * argb - Reference to store the ARGB8888 color value + * + * Return: + * On success - OK + * On error - -EINVAL + * +*******************************************************************************/ + +static int stm32_getcolor(FAR struct ltdc_layer_s *layer, uint32_t *argb) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, argb = %p\n", layer, argb); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + *argb = priv->state.color; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setcolorkey + * + * Description: + * Configure layer default color key (chromakey) value for transparency. + * Layer default value during initializing: 0x00000000 + * Colorkey is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * rgb - RGB888 color value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_setcolorkey(FAR struct ltdc_layer_s *layer, uint32_t rgb) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, argb = %08x\n", layer, rgb); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + priv->state.colorkey = rgb; + priv->operation |= LTDC_LAYER_SETCOLORKEY; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getcolorkey + * + * Description: + * Get the configured layer color key (chromakey) for transparency. + * + * Parameter: + * layer - Reference to the layer structure + * rgb - Reference to store the RGB888 color key + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getcolorkey(FAR struct ltdc_layer_s *layer, uint32_t *rgb) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, argb = %p\n", layer, rgb); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + *rgb = priv->state.colorkey; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: setalpha + * + * Description: + * Configure layer alpha value factor into blend operation. + * During the layer blend operation the source alpha value is multiplied + * with this alpha value. If the source color format doesn't support alpha + * channel (e.g. non ARGB8888) this alpha value will be used as constant + * alpha value for blend operation. + * Default alpha value during initializing: 0xff + * Alpha is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_setalpha(FAR struct ltdc_layer_s *layer, uint8_t alpha) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, alpha = %02x\n", layer, alpha); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + priv->state.alpha = alpha; + priv->operation |= LTDC_LAYER_SETALPHAVALUE; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getalpha + * + * Description: + * Get configured layer alpha value factor for blend operation. + * + * Parameter: + * layer - Reference to the layer structure + * alpha - Reference to store the alpha value + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getalpha(FAR struct ltdc_layer_s *layer, uint8_t *alpha) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, alpha = %p\n", layer, alpha); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + *alpha = priv->state.alpha; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: setblendmode + * + * Description: + * Configure blend mode of the layer. + * Default mode during initializing: LTDC_BLEND_NONE + * Blendmode is active after next update. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Blend mode (see LTDC_BLEND_*) + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure information: + * LTDC_BLEND_NONE: + * Informs the driver to disable all blend operation for the given layer. + * That means the layer is opaque. Note this has no effect on the + * colorkey settings. + * + * LTDC_BLEND_ALPHA: + * Informs the driver to enable alpha blending for the given layer. + * + * LTDC_BLEND_COLORKEY: + * Informs the driver to enable colorkeying for the given layer. + * + * LTDC_BLEND_SRCPIXELALPHA: + * Informs the driver to use the pixel alpha value of the layer instead + * the constant alpha value. This is only useful for ARGB8888 + * color format. + * + * LTDC_BLEND_DESTPIXELALPHA: + * Informs the driver to use the pixel alpha value of the subjacent layer + * instead the constant alpha value. This is only useful for ARGB8888 + * color format. + * + ****************************************************************************/ + +static int stm32_setblendmode(FAR struct ltdc_layer_s *layer, uint32_t mode) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + uint32_t blendmode = mode; + + lcdinfo("layer = %p, mode = %08x\n", layer, mode); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret = OK; + + sem_wait(priv->state.lock); + + /* Disable colorkeying by default */ + + priv->operation &= ~LTDC_LAYER_ENABLECOLORKEY; + + if (blendmode & (LTDC_BLEND_ALPHA | LTDC_BLEND_PIXELALPHA | + LTDC_BLEND_ALPHAINV | LTDC_BLEND_PIXELALPHAINV)) + { + /* Enable any alpha blending */ + + stm32_ltdc_lunsetopac(priv); + } + else + { + /* Disable any alpha blending */ + + stm32_ltdc_lsetopac(priv); + } + + if (blendmode & LTDC_BLEND_ALPHA || blendmode == LTDC_BLEND_NONE) + { + /* alpha blending introduce LTDC_BLEND_ALPHAINV */ + + priv->bf1 = LTDC_BF1_CONST_ALPHA; + priv->bf2 = LTDC_BF2_CONST_ALPHA; + blendmode &= ~LTDC_BLEND_ALPHA; + } + + if (blendmode & LTDC_BLEND_PIXELALPHA) + { + /* pixel alpha blending introduce LTDC_BLEND_PIXELALPHAINV */ + + priv->bf1 = LTDC_BF1_PIXEL_ALPHA; + priv->bf2 = LTDC_BF2_PIXEL_ALPHA; + blendmode &= ~LTDC_BLEND_PIXELALPHA; + } + + if (blendmode & LTDC_BLEND_ALPHAINV) + { + /* alpha blending of source input */ + + priv->bf2 = LTDC_BF2_CONST_ALPHA; + blendmode &= ~LTDC_BLEND_ALPHAINV; + } + + if (blendmode & LTDC_BLEND_PIXELALPHAINV) + { + /* pixel alpha blending of source input */ + + priv->bf2 = LTDC_BF2_PIXEL_ALPHA; + blendmode &= ~LTDC_BLEND_PIXELALPHAINV; + } + + if (mode & LTDC_BLEND_COLORKEY) + { + /* Enable colorkeying */ + + priv->operation |= LTDC_LAYER_ENABLECOLORKEY; + blendmode &= ~LTDC_BLEND_COLORKEY; + } + if (blendmode) + { + lcderr("ERROR: Unknown blendmode %02x\n", blendmode); + ret = -EINVAL; + } + + if (ret == OK) + { + priv->state.blendmode = mode; + priv->operation |= (LTDC_LAYER_SETBLENDMODE | + LTDC_LAYER_SETALPHAVALUE | + LTDC_LAYER_SETCOLORKEY); + } + + sem_post(priv->state.lock); + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getblendmode + * + * Description: + * Get configured blend mode of the layer. + * + * Parameter: + * layer - Reference to the layer structure + * mode - Reference to store the blend mode + * + * Return: + * On success - OK + * On error - -EINVAL + ****************************************************************************/ + +static int stm32_getblendmode(FAR struct ltdc_layer_s *layer, uint32_t *mode) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, mode = %p\n", layer, mode); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + *mode = priv->state.blendmode; + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setarea + * + * Description: + * Configure visible layer area and the reference position of the first + * pixel of the whole layer which is the first visible top left pixel in + * the active area. + * Area is active after next update. + * + * Parameter: + * layer - Reference to the layer control structure + * area - Reference to the valid area structure for the new active area + * srcxpos - x position of the visible pixel of the whole layer + * srcypos - y position of the visible pixel of the whole layer + * + * Return: + * On success - OK + * On error - -EINVAL + * + * Procedure Information: + * If the srcxpos and srcypos unequal the xpos and ypos of the area + * structure this acts like moving the visible area to another position on + * the screen during the next update operation. + * + ****************************************************************************/ + +static int stm32_setarea(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + fb_coord_t srcxpos, + fb_coord_t srcypos) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, area = %p, srcxpos = %d, srcypos = %d\n", + layer, area, srcxpos, srcypos); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret; + + sem_wait(priv->state.lock); + + ret = stm32_ltdc_lvalidatearea(priv, area->xpos, area->ypos, area->xres, + area->yres, srcxpos, srcypos); + + if (ret == OK) + { + priv->state.xpos = srcxpos; + priv->state.ypos = srcypos; + priv->state.area.xpos = area->xpos; + priv->state.area.ypos = area->ypos; + priv->state.area.xres = area->xres; + priv->state.area.yres = area->yres; + priv->operation |= LTDC_LAYER_SETAREA; + } + + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getarea + * + * Description: + * Get configured visible layer area. + * + * Parameter: + * layer - Reference to the layer control structure + * area - Reference to the area structure to store the active area + * srcxpos - Reference to store the referenced x position of the whole layer + * srcypos - Reference to store the reterenced y position of the whole layer + * + * Return: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getarea(FAR struct ltdc_layer_s *layer, + FAR struct ltdc_area_s *area, + fb_coord_t *srcxpos, fb_coord_t *srcypos) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, area = %p, srcxpos = %p, srcypos = %p\n", + layer, area, srcxpos, srcypos); + + if (stm32_ltdc_lvalidate(priv)) + { + sem_wait(priv->state.lock); + *srcxpos = priv->state.xpos; + *srcypos = priv->state.ypos; + memcpy(area, &priv->state.area, sizeof(struct ltdc_area_s)); + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_update + * + * Description: + * Update current layer settings and make changes visible. + * + * Parameter: + * layer - Reference to the layer structure + * mode - operation mode + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid + * -ECANCELED - Operation cancelled, something goes wrong + * + * Procedure information: + * LTDC_UPDATE_SIM: + * Informs the driver to update both layers simultaneously. Otherwise update + * the given layer only. + * + * LTDC_UPDATE_FLIP: + * Informs the driver to perform a flip operation. + * This only effects the ltdc layer 1 and 2 and can be useful for double + * buffering. Each flip operation changed the active layer to the inactive + * and vice versa. In the context of the ltdc that means, the inactive layer + * is complete disabled. So the subjacent layer is the background layer + * (background color). To reactivate both layer and their current settings + * perform an update without LTDC_UPDATE_FLIP flag. + * + * LTDC_UPDATE_ACTIVATE: + * Informs the driver that the given layer should be the active layer when + * the operation is complete. + * + * LTDC_SYNC_VBLANK: + * Informs the driver to update the layer upon vertical blank. Otherwise + * immediately. + * + ****************************************************************************/ + +static int stm32_update(FAR struct ltdc_layer_s *layer, uint32_t mode) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; +#ifdef CONFIG_STM32F7_LTDC_L2 + FAR struct stm32_layer_s *active = &LAYER(g_lactive); + FAR struct stm32_layer_s *inactive = &LAYER(!g_lactive); +#endif + + lcdinfo("layer = %p, mode = %08x\n", layer, mode); + + if (stm32_ltdc_lvalidate(priv)) + { + /* Reload immediately by default */ + + bool waitvblank = false; + uint8_t reload = LTDC_SRCR_IMR; + + sem_wait(priv->state.lock); + + if (mode & LTDC_SYNC_VBLANK) + { + reload = LTDC_SRCR_VBR; + } + + if (mode & LTDC_SYNC_WAIT) + { + waitvblank = true; + } + + /* Ensures that last register reload operation has been completed */ + + if (stm32_ltdc_waitforirq() != OK) + { + lcderr("ERROR: Returning ECANCELED\n"); + return -ECANCELED; + } + + /* Update the given layer */ + + stm32_ltdc_lupdate(priv); + +#ifdef CONFIG_STM32F7_LTDC_L2 + /* The following operation only useful if layer 2 is supported. + * Otherwise ignore it. + */ + + if (mode & LTDC_UPDATE_SIM) + { + /* Also update the flip layer */ + + stm32_ltdc_lupdate(&LAYER(!priv->state.lid)); + } + + if (mode & LTDC_UPDATE_ACTIVATE) + { + /* Set the given layer to the next active layer */ + + g_lactive = priv->state.lid; + + /* Also change the current active layer for flip operation */ + + active = &LAYER(!g_lactive); + } + + if (mode & LTDC_UPDATE_FLIP) + { + /* Reset if manipulated by ACTIVATE flag */ + + inactive = &LAYER(!active->state.lid); + + /* Set blendfactor for current active layer to there reset value */ + + stm32_ltdc_lblendmode(active, STM32_LTDC_BF1_RESET, + STM32_LTDC_BF2_RESET); + + /* Set blendfactor for current inactive layer */ + + stm32_ltdc_lblendmode(inactive, inactive->bf1, inactive->bf2); + + /* Disable the active layer */ + + active->operation &= ~LTDC_LAYER_ENABLE; + + stm32_ltdc_lenable(active); + + /* Enable the inactive layer */ + + inactive->operation |= LTDC_LAYER_ENABLE; + + stm32_ltdc_lenable(inactive); + + /* Ensure that both layer active and the manipulated layer + * settings restored during the next update (non flip) operation + */ + + active->operation |= (LTDC_LAYER_SETBLENDMODE | + LTDC_LAYER_ENABLE | + LTDC_LAYER_SETCOLOR | + LTDC_LAYER_SETENABLE); + + /* Change layer activity */ + + g_lactive = inactive->state.lid; + } +#endif + + /* Make the changes visible */ + + stm32_ltdc_reload(reload, waitvblank); + + sem_post(priv->state.lock); + + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +#ifdef CONFIG_STM32F7_DMA2D +/**************************************************************************** + * Name: stm32_blit + * + * Description: + * Copy selected area from a source layer to selected position of the + * destination layer. + * + * Parameter: + * dest - Reference to the destination layer + * destxpos - Selected x position of the destination layer + * destypos - Selected y position of the destination layer + * src - Reference to the source layer + * srcarea - Reference to the selected area of the source layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * + ****************************************************************************/ + +static int stm32_blit(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *src, + FAR const struct ltdc_area_s *srcarea) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)dest; + + lcdinfo("dest = %p, destxpos = %d, destypos = %d, src = %p, srcarea = %p\n", + dest, destxpos, destypos, src, srcarea); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret; + + sem_wait(priv->state.lock); + ret = priv->dma2d->blit(priv->dma2d, destxpos, destypos, src, srcarea); + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_blend + * + * Description: + * Blends the selected area from a foreground layer with selected position + * of the background layer. Copy the result to the destination layer. Note! + * The content of the foreground and background layer is not changed. + * + * Parameter: + * dest - Reference to the destination layer + * destxpos - Selected x position of the destination layer + * destypos - Selected y position of the destination layer + * fore - Reference to the foreground layer + * forexpos - Selected x position of the foreground layer + * foreypos - Selected y position of the foreground layer + * back - Reference to the background layer + * backarea - Reference to the selected area of the background layer + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * + ****************************************************************************/ + +static int stm32_blend(FAR struct ltdc_layer_s *dest, + fb_coord_t destxpos, fb_coord_t destypos, + FAR const struct dma2d_layer_s *fore, + fb_coord_t forexpos, fb_coord_t foreypos, + FAR const struct dma2d_layer_s *back, + FAR const struct ltdc_area_s *backarea) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)dest; + + lcdinfo("dest=%p, destxpos=%d, destypos=%d, " + "fore=%p, forexpos=%d foreypos=%d, " + "back=%p, backarea=%p\n", + dest, destxpos, destypos, fore, forexpos, foreypos, back, backarea); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret; + + sem_wait(priv->state.lock); + ret = priv->dma2d->blend(priv->dma2d, destxpos, destypos, + fore, forexpos, foreypos, back, backarea); + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: fillarea + * + * Description: + * Fill the selected area of the whole layer with a specific color. + * + * Parameter: + * layer - Reference to the layer structure + * area - Reference to the valid area structure select the area + * color - Color to fill the selected area. Color must be formatted + * according to the layer pixel format. + * + * Return: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * area outside the visible area of the layer. + * + ****************************************************************************/ + +static int stm32_fillarea(FAR struct ltdc_layer_s *layer, + FAR const struct ltdc_area_s *area, + uint32_t color) +{ + FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + + lcdinfo("layer = %p, area = %p, color = %08x\n", layer, area, color); + + if (stm32_ltdc_lvalidate(priv)) + { + int ret; + + sem_wait(priv->state.lock); + ret = priv->dma2d->fillarea(priv->dma2d, area, color); + sem_post(priv->state.lock); + + return ret; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} +#endif + +/**************************************************************************** + * Name: stm32_ltdcgetlayer + * + * Description: + * This is a non-standard framebuffer interface. + * Get the specific layer object by the layer id to enable layer hardware + * support. + * + * Parameter: + * lid - Layer identifier + * + * Return: + * Reference to the layer control structure on success or Null if lid + * is invalid. + * + ****************************************************************************/ + +FAR struct ltdc_layer_s *stm32_ltdcgetlayer(int lid) +{ + lcdinfo("lid: %d\n", lid); + + if (lid == LTDC_LAYER_L1 || lid == LTDC_LAYER_L2) + { + return (FAR struct ltdc_layer_s *) &LAYER(lid); + } + + lcderr("ERROR: Returning EINVAL\n"); + errno = EINVAL; + return NULL; +} +#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ + +/**************************************************************************** + * Name: stm32_ltdcinitialize + * + * Description: + * Initialize the ltdc controller + * + * Return: + * OK + * + ****************************************************************************/ + +int stm32_ltdcinitialize(void) +{ +#ifdef CONFIG_STM32F7_DMA2D + int ret; +#endif + + lcdinfo("Initialize LTDC driver\n"); + + if (g_initialized == true) + { + return OK; + } + + /* Disable the LCD */ + + stm32_lcd_enable(false); + + lcdinfo("Configuring the LCD controller\n"); + + /* Configure LCD periphery */ + + lcdinfo("Configure lcd periphery\n"); + stm32_ltdc_periphconfig(); + + /* Configure global ltdc register */ + + lcdinfo("Configure global register\n"); + stm32_global_configure(); + +#ifdef CONFIG_STM32F7_DMA2D + /* Initialize the dma2d controller */ + + ret = up_dma2dinitialize(); + + if (ret != OK) + { + return ret; + } +#endif + + /* Initialize ltdc layer */ + + lcdinfo("Initialize ltdc layer\n"); + stm32_ltdc_linit(LTDC_LAYER_L1); +#ifdef CONFIG_STM32F7_LTDC_L2 + stm32_ltdc_linit(LTDC_LAYER_L2); +#endif + + /* Display layer 1 and 2 */ + + stm32_ltdc_lenable(&LAYER_L1); +#ifdef CONFIG_STM32F7_LTDC_L2 + stm32_ltdc_lenable(&LAYER_L2); +#endif + + /* Enable the backlight */ + +#ifdef CONFIG_STM32F7_LCD_BACKLIGHT + stm32_backlight(true); +#endif + + /* Reload shadow register */ + + lcdinfo("Reload shadow register\n"); + stm32_ltdc_reload(LTDC_SRCR_IMR, false); + + /* Turn the LCD on */ + + lcdinfo("Enabling the display\n"); + stm32_lcd_enable(true); + + /* Set initialized state */ + + g_initialized = true; + return OK; +} + +/**************************************************************************** + * Name: stm32_ltdcgetvplane + * + * Description: + * Return a a reference to the framebuffer object for the specified video + * plane. + * + * Input parameters: + * None + * + * Returned value: + * Reference to the framebuffer object (NULL on failure) + * + ****************************************************************************/ + +struct fb_vtable_s *stm32_ltdcgetvplane(int vplane) +{ + lcdinfo("vplane: %d\n", vplane); + + if (vplane == 0) + { + return (struct fb_vtable_s *)&g_vtable; + } + + return NULL; +} + +/**************************************************************************** + * Name: stm32_ltdcuninitialize + * + * Description: + * Uninitialize the framebuffer driver. Bad things will happen if you + * call this without first calling fb_initialize()! + * + ****************************************************************************/ + +void stm32_ltdcuninitialize(void) +{ + /* Disable all ltdc interrupts */ + + stm32_ltdc_irqctrl(0, LTDC_IER_RRIE | LTDC_IER_TERRIE | + LTDC_IER_FUIE | LTDC_IER_LIE); + + up_disable_irq(g_interrupt.irq); + irq_detach(g_interrupt.irq); + + /* Disable the LCD controller */ + + stm32_lcd_enable(false); + + /* Set initialized state */ + + g_initialized = false; +} + +/**************************************************************************** + * Name: stm32_lcdclear + * + * Description: + * This is a non-standard LCD interface just for the STM32 LTDC. Clearing the + * display in the normal way by writing a sequences of runs that covers the + * entire display can be slow. Here the display is cleared by simply setting + * all video memory to the specified color. + * + * Parameter: + * color - The color the clear the whole framebuffer + * + ****************************************************************************/ + +void stm32_lcdclear(nxgl_mxpixel_t color) +{ +#ifdef CONFIG_STM32F7_LTDC_L2 + stm32_ltdc_lclear(&LAYER(LTDC_LAYER_L2), color); +#endif + stm32_ltdc_lclear(&LAYER(LTDC_LAYER_L1), color); +} + +/**************************************************************************** + * Name: stm32_lcd_backlight + * + * Description: + * Provide this interface to turn the backlight on and off. + * + * Parameter: + * blon - Enable or disable the lcd backlight + * + ****************************************************************************/ + +#ifdef CONFIG_STM32F7_LCD_BACKLIGHT +void stm32_backlight(bool blon) +{ + /* Set default backlight level CONFIG_STM32F7_LTDC_DEFBACKLIGHT */ + + lcderr("ERROR: Not supported\n"); +} +#endif diff --git a/arch/arm/src/stm32f7/stm32_ltdc.h b/arch/arm/src/stm32f7/stm32_ltdc.h new file mode 100755 index 00000000000..c0e46986363 --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_ltdc.h @@ -0,0 +1,157 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_ltdc.h + * + * Copyright (C) 2013-2014 Ken Pettit. All rights reserved. + * Authors: Ken Pettit + * Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H +#define __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include + +#ifdef CONFIG_STM32F7_LTDC + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/* Common layer state structure for the LTDC and DMA2D controller */ + +struct stm32_ltdc_s +{ + /* Fixed settings */ + + int lid; /* Layer identifier */ + struct fb_videoinfo_s vinfo; /* Layer videoinfo */ + struct fb_planeinfo_s pinfo; /* Layer planeinfo */ + + /* Positioning */ + + struct ltdc_area_s area; /* Active layer area */ + fb_coord_t xpos; /* Reference x position */ + fb_coord_t ypos; /* Reference y position */ + + /* Coloring */ + + uint32_t color; /* Layer color definition */ +#ifdef CONFIG_FB_CMAP + uint32_t *clut; /* 32-bit aligned clut color table */ +#endif + + /* Blending */ + + uint8_t alpha; /* Layer constant alpha value */ + uint32_t colorkey; /* Layer colorkey */ + uint32_t blendmode; /* Layer blend factor */ + + /* Operation */ + + sem_t *lock; /* Ensure mutually exclusive access */ +}; + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ +/* The STM32 LTDC driver uses the common framebuffer interfaces declared in + * include/nuttx/video/fb.h. + */ + +int stm32_ltdcinitialize(void); +FAR struct fb_vtable_s *stm32_ltdcgetvplane(int vplane); +void stm32_ltdcuninitialize(void); + +/************************************************************************************ + * Name: stm32_ltdcgetlayer + * + * Description: + * Get the ltdc layer structure to perform hardware layer operation + * + * Parameter: + * lid - Layer identifier + * + * Return: + * Reference to the layer control structure on success or Null if parameter + * invalid. + * + ************************************************************************************/ + +FAR struct ltdc_layer_s *stm32_ltdcgetlayer(int lid); + +/************************************************************************************ + * Name: stm32_lcdclear + * + * Description: + * This is a non-standard LCD interface just for the STM32 LTDC. Clearing the + * display in the normal way by writing a sequences of runs that covers the + * entire display can be slow. Here the display is cleared by simply setting + * all video memory to the specified color. + * + ************************************************************************************/ + +void stm32_lcdclear(nxgl_mxpixel_t color); + +/************************************************************************************ + * Name: stm32_lcd_backlight + * + * Description: + * If CONFIG_STM32F7_LCD_BACKLIGHT is defined, then the board-specific logic must + * provide this interface to turn the backlight on and off. + * + ************************************************************************************/ + +#ifdef CONFIG_STM32F7_LCD_BACKLIGHT +void stm32_backlight(bool blon); +#endif + +#endif /* CONFIG_STM32F7_LTDC */ +#endif /* __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H */ diff --git a/arch/arm/src/stm32f7/stm32f76xx77xx_rcc.c b/arch/arm/src/stm32f7/stm32f76xx77xx_rcc.c index 5a08806eb3a..f43aa27b0b1 100644 --- a/arch/arm/src/stm32f7/stm32f76xx77xx_rcc.c +++ b/arch/arm/src/stm32f7/stm32f76xx77xx_rcc.c @@ -909,7 +909,7 @@ static void stm32_stdclockconfig(void) | RCC_DCKCFGR2_CK48MSEL_MASK | RCC_DCKCFGR2_SDMMCSEL_MASK | RCC_DCKCFGR2_SDMMC2SEL_MASK - | RCC_DCKCFGR2_DSISELL_MASK); + | RCC_DCKCFGR2_DSISEL_MASK); regval |= ( STM32_RCC_DCKCFGR2_USART1SRC | STM32_RCC_DCKCFGR2_USART2SRC diff --git a/configs/Kconfig b/configs/Kconfig old mode 100644 new mode 100755 index c7f8704765d..0257f18af2c --- a/configs/Kconfig +++ b/configs/Kconfig @@ -1160,6 +1160,17 @@ config ARCH_BOARD_STM32F746G_DISCO MCU. The STM32F746NGH6 is a 216MHz Cortex-M7 operation with 1024Kb Flash memory and 320Kb SRAM. +config ARCH_BOARD_STM32F769I_DISCO + bool "STMicro STM32F769I-Discovery board" + depends on ARCH_CHIP_STM32F769NI + select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS + ---help--- + STMicro STM32F769I-DISCO development board featuring the STM32F769NIH6 + MCU. The STM32F769NIH6 is a 216MHz Cortex-M7 with 1024Kb Flash + memory and 320Kb SRAM. + config ARCH_BOARD_STM32F746_WS bool "Waveshare STM32F746 board" depends on ARCH_CHIP_STM32F746IG @@ -1621,6 +1632,7 @@ config ARCH_BOARD default "stm32f411e-disco" if ARCH_BOARD_STM32F411E_DISCO default "stm32f429i-disco" if ARCH_BOARD_STM32F429I_DISCO default "stm32f746g-disco" if ARCH_BOARD_STM32F746G_DISCO + default "stm32f769i-disco" if ARCH_BOARD_STM32F769I_DISCO default "stm32f746-ws" if ARCH_BOARD_STM32F746_WS default "b-l475e-iot01a" if ARCH_BOARD_B_L475E_IOT01A default "stm32l476vg-disco" if ARCH_BOARD_STM32L476VG_DISCO @@ -2014,6 +2026,9 @@ endif if ARCH_BOARD_STM32F746G_DISCO source "configs/stm32f746g-disco/Kconfig" endif +if ARCH_BOARD_STM32F769I_DISCO +source "configs/stm32f769i-disco/Kconfig" +endif if ARCH_BOARD_B_L475E_IOT01A source "configs/b-l475e-iot01a/Kconfig" endif diff --git a/configs/nucleo-144/include/board.h b/configs/nucleo-144/include/board.h index 1027e514ec4..ac06c1fca97 100644 --- a/configs/nucleo-144/include/board.h +++ b/configs/nucleo-144/include/board.h @@ -170,7 +170,6 @@ #define STM32_RCC_DCKCFGR2_CK48MSRC RCC_DCKCFGR2_CK48MSEL_PLL #define STM32_RCC_DCKCFGR2_SDMMCSRC RCC_DCKCFGR2_SDMMCSEL_48MHZ #define STM32_RCC_DCKCFGR2_SDMMC2SRC RCC_DCKCFGR2_SDMMC2SEL_48MHZ -#define STM32_RCC_DCKCFGR2_DSISRC RCC_DCKCFGR2_DSISEL_48MHZ /* Several prescalers allow the configuration of the two AHB buses, the diff --git a/configs/stm32f746-ws/include/board.h b/configs/stm32f746-ws/include/board.h index b58542d120e..d8c80f0677c 100644 --- a/configs/stm32f746-ws/include/board.h +++ b/configs/stm32f746-ws/include/board.h @@ -167,7 +167,6 @@ #define STM32_RCC_DCKCFGR2_CK48MSRC RCC_DCKCFGR2_CK48MSEL_PLLSAI #define STM32_RCC_DCKCFGR2_SDMMCSRC RCC_DCKCFGR2_SDMMCSEL_48MHZ #define STM32_RCC_DCKCFGR2_SDMMC2SRC RCC_DCKCFGR2_SDMMC2SEL_48MHZ -#define STM32_RCC_DCKCFGR2_DSISRC RCC_DCKCFGR2_DSISEL_48MHZ /* Several prescalers allow the configuration of the two AHB buses, the * high-speed APB (APB2) and the low-speed APB (APB1) domains. The maximum diff --git a/configs/stm32f746g-disco/include/board.h b/configs/stm32f746g-disco/include/board.h index e54698e768a..0964e6b90f0 100644 --- a/configs/stm32f746g-disco/include/board.h +++ b/configs/stm32f746g-disco/include/board.h @@ -199,7 +199,6 @@ #define STM32_RCC_DCKCFGR2_CK48MSRC RCC_DCKCFGR2_CK48MSEL_PLLSAI #define STM32_RCC_DCKCFGR2_SDMMCSRC RCC_DCKCFGR2_SDMMCSEL_48MHZ #define STM32_RCC_DCKCFGR2_SDMMC2SRC RCC_DCKCFGR2_SDMMC2SEL_48MHZ -#define STM32_RCC_DCKCFGR2_DSISRC RCC_DCKCFGR2_DSISEL_48MHZ /* Several prescalers allow the configuration of the two AHB buses, the * high-speed APB (APB2) and the low-speed APB (APB1) domains. The maximum diff --git a/configs/stm32f769i-disco/Kconfig b/configs/stm32f769i-disco/Kconfig new file mode 100644 index 00000000000..ff5c8e1a003 --- /dev/null +++ b/configs/stm32f769i-disco/Kconfig @@ -0,0 +1,8 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_STM32F769I_DISCO + +endif # ARCH_BOARD_STM32F769I_DISCO diff --git a/configs/stm32f769i-disco/README.txt b/configs/stm32f769i-disco/README.txt new file mode 100644 index 00000000000..a0fe5800e42 --- /dev/null +++ b/configs/stm32f769i-disco/README.txt @@ -0,0 +1,129 @@ +README +====== + +This README discusses issues unique to NuttX configurations for the +STMicro STM32F769I-DISCO development board featuring the STM32F769NIH6 +MCU. The STM32F769NIH6 is a 216MHz Cortex-M7 operation with 2048K Flash +memory and 512Kb SRAM. The board features: + + - On-board ST-LINK/V2 for programming and debugging, + - Mbed-enabled (mbed.org) + - 4-inch 800x472 color LCD-TFT with capacitive touch screen + - SAI audio codec + - Audio line in and line out jack + - Two ST MEMS microphones + - SPDIF RCA input connector + - Two pushbuttons (user and reset) + - 512-Mbit Quad-SPI Flash memory + - 128-Mbit SDRAM + - Connector for microSD card + - RF-EEPROM daughterboard connector + - USB OTG HS with Micro-AB connectors + - Ethernet connector compliant with IEEE-802.3-2002 and PoE + +Refer to the http://www.st.com website for further information about this +board (search keyword: stm32f769i-disco) + +Contents +======== + + - STATUS + - Development Environment + - LEDs and Buttons + - Serial Console + - Configurations + +STATUS +====== + + 2017-07: The basic NSH configuration is functional using a serial + console on USART1, which is connected to the "virtual com port" + of the ST/LINK USB adapter. + + 2017-07: STM32 F7 Ethernet appears to be functional, but has had + only light testing. + + Work in progress: Use LCD over DSI interface, rest of board. + +Development Environment +======================= + + The Development environments for the STM32F769I-DISCO board are identical + to the environments for other STM32F boards. For full details on the + environment options and setup, see the README.txt file in the + config/stm32f769i-disco directory. + +LEDs and Buttons +================ + + LEDs + ---- + The STM32F769I-DISCO board has numerous LEDs but only one, LD3 located + near the reset button, that can be controlled by software. + + LD3 is controlled by PI1 which is also the SPI2_SCK at the Arduino + interface. One end of LD3 is grounded so a high output on PI1 will + illuminate the LED. + + This LED is not used by the board port unless CONFIG_ARCH_LEDS is defined. + In that case, the usage by the board port is defined in include/board.h + and src/stm32_leds.c. The LEDs are used to encode OS-related events as + follows: + + SYMBOL Meaning LD3 + ------------------- ----------------------- ------ + LED_STARTED NuttX has been started OFF + LED_HEAPALLOCATE Heap has been allocated OFF + LED_IRQSENABLED Interrupts enabled OFF + LED_STACKCREATED Idle stack created ON + LED_INIRQ In an interrupt N/C + LED_SIGNAL In a signal handler N/C + LED_ASSERTION An assertion failed N/C + LED_PANIC The system has crashed FLASH + + Thus is LD3 is statically on, NuttX has successfully booted and is, + apparently, running normally. If LD3 is flashing at approximately + 2Hz, then a fatal error has been detected and the system has halted. + + Buttons + ------- + Pushbutton B1, labelled "User", is connected to GPIO PI11. A high + value will be sensed when the button is depressed. + +Serial Console +============== + + Use the serial interface the ST/LINK provides to the USB host. + + +Configurations +============== + + Common Configuration Information + -------------------------------- + Each STM32F769I-DISCO configuration is maintained in a sub-directory and + can be selected as follow: + + cd tools + ./configure.sh stm32f769i-disco/ + cd - + + Where is one of the sub-directories listed below. + + +Configuration Directories +------------------------- + + nsh: + --- + Configures the NuttShell (NSH) located at apps/examples/nsh. The + Configuration enables the serial interfaces on UART1. + Otherwise nothing is enabled, so that config is a starting point + for initial testing. + Support for builtin applications is enabled, but in the base + configuration no builtin applications are selected. + + nsh-ehternet: + --- + Same as above but a lot more hardware peripherals enabled, + in particular ethernet, as well as networking stuff. diff --git a/configs/stm32f769i-disco/include/board.h b/configs/stm32f769i-disco/include/board.h new file mode 100644 index 00000000000..6cdef6b7c1d --- /dev/null +++ b/configs/stm32f769i-disco/include/board.h @@ -0,0 +1,519 @@ +/************************************************************************************ + * configs/stm32f769i-disco/include/board.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __CONFIG_STM32F769I_DISCO_INCLUDE_BOARD_H +#define __CONFIG_STM32F769I_DISCO_INCLUDE_BOARD_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +#include "stm32_rcc.h" +#if defined(CONFIG_STM32F7_SDMMC1) || defined(CONFIG_STM32F7_SDMMC2) +# include "stm32_sdmmc.h" +#endif + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Clocking *************************************************************************/ +/* The STM32F7 Discovery board provides the following clock sources: + * + * X2: 25 MHz oscillator for STM32F769NIH6 microcontroller and Ethernet PHY. + * X1: 32.768 KHz crystal for STM32F769NIH6 embedded RTC + * + * So we have these clock source available within the STM32 + * + * HSI: 16 MHz RC factory-trimmed + * LSI: 32 KHz RC + * HSE: On-board crystal frequency is 25MHz + * LSE: 32.768 kHz + */ + +#define STM32_BOARD_XTAL 25000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE = 25,000,000 + * + * PLL_VCO = (STM32_HSE_FREQUENCY / PLLM) * PLLN + * Subject to: + * + * 2 <= PLLM <= 63 + * 192 <= PLLN <= 432 + * 192 MHz <= PLL_VCO <= 432MHz + * + * SYSCLK = PLL_VCO / PLLP + * Subject to + * + * PLLP = {2, 4, 6, 8} + * SYSCLK <= 216 MHz + * + * USB OTG FS, SDMMC and RNG Clock = PLL_VCO / PLLQ + * Subject to + * The USB OTG FS requires a 48 MHz clock to work correctly. The SDMMC + * and the random number generator need a frequency lower than or equal + * to 48 MHz to work correctly. + * + * 2 <= PLLQ <= 15 + */ + +#if defined(CONFIG_STM32F7_OTGFS) +/* USB OTG FS clock (= SDMMCCLK = RNGCLK) must be 48 MHz + * + * PLL_VCO = (25,000,000 / 25) * 384 = 384 MHz + * SYSCLK = 384 MHz / 2 = 192 MHz + * USB OTG FS, SDMMC and RNG Clock = 384 MHz / 8 = 48MHz + * DSI CLK = PLL_VCO / PLLR = 384 / 7 = 54,86 MHz + */ + +#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(25) +#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(384) +#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2 +#define STM32_PLLCFG_PLLQ RCC_PLLCFG_PLLQ(8) +#define STM32_PLLCFG_PLLR RCC_PLLCFG_PLLR(7) + +#define STM32_VCO_FREQUENCY ((STM32_HSE_FREQUENCY / 25) * 384) +#define STM32_SYSCLK_FREQUENCY (STM32_VCO_FREQUENCY / 2) +#define STM32_OTGFS_FREQUENCY (STM32_VCO_FREQUENCY / 8) + +#elif defined(CONFIG_STM32F7_SDMMC1) || defined(CONFIG_STM32F7_SDMMC2) || defined(CONFIG_STM32F7_RNG) +/* SDMMCCLK (= USB OTG FS clock = RNGCLK) should be <= 48MHz + * + * PLL_VCO = (25,000,000 / 25) * 432 = 432 MHz + * SYSCLK = 432 MHz / 2 = 216 MHz + * USB OTG FS, SDMMC and RNG Clock = 432 MHz / 10 = 43.2 MHz + * DSI CLK = PLL_VCO / PLLR = 432 / 8 = 54 MHz + */ + +#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(25) +#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(432) +#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2 +#define STM32_PLLCFG_PLLQ RCC_PLLCFG_PLLQ(10) +#define STM32_PLLCFG_PLLR RCC_PLLCFG_PLLR(8) + +#define STM32_VCO_FREQUENCY ((STM32_HSE_FREQUENCY / 25) * 432) +#define STM32_SYSCLK_FREQUENCY (STM32_VCO_FREQUENCY / 2) +#define STM32_OTGFS_FREQUENCY (STM32_VCO_FREQUENCY / 10) + +#else +/* No restrictions by OTGFS + * + * PLL_VCO = (25,000,000 / 25) * 432 = 432 MHz + * SYSCLK = 432 MHz / 2 = 216 MHz + * USB OTG FS, SDMMC and RNG Clock = 432 MHz / 10 = 43.2 MHz + * DSI CLK = PLL_VCO / PLLR = 432 / 8 = 54 MHz + */ + +#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(25) +#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(432) +#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2 +#define STM32_PLLCFG_PLLQ RCC_PLLCFG_PLLQ(10) +#define STM32_PLLCFG_PLLR RCC_PLLCFG_PLLR(8) + +#define STM32_VCO_FREQUENCY ((STM32_HSE_FREQUENCY / 25) * 432) +#define STM32_SYSCLK_FREQUENCY (STM32_VCO_FREQUENCY / 2) +#define STM32_OTGFS_FREQUENCY (STM32_VCO_FREQUENCY / 10) +#endif + +/* Configure factors for PLLSAI clock */ + +#define STM32_RCC_PLLSAICFGR_PLLSAIN RCC_PLLSAICFGR_PLLSAIN(192) +#define STM32_RCC_PLLSAICFGR_PLLSAIP RCC_PLLSAICFGR_PLLSAIP(2) +#define STM32_RCC_PLLSAICFGR_PLLSAIQ RCC_PLLSAICFGR_PLLSAIQ(2) +#define STM32_RCC_PLLSAICFGR_PLLSAIR RCC_PLLSAICFGR_PLLSAIR(2) + +/* Configure Dedicated Clock Configuration Register */ + +#define STM32_RCC_DCKCFGR1_PLLI2SDIVQ RCC_DCKCFGR1_PLLI2SDIVQ(1) +#define STM32_RCC_DCKCFGR1_PLLSAIDIVQ RCC_DCKCFGR1_PLLSAIDIVQ(1) +#define STM32_RCC_DCKCFGR1_PLLSAIDIVR RCC_DCKCFGR1_PLLSAIDIVR(0) +#define STM32_RCC_DCKCFGR1_SAI1SRC RCC_DCKCFGR1_SAI1SEL(0) +#define STM32_RCC_DCKCFGR1_SAI2SRC RCC_DCKCFGR1_SAI2SEL(0) +#define STM32_RCC_DCKCFGR1_TIMPRESRC 0 +#define STM32_RCC_DCKCFGR1_DFSDM1SRC 0 +#define STM32_RCC_DCKCFGR1_ADFSDM1SRC 0 + + + +/* Configure factors for PLLI2S clock */ + +#define STM32_RCC_PLLI2SCFGR_PLLI2SN RCC_PLLI2SCFGR_PLLI2SN(192) +#define STM32_RCC_PLLI2SCFGR_PLLI2SP RCC_PLLI2SCFGR_PLLI2SP(2) +#define STM32_RCC_PLLI2SCFGR_PLLI2SQ RCC_PLLI2SCFGR_PLLI2SQ(2) +#define STM32_RCC_PLLI2SCFGR_PLLI2SR RCC_PLLI2SCFGR_PLLI2SR(2) + +/* Configure Dedicated Clock Configuration Register 2 */ + +#define STM32_RCC_DCKCFGR2_USART1SRC RCC_DCKCFGR2_USART1SEL_APB +#define STM32_RCC_DCKCFGR2_USART2SRC RCC_DCKCFGR2_USART2SEL_APB +#define STM32_RCC_DCKCFGR2_UART4SRC RCC_DCKCFGR2_UART4SEL_APB +#define STM32_RCC_DCKCFGR2_UART5SRC RCC_DCKCFGR2_UART5SEL_APB +#define STM32_RCC_DCKCFGR2_USART6SRC RCC_DCKCFGR2_USART6SEL_APB +#define STM32_RCC_DCKCFGR2_UART7SRC RCC_DCKCFGR2_UART7SEL_APB +#define STM32_RCC_DCKCFGR2_UART8SRC RCC_DCKCFGR2_UART8SEL_APB +#define STM32_RCC_DCKCFGR2_I2C1SRC RCC_DCKCFGR2_I2C1SEL_HSI +#define STM32_RCC_DCKCFGR2_I2C2SRC RCC_DCKCFGR2_I2C2SEL_HSI +#define STM32_RCC_DCKCFGR2_I2C3SRC RCC_DCKCFGR2_I2C3SEL_HSI +#define STM32_RCC_DCKCFGR2_I2C4SRC RCC_DCKCFGR2_I2C4SEL_HSI +#define STM32_RCC_DCKCFGR2_LPTIM1SRC RCC_DCKCFGR2_LPTIM1SEL_APB +#define STM32_RCC_DCKCFGR2_CECSRC RCC_DCKCFGR2_CECSEL_HSI +#define STM32_RCC_DCKCFGR2_CK48MSRC RCC_DCKCFGR2_CK48MSEL_PLLSAI +#define STM32_RCC_DCKCFGR2_SDMMCSRC RCC_DCKCFGR2_SDMMCSEL_48MHZ +#define STM32_RCC_DCKCFGR2_SDMMC2SRC RCC_DCKCFGR2_SDMMC2SEL_48MHZ +#define STM32_RCC_DCKCFGR2_DSISRC RCC_DCKCFGR2_DSISEL_PHY + +/* Several prescalers allow the configuration of the two AHB buses, the + * high-speed APB (APB2) and the low-speed APB (APB1) domains. The maximum + * frequency of the two AHB buses is 216 MHz while the maximum frequency of + * the high-speed APB domains is 108 MHz. The maximum allowed frequency of + * the low-speed APB domain is 54 MHz. + */ + +/* AHB clock (HCLK) is SYSCLK (216 MHz) */ + +#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK /* HCLK = SYSCLK / 1 */ +#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY +#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */ + +/* APB1 clock (PCLK1) is HCLK/4 (54 MHz) */ + +#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLKd4 /* PCLK1 = HCLK / 4 */ +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/4) + +/* Timers driven from APB1 will be twice PCLK1 */ + +#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* APB2 clock (PCLK2) is HCLK/2 (108MHz) */ + +#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM9_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM10_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM11_CLKIN (2*STM32_PCLK2_FREQUENCY) + +/* FLASH wait states + * + * --------- ---------- ----------- + * VDD MAX SYSCLK WAIT STATES + * --------- ---------- ----------- + * 1.7-2.1 V 180 MHz 8 + * 2.1-2.4 V 216 MHz 9 + * 2.4-2.7 V 216 MHz 8 + * 2.7-3.6 V 216 MHz 7 + * --------- ---------- ----------- + */ + +#define BOARD_FLASH_WAITSTATES 7 + +/* LED definitions ******************************************************************/ +/* The STM32F769I-DISCO board has numerous LEDs but only one, LD1 located near the + * reset button, that can be controlled by software (LD2 is a power indicator, LD3-6 + * indicate USB status, LD7 is controlled by the ST-Link). + * + * LD1 is controlled by PI1 which is also the SPI2_SCK at the Arduino interface. + * One end of LD1 is grounded so a high output on PI1 will illuminate the LED. + * + * If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in any way. + * The following definitions are used to access individual LEDs. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED1 0 +#define BOARD_NLEDS 1 + +#define BOARD_LD1 BOARD_LED1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/stm32_leds.c. The LEDs are used to encode OS-related + * events as follows: + * + * SYMBOL Meaning LD1 + * ------------------- ----------------------- ------ + * LED_STARTED NuttX has been started OFF + * LED_HEAPALLOCATE Heap has been allocated OFF + * LED_IRQSENABLED Interrupts enabled OFF + * LED_STACKCREATED Idle stack created ON + * LED_INIRQ In an interrupt N/C + * LED_SIGNAL In a signal handler N/C + * LED_ASSERTION An assertion failed N/C + * LED_PANIC The system has crashed FLASH + * + * Thus is LD1 is statically on, NuttX has successfully booted and is, + * apparently, running normally. If LD1 is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + +#define LED_STARTED 0 /* LD1=OFF */ +#define LED_HEAPALLOCATE 0 /* LD1=OFF */ +#define LED_IRQSENABLED 0 /* LD1=OFF */ +#define LED_STACKCREATED 1 /* LD1=ON */ +#define LED_INIRQ 2 /* LD1=no change */ +#define LED_SIGNAL 2 /* LD1=no change */ +#define LED_ASSERTION 2 /* LD1=no change */ +#define LED_PANIC 3 /* LD1=flashing */ + +/* Button definitions ***************************************************************/ +/* The STM32F7 Discovery supports one button: Pushbutton B1, labelled "User", is + * connected to GPIO PA0. A high value will be sensed when the button is depressed. + */ + +#define BUTTON_USER 0 +#define NUM_BUTTONS 1 +#define BUTTON_USER_BIT (1 << BUTTON_USER) + +/* Alternate function pin selections ************************************************/ + +/* USART6: + * + * These configurations assume that you are using a standard Arduio RS-232 shield + * with the serial interface with RX on pin D0 and TX on pin D1: + * + * -------- --------------- + * STM32F7 + * ARDUINO FUNCTION GPIO + * -- ----- --------- ----- + * DO RX USART6_RX PC7 + * D1 TX USART6_TX PC6 + * -- ----- --------- ----- + */ + +#define GPIO_USART6_RX GPIO_USART6_RX_1 +#define GPIO_USART6_TX GPIO_USART6_TX_1 + +/* USART1: + * USART1 is connected to the "Virtual Com Port" lines + * of the ST-LINK controller. + * + * -------- --------------- + * STM32F7 + * SIGNAME FUNCTION GPIO + * -- ----- --------- ----- + * VCP_RX USART1_RX PA10 + * VCP_TX USART1_TX PA9 + * -- ----- --------- ----- + */ + +#define GPIO_USART1_RX GPIO_USART1_RX_1 +#define GPIO_USART1_TX GPIO_USART1_TX_1 + +/* The STM32 F7 connects to a SMSC LAN8742A PHY using these pins: + * + * STM32 F7 BOARD LAN8742A + * GPIO SIGNAL PIN NAME + * -------- ------------ ------------- + * PG11 RMII_TX_EN TXEN + * PG13 RMII_TXD0 TXD0 + * PG14 RMII_TXD1 TXD1 + * PC4 RMII_RXD0 RXD0/MODE0 + * PC5 RMII_RXD1 RXD1/MODE1 + * PD5 RMII_RXER RXER/PHYAD0 + * PA7 RMII_CRS_DV CRS_DV/MODE2 + * PC1 RMII_MDC MDC + * PA2 RMII_MDIO MDIO + * N/A NRST nRST + * PA1 RMII_REF_CLK nINT/REFCLK0 + * N/A OSC_25M XTAL1/CLKIN + * + * The PHY address is 0, since RMII_RXER/PHYAD0 features a pull down. + * After reset, RMII_RXER/PHYAD0 switches to the RXER function, + * receive errors can be detected using GPIO pin PD5 + */ + +#define GPIO_ETH_RMII_TX_EN GPIO_ETH_RMII_TX_EN_2 +#define GPIO_ETH_RMII_TXD0 GPIO_ETH_RMII_TXD0_2 +#define GPIO_ETH_RMII_TXD1 GPIO_ETH_RMII_TXD1_2 + +/* I2C Mapping + * I2C #4 is connected to the LCD daughter board + * and the WM8994 audio codec. + * + * I2C4_SCL - PD12 + * I2C4_SDA - PB7 + */ +#define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 +#define GPIO_I2C4_SDA GPIO_I2C4_SDA_5 + +/* SDMMC */ + +/* Stream selections are arbitrary for now but might become important in the future + * if we set aside more DMA channels/streams. + * + * SDIO DMA + * DMAMAP_SDMMC1_1 = Channel 4, Stream 3 + * DMAMAP_SDMMC1_2 = Channel 4, Stream 6 + * + * DMAMAP_SDMMC2_1 = Channel 11, Stream 0 + * DMAMAP_SDMMC2_2 = Channel 11, Stream 5 + */ + +// #define DMAMAP_SDMMC1 DMAMAP_SDMMC1_1 +#define DMAMAP_SDMMC2 DMAMAP_SDMMC2_1 + +/* SDIO dividers. Note that slower clocking is required when DMA is disabled + * in order to avoid RX overrun/TX underrun errors due to delayed responses + * to service FIFOs in interrupt driven mode. These values have not been + * tuned!!! + * + * SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(118+2)=400 KHz + */ + +#define STM32_SDMMC_INIT_CLKDIV (118 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +/* DMA ON: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(1+2)=16 MHz + * DMA OFF: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(2+2)=12 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define STM32_SDMMC_MMCXFR_CLKDIV (1 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_MMCXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif + +/* DMA ON: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(1+2)=16 MHz + * DMA OFF: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(2+2)=12 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define STM32_SDMMC_SDXFR_CLKDIV (1 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_SDXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif + +/* SDMMC2 Pin mapping + * + * D0 - PG9 + * D1 - PG10 + * D2 - PB3 + * D3 - PB4 + */ +#define GPIO_SDMMC2_D0 GPIO_SDMMC2_D0_2 +#define GPIO_SDMMC2_D1 GPIO_SDMMC2_D1_2 +#define GPIO_SDMMC2_D2 GPIO_SDMMC2_D2_1 +#define GPIO_SDMMC2_D3 GPIO_SDMMC2_D3_1 + +/* LCD DISPLAY + * (work in progress as of 2017 07 19) + */ +#define BOARD_LTDC_WIDTH 800 +#define BOARD_LTDC_HEIGHT 472 + +#define BOARD_LTDC_HSYNC 10 +#define BOARD_LTDC_HFP 10 +#define BOARD_LTDC_HBP 20 +#define BOARD_LTDC_VSYNC 2 +#define BOARD_LTDC_VFP 4 +#define BOARD_LTDC_VBP 2 + +#define BOARD_LTDC_GCR_PCPOL 0 +#define BOARD_LTDC_GCR_DEPOL 0 +#define BOARD_LTDC_GCR_VSPOL 0 +#define BOARD_LTDC_GCR_HSPOL 0 + +// #define BOARD_LTDC_OUTPUT_BPP 16 + +//#define BOARD_LTDC_GCR_DEN +//#define BOARD_LTDC_GCR_DBW +//#define BOARD_LTDC_GCR_DGW +//#define BOARD_LTDC_GCR_DRW + +/************************************************************************************ + * Public Data + ************************************************************************************/ +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the initialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +void stm32_boardinitialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIG_STM32F769I_DISCO_INCLUDE_BOARD_H */ diff --git a/configs/stm32f769i-disco/kernel/.gitignore b/configs/stm32f769i-disco/kernel/.gitignore new file mode 100644 index 00000000000..7bacd5aee3e --- /dev/null +++ b/configs/stm32f769i-disco/kernel/.gitignore @@ -0,0 +1,2 @@ +/nuttx_user.elf + diff --git a/configs/stm32f769i-disco/kernel/Makefile b/configs/stm32f769i-disco/kernel/Makefile new file mode 100644 index 00000000000..6608ded637d --- /dev/null +++ b/configs/stm32f769i-disco/kernel/Makefile @@ -0,0 +1,122 @@ +############################################################################ +# configs/stm32f769i-disco/kernel/Makefile +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +# This is the directory for the board-specific header files + +BOARD_INCLUDE = $(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)include + +# The entry point name (if none is provided in the .config file) + +CONFIG_USER_ENTRYPOINT ?= user_start +ENTRYPT = $(patsubst "%",%,$(CONFIG_USER_ENTRYPOINT)) + +# Get the paths to the libraries and the links script path in format that +# is appropriate for the host OS + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + USER_LIBPATHS = ${shell for path in $(USERLIBS); do dir=`dirname $(TOPDIR)$(DELIM)$$path`;echo "-L\"`cygpath -w $$dir`\"";done} + USER_LDSCRIPT = -T "${shell cygpath -w $(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)scripts$(DELIM)memory.ld}" + USER_LDSCRIPT += -T "${shell cygpath -w $(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)scripts$(DELIM)user-space.ld}" + USER_HEXFILE += "${shell cygpath -w $(TOPDIR)$(DELIM)nuttx_user.hex}" + USER_SRECFILE += "${shell cygpath -w $(TOPDIR)$(DELIM)nuttx_user.srec}" + USER_BINFILE += "${shell cygpath -w $(TOPDIR)$(DELIM)nuttx_user.bin}" +else + # Linux/Cygwin-native toolchain + USER_LIBPATHS = $(addprefix -L$(TOPDIR)$(DELIM),$(dir $(USERLIBS))) + USER_LDSCRIPT = -T$(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)scripts$(DELIM)memory.ld + USER_LDSCRIPT += -T$(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)scripts$(DELIM)user-space.ld + USER_HEXFILE += "$(TOPDIR)$(DELIM)nuttx_user.hex" + USER_SRECFILE += "$(TOPDIR)$(DELIM)nuttx_user.srec" + USER_BINFILE += "$(TOPDIR)$(DELIM)nuttx_user.bin" +endif + +USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) +USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) +USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +# Source files + +CSRCS = stm32_userspace.c +COBJS = $(CSRCS:.c=$(OBJEXT)) +OBJS = $(COBJS) + +# Targets: + +all: $(TOPDIR)$(DELIM)nuttx_user.elf $(TOPDIR)$(DELIM)User.map +.PHONY: nuttx_user.elf depend clean distclean + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +# Create the nuttx_user.elf file containing all of the user-mode code + +nuttx_user.elf: $(OBJS) + $(Q) $(LD) -o $@ $(USER_LDFLAGS) $(USER_LIBPATHS) $(OBJS) --start-group $(USER_LDLIBS) --end-group $(USER_LIBGCC) + +$(TOPDIR)$(DELIM)nuttx_user.elf: nuttx_user.elf + @echo "LD: nuttx_user.elf" + $(Q) cp -a nuttx_user.elf $(TOPDIR)$(DELIM)nuttx_user.elf +ifeq ($(CONFIG_INTELHEX_BINARY),y) + @echo "CP: nuttx_user.hex" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex nuttx_user.elf $(USER_HEXFILE) +endif +ifeq ($(CONFIG_MOTOROLA_SREC),y) + @echo "CP: nuttx_user.srec" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec nuttx_user.elf $(USER_SRECFILE) +endif +ifeq ($(CONFIG_RAW_BINARY),y) + @echo "CP: nuttx_user.bin" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary nuttx_user.elf $(USER_BINFILE) +endif + +$(TOPDIR)$(DELIM)User.map: nuttx_user.elf + @echo "MK: User.map" + $(Q) $(NM) nuttx_user.elf >$(TOPDIR)$(DELIM)User.map + $(Q) $(CROSSDEV)size nuttx_user.elf + +.depend: + +depend: .depend + +clean: + $(call DELFILE, nuttx_user.elf) + $(call DELFILE, "$(TOPDIR)$(DELIM)nuttx_user.*") + $(call DELFILE, "$(TOPDIR)$(DELIM)User.map") + $(call CLEAN) + +distclean: clean diff --git a/configs/stm32f769i-disco/kernel/stm32_userspace.c b/configs/stm32f769i-disco/kernel/stm32_userspace.c new file mode 100644 index 00000000000..d0fd835c82a --- /dev/null +++ b/configs/stm32f769i-disco/kernel/stm32_userspace.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * configs/stm32f769i-disco/kernel/stm32_userspace.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_NUTTX_USERSPACE +# error "CONFIG_NUTTX_USERSPACE not defined" +#endif + +#if CONFIG_NUTTX_USERSPACE != 0x08020000 +# error "CONFIG_NUTTX_USERSPACE must be 0x08020000 to match memory.ld" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These 'addresses' of these values are setup by the linker script. They are + * not actual uint32_t storage locations! They are only used meaningfully in the + * following way: + * + * - The linker script defines, for example, the symbol_sdata. + * - The declaration extern uint32_t _sdata; makes C happy. C will believe + * that the value _sdata is the address of a uint32_t variable _data (it is + * not!). + * - We can recover the linker value then by simply taking the address of + * of _data. like: uint32_t *pdata = &_sdata; + */ + +extern uint32_t _stext; /* Start of .text */ +extern uint32_t _etext; /* End_1 of .text + .rodata */ +extern const uint32_t _eronly; /* End+1 of read only section (.text + .rodata) */ +extern uint32_t _sdata; /* Start of .data */ +extern uint32_t _edata; /* End+1 of .data */ +extern uint32_t _sbss; /* Start of .bss */ +extern uint32_t _ebss; /* End+1 of .bss */ + +/* This is the user space entry point */ + +int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]); + +const struct userspace_s userspace __attribute__ ((section (".userspace"))) = +{ + /* General memory map */ + + .us_entrypoint = (main_t)CONFIG_USER_ENTRYPOINT, + .us_textstart = (uintptr_t)&_stext, + .us_textend = (uintptr_t)&_etext, + .us_datasource = (uintptr_t)&_eronly, + .us_datastart = (uintptr_t)&_sdata, + .us_dataend = (uintptr_t)&_edata, + .us_bssstart = (uintptr_t)&_sbss, + .us_bssend = (uintptr_t)&_ebss, + + /* Memory manager heap structure */ + + .us_heap = &g_mmheap, + + /* Task/thread startup routines */ + + .task_startup = task_startup, +#ifndef CONFIG_DISABLE_PTHREAD + .pthread_startup = pthread_startup, +#endif + + /* Signal handler trampoline */ + +#ifndef CONFIG_DISABLE_SIGNALS + .signal_handler = up_signal_handler, +#endif + + /* User-space work queue support (declared in include/nuttx/wqueue.h) */ + +#ifdef CONFIG_LIB_USRWORK + .work_usrstart = work_usrstart, +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */ diff --git a/configs/stm32f769i-disco/nsh-ethernet/defconfig b/configs/stm32f769i-disco/nsh-ethernet/defconfig new file mode 100644 index 00000000000..1344adca8ca --- /dev/null +++ b/configs/stm32f769i-disco/nsh-ethernet/defconfig @@ -0,0 +1,102 @@ +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f769i-disco" +CONFIG_ARCH_BOARD_STM32F769I_DISCO=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP_STM32F769NI=y +CONFIG_ARCH_CHIP_STM32F7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_LAZYFPU=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_MEMCARD_ERROR=y +CONFIG_DEBUG_MEMCARD_WARN=y +CONFIG_DEBUG_MEMCARD=y +CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEBUG_NET_WARN=y +CONFIG_DEBUG_NET=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DISABLE_POLL=y +CONFIG_ETH0_PHY_LAN8742A=y +CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y +CONFIG_EXAMPLES_NSH=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HAVE_CXX=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MMCSD=y +CONFIG_MM_REGIONS=3 +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NET_ETH_MTU=1500 +CONFIG_NET_HOSTNAME="stntest" +CONFIG_NET_ICMP_PING=y +CONFIG_NET_ICMP=y +CONFIG_NET_RXAVAIL=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_SOLINGER=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NET_UDP=y +CONFIG_NET=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_MOTD=y +CONFIG_NSH_NETINIT_DEBUG=y +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_RAM_SIZE=376832 +CONFIG_RAM_START=0x20020000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +# CONFIG_SPI_CALLBACK is not set +CONFIG_SPI=y +CONFIG_START_DAY=14 +CONFIG_STM32F7_BKPSRAM=y +CONFIG_STM32F7_CEC=y +CONFIG_STM32F7_DMA1=y +CONFIG_STM32F7_DMA2=y +CONFIG_STM32F7_ETHMAC=y +CONFIG_STM32F7_I2C4=y +CONFIG_STM32F7_OTGHS=y +CONFIG_STM32F7_PHYADDR=0 +CONFIG_STM32F7_PHYSR_100FD=0x18 +CONFIG_STM32F7_PHYSR_100HD=0x8 +CONFIG_STM32F7_PHYSR_10FD=0x14 +CONFIG_STM32F7_PHYSR_10HD=0x4 +CONFIG_STM32F7_PHYSR=31 +CONFIG_STM32F7_PHYSR_ALTCONFIG=y +CONFIG_STM32F7_PHYSR_ALTMODE=0x1C +CONFIG_STM32F7_QUADSPI=y +CONFIG_STM32F7_RNG=y +CONFIG_STM32F7_SDMMC2=y +CONFIG_STM32F7_SDMMC_DMA=y +CONFIG_STM32F7_USART1=y +CONFIG_STM32F7_USART6=y +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/configs/stm32f769i-disco/nsh/defconfig b/configs/stm32f769i-disco/nsh/defconfig new file mode 100644 index 00000000000..18a906007f9 --- /dev/null +++ b/configs/stm32f769i-disco/nsh/defconfig @@ -0,0 +1,48 @@ +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f769i-disco" +CONFIG_ARCH_BOARD_STM32F769I_DISCO=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP_STM32F769NI=y +CONFIG_ARCH_CHIP_STM32F7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_LAZYFPU=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DISABLE_POLL=y +CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y +CONFIG_EXAMPLES_NSH=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HAVE_CXX=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MM_REGIONS=3 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_BUILTIN_APPS=y +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SPI=y +CONFIG_START_DAY=14 +CONFIG_STM32F7_USART1=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/configs/stm32f769i-disco/scripts/Make.defs b/configs/stm32f769i-disco/scripts/Make.defs new file mode 100644 index 00000000000..f08aad516ab --- /dev/null +++ b/configs/stm32f769i-disco/scripts/Make.defs @@ -0,0 +1,113 @@ +############################################################################ +# configs/stm32f769i-disco/scripts/Make.defs +# +# Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = flash.ld + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT) +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +AR = $(ARCROSSDEV)ar rcs +NM = $(ARCROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +ARCHCFLAGS = -fno-builtin +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +ifneq ($(CROSSDEV),arm-nuttx-elf-) + LDFLAGS += -nostartfiles -nodefaultlibs +endif +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = + diff --git a/configs/stm32f769i-disco/scripts/flash.ld b/configs/stm32f769i-disco/scripts/flash.ld new file mode 100644 index 00000000000..1cdb04b8d77 --- /dev/null +++ b/configs/stm32f769i-disco/scripts/flash.ld @@ -0,0 +1,147 @@ +/**************************************************************************** + * configs/stm32f769i-disco/scripts/flash.ld + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Modified 11/4/2013 for STM32F429 support + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The STM32F769NIH6 has 2048Kb of main FLASH memory. This FLASH memory can + * be accessed from either the AXIM interface at address 0x0800:0000 or from + * the ITCM interface at address 0x0020:0000. + * + * Additional information, including the option bytes, is available at at + * FLASH at address 0x1ff0:0000. + * + * In the STM32F769NIH6, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash on ITCM at 0x0020:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x0010:0000 + * + * NuttX does not modify these option bytes. On the unmodified STM32F769I + * DISCO board, the BOOT0 pin is at ground so by default, the STM32 will boot + * to address 0x0020:0000 in ITCM FLASH. + * + * The STM32F769NIH6 also has 512Kb of data SRAM (in addition to ITCM SRAM). + * SRAM is split up into three blocks: + * + * 1) 128Kb of DTCM SRM beginning at address 0x2000:0000 + * 2) 368Kb of SRAM1 beginning at address 0x2002:0000 + * 3) 16Kb of SRAM2 beginning at address 0x2007:c000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00200000, LENGTH = 2048K + flash (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + sram1 (rwx) : ORIGIN = 0x20020000, LENGTH = 368K + sram2 (rwx) : ORIGIN = 0x2007c000, LENGTH = 16K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > sram1 AT > flash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > sram1 + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/configs/stm32f769i-disco/scripts/kernel-space.ld b/configs/stm32f769i-disco/scripts/kernel-space.ld new file mode 100644 index 00000000000..16688ac7549 --- /dev/null +++ b/configs/stm32f769i-disco/scripts/kernel-space.ld @@ -0,0 +1,109 @@ +/**************************************************************************** + * configs/stm32f769i-disco/scripts/kernel-space.ld + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +OUTPUT_ARCH(arm) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > kflash + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > kflash + + .ARM.extab : { + *(.ARM.extab*) + } > kflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > kflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > ksram AT > kflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > ksram + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/configs/stm32f769i-disco/scripts/memory.ld b/configs/stm32f769i-disco/scripts/memory.ld new file mode 100644 index 00000000000..748620b1a8e --- /dev/null +++ b/configs/stm32f769i-disco/scripts/memory.ld @@ -0,0 +1,129 @@ +/**************************************************************************** + * configs/stm32f769i-disco/scripts/memory.ld + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The STM32F769NIH6 has 2048Kb of main FLASH memory. This FLASH memory can + * be accessed from either the AXIM interface at address 0x0800:0000 or from + * the ITCM interface at address 0x0020:0000. + * + * Additional information, including the option bytes, is available at at + * FLASH at address 0x1ff0:0000. + * + * In the STM32F769NIH6, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash on ITCM at 0x0020:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x0010:0000 + * + * NuttX does not modify these option bytes. On the unmodified STM32F769I + * DISCO board, the BOOT0 pin is at ground so by default, the STM32 will boot + * to address 0x0020:0000 in ITCM FLASH. + * + * The STM32F769NIH6 also has 512Kb of data SRAM (in addition to ITCM SRAM). + * SRAM is split up into three blocks: + * + * 1) 128Kb of DTCM SRM beginning at address 0x2000:0000 + * 2) 368Kb of SRAM1 beginning at address 0x2002:0000 + * 3) 16Kb of SRAM2 beginning at address 0x2007:c000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + * + * For MPU support, the kernel-mode NuttX section is assumed to be 128Kb of + * FLASH and 4Kb of SRAM. That is an excessive amount for the kernel which + * should fit into 64KB and, of course, can be optimized as needed (See + * also configs/stm32f769i-disco/scripts/kernel-space.ld). Allowing the + * additional does permit addition debug instrumentation to be added to the + * kernel space without overflowing the partition. + * + * Alignment of the user space FLASH partition is also a critical factor: + * The user space FLASH partition will be spanned with a single region of + * size 2**n bytes. The alignment of the user-space region must be the same. + * As a consequence, as the user-space increases in size, the alignment + * requirement also increases. + * + * This alignment requirement means that the largest user space FLASH region + * you can have will be 512KB at it would have to be positioned at + * 0x08800000. If you change this address, don't forget to change the + * CONFIG_NUTTX_USERSPACE configuration setting to match and to modify + * the check in kernel/userspace.c. + * + * For the same reasons, the maximum size of the SRAM mapping is limited to + * 4KB. Both of these alignment limitations could be reduced by using + * multiple regions to map the FLASH/SDRAM range or perhaps with some + * clever use of subregions. + * + * A detailed memory map for the 112KB SRAM region is as follows: + * + * 0x20001 0000: Kernel .data region. Typical size: 0.1KB + * ------- ---- Kernel .bss region. Typical size: 1.8KB + * 0x20001 0800: Kernel IDLE thread stack (approximate). Size is + * determined by CONFIG_IDLETHREAD_STACKSIZE and + * adjustments for alignment. Typical is 1KB. + * ------- ---- Padded to 4KB + * 0x20001 1000: User .data region. Size is variable. + * ------- ---- User .bss region Size is variable. + * 0x20001 2000: Beginning of kernel heap. Size determined by + * CONFIG_MM_KERNEL_HEAPSIZE. + * ------- ---- Beginning of user heap. Can vary with other settings. + * 0x20004 c000: End+1 of SRAM1 + */ + +MEMORY +{ + /* ITCM boot address */ + + itcm (rwx) : ORIGIN = 0x00200000, LENGTH = 2048K + + /* 2048KB FLASH */ + + kflash (rx) : ORIGIN = 0x08000000, LENGTH = 128K + uflash (rx) : ORIGIN = 0x08020000, LENGTH = 128K + xflash (rx) : ORIGIN = 0x08040000, LENGTH = 1792K + + /* 368KB of contiguous SRAM1 */ + + ksram (rwx) : ORIGIN = 0x20010000, LENGTH = 4K + usram (rwx) : ORIGIN = 0x20011000, LENGTH = 4K + xsram (rwx) : ORIGIN = 0x20012000, LENGTH = 368K - 8K + + /* DTCM SRAM */ + + dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + sram2 (rwx) : ORIGIN = 0x2007c000, LENGTH = 16K +} diff --git a/configs/stm32f769i-disco/scripts/user-space.ld b/configs/stm32f769i-disco/scripts/user-space.ld new file mode 100644 index 00000000000..a021e84a567 --- /dev/null +++ b/configs/stm32f769i-disco/scripts/user-space.ld @@ -0,0 +1,111 @@ +/**************************************************************************** + * configs/stm32f769i-disco/scripts/user-space.ld + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +OUTPUT_ARCH(arm) +SECTIONS +{ + .userspace : { + *(.userspace) + } > uflash + + .text : { + _stext = ABSOLUTE(.); + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > uflash + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > uflash + + .ARM.extab : { + *(.ARM.extab*) + } > uflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > uflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > usram AT > uflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > usram + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/configs/stm32f769i-disco/src/.gitignore b/configs/stm32f769i-disco/src/.gitignore new file mode 100644 index 00000000000..726d936e1e3 --- /dev/null +++ b/configs/stm32f769i-disco/src/.gitignore @@ -0,0 +1,2 @@ +/.depend +/Make.dep diff --git a/configs/stm32f769i-disco/src/Makefile b/configs/stm32f769i-disco/src/Makefile new file mode 100644 index 00000000000..15a80a56169 --- /dev/null +++ b/configs/stm32f769i-disco/src/Makefile @@ -0,0 +1,63 @@ +############################################################################ +# configs/stm32f769i-disco/src/Makefile +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = stm32_boot.c stm32_spi.c + +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += stm32_autoleds.c +else +CSRCS += stm32_userleds.c +endif + +ifeq ($(CONFIG_ARCH_BUTTONS),y) +CSRCS += stm32_buttons.c +endif + +ifeq ($(CONFIG_LIB_BOARDCTL),y) +CSRCS += stm32_appinitialize.c +endif + +ifeq ($(CONFIG_ARCH_FPU),y) +CSRCS += stm32_ostest.c +endif + +ifeq ($(CONFIG_SPORADIC_INSTRUMENTATION),y) +CSRCS += stm32_sporadic.c +endif + +include $(TOPDIR)/configs/Board.mk diff --git a/configs/stm32f769i-disco/src/stm32_appinitialize.c b/configs/stm32f769i-disco/src/stm32_appinitialize.c new file mode 100644 index 00000000000..31e7d1d7966 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_appinitialize.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * config/stm32f769i-disco/src/stm32_appinitilaize.c + * + * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "stm32_ccm.h" +#include "stm32f769i-disco.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initalization logic and the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_FS_PROCFS + int ret; + +#ifdef CONFIG_STM32_CCM_PROCFS + /* Register the CCM procfs entry. This must be done before the procfs is + * mounted. + */ + + (void)ccm_procfs_register(); +#endif + + /* Mount the procfs file system */ + + ret = mount(NULL, SAMV71_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + SYSLOG("ERROR: Failed to mount procfs at %s: %d\n", + SAMV71_PROCFS_MOUNTPOINT, ret); + } +#endif + + return OK; +} diff --git a/configs/stm32f769i-disco/src/stm32_autoleds.c b/configs/stm32f769i-disco/src/stm32_autoleds.c new file mode 100644 index 00000000000..22e7c186150 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_autoleds.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * configs/stm32f769i-disco/src/stm32_autoleds.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "stm32_gpio.h" +#include "stm32f769i-disco.h" + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + /* Configure the LD1 GPIO for output. Initial state is OFF */ + + stm32_configgpio(GPIO_LD3); +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + bool ledstate = false; + + switch (led) + { + case 0: /* LED_STARTED: NuttX has been started STATUS LED=OFF */ + /* LED_HEAPALLOCATE: Heap has been allocated STATUS LED=OFF */ + /* LED_IRQSENABLED: Interrupts enabled STATUS LED=OFF */ + break; /* Leave ledstate == true to turn OFF */ + + default: + case 2: /* LED_INIRQ: In an interrupt STATUS LED=N/C */ + /* LED_SIGNAL: In a signal handler STATUS LED=N/C */ + /* LED_ASSERTION: An assertion failed STATUS LED=N/C */ + return; /* Return to leave STATUS LED unchanged */ + + case 3: /* LED_PANIC: The system has crashed STATUS LED=FLASH */ + case 1: /* LED_STACKCREATED: Idle stack created STATUS LED=ON */ + ledstate = true; /* Set ledstate == false to turn ON */ + break; + } + + stm32_gpiowrite(GPIO_LD3, ledstate); +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + /* These should not happen and are ignored */ + + default: + case 0: /* LED_STARTED: NuttX has been started STATUS LED=OFF */ + /* LED_HEAPALLOCATE: Heap has been allocated STATUS LED=OFF */ + /* LED_IRQSENABLED: Interrupts enabled STATUS LED=OFF */ + case 1: /* LED_STACKCREATED: Idle stack created STATUS LED=ON */ + + /* These result in no-change */ + + case 2: /* LED_INIRQ: In an interrupt STATUS LED=N/C */ + /* LED_SIGNAL: In a signal handler STATUS LED=N/C */ + /* LED_ASSERTION: An assertion failed STATUS LED=N/C */ + return; /* Return to leave STATUS LED unchanged */ + + /* Turn STATUS LED off set driving the output high */ + + case 3: /* LED_PANIC: The system has crashed STATUS LED=FLASH */ + stm32_gpiowrite(GPIO_LD3, false); + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/configs/stm32f769i-disco/src/stm32_boot.c b/configs/stm32f769i-disco/src/stm32_boot.c new file mode 100644 index 00000000000..d0f95192133 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_boot.c @@ -0,0 +1,127 @@ +/************************************************************************************ + * configs/stm32f769i-disco/src/stm32_boot.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#include +#include + +#include "up_arch.h" +#include "stm32f769i-disco.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the initialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +void stm32_boardinitialize(void) +{ +#if defined(CONFIG_STM32F7_SPI1) || defined(CONFIG_STM32F7_SPI2) || \ + defined(CONFIG_STM32F7_SPI3) || defined(CONFIG_STM32F7_SPI4) || \ + defined(CONFIG_STM32F7_SPI5) + /* Configure SPI chip selects if 1) SPI is not disabled, and 2) the weak function + * stm32_spidev_initialize() has been brought into the link. + */ + + if (stm32_spidev_initialize) + { + stm32_spidev_initialize(); + } +#endif + +#ifdef CONFIG_SPORADIC_INSTRUMENTATION + /* This configuration has been used for evaluating the NuttX sporadic scheduler. + * The following caqll initializes the sporadic scheduler monitor. + */ + + arch_sporadic_initialize(); +#endif + +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + + board_autoled_initialize(); +#endif +} + +/************************************************************************************ + * Name: board_initialize + * + * Description: + * If CONFIG_BOARD_INITIALIZE is selected, then an additional initialization call + * will be performed in the boot-up sequence to a function called + * board_initialize(). board_initialize() will be called immediately after + * up_initialize() is called and just before the initial application is started. + * This additional initialization phase may be used, for example, to initialize + * board-specific device drivers. + * + ************************************************************************************/ + +#ifdef CONFIG_BOARD_INITIALIZE +void board_initialize(void) +{ +#if defined(CONFIG_NSH_LIBRARY) && !defined(CONFIG_LIB_BOARDCTL) + /* Perform NSH initialization here instead of from the NSH. This + * alternative NSH initialization is necessary when NSH is ran in user-space + * but the initialization function must run in kernel space. + */ + + (void)board_app_initialize(0); +#endif +} +#endif diff --git a/configs/stm32f769i-disco/src/stm32_buttons.c b/configs/stm32f769i-disco/src/stm32_buttons.c new file mode 100644 index 00000000000..8fd7b6cef29 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_buttons.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * configs/stm32f769i-disco/src/stm32_buttons.c + * + * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "stm32_gpio.h" +#include "stm32f769i-disco.h" + +#ifdef CONFIG_ARCH_BUTTONS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current state + * of all buttons or board_button_irq() may be called to register button + * interrupt handlers. + * + ****************************************************************************/ + +void board_button_initialize(void) +{ + stm32_configgpio(GPIO_BTN_USER); +} + +/**************************************************************************** + * Name: board_buttons + ****************************************************************************/ + +uint32_t board_buttons(void) +{ + return stm32_gpioread(GPIO_BTN_USER) ? 1 : 0; +} + +/************************************************************************************ + * Button support. + * + * Description: + * board_button_initialize() must be called to initialize button resources. After + * that, board_buttons() may be called to collect the current state of all + * buttons or board_button_irq() may be called to register button interrupt + * handlers. + * + * After board_button_initialize() has been called, board_buttons() may be called to + * collect the state of all buttons. board_buttons() returns an 32-bit bit set + * with each bit associated with a button. See the BUTTON_*_BIT + * definitions in board.h for the meaning of each bit. + * + * board_button_irq() may be called to register an interrupt handler that will + * be called when a button is depressed or released. The ID value is a + * button enumeration value that uniquely identifies a button resource. See the + * BUTTON_* definitions in board.h for the meaning of enumeration + * value. + * + ************************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +int board_button_irq(int id, xcpt_t irqhandler, FAR void *arg) +{ +#warning Missing logic + return -ENOSYS; +} +#endif +#endif /* CONFIG_ARCH_BUTTONS */ diff --git a/configs/stm32f769i-disco/src/stm32_ostest.c b/configs/stm32f769i-disco/src/stm32_ostest.c new file mode 100644 index 00000000000..184f88d6709 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_ostest.c @@ -0,0 +1,113 @@ +/************************************************************************************ + * configs/stm32f769i-disco/src/stm32_ostest.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "stm32f769i-disco.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#undef HAVE_FPU +#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_EXAMPLES_OSTEST_FPUTESTDISABLE) && \ + defined(CONFIG_EXAMPLES_OSTEST_FPUSIZE) && defined(CONFIG_SCHED_WAITPID) && \ + !defined(CONFIG_DISABLE_SIGNALS) +# define HAVE_FPU 1 +#endif + +#ifdef HAVE_FPU + +#if CONFIG_EXAMPLES_OSTEST_FPUSIZE != (4*SW_FPU_REGS) +# error "CONFIG_EXAMPLES_OSTEST_FPUSIZE has the wrong size" +#endif + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +static uint32_t g_saveregs[XCPTCONTEXT_REGS]; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ +/* Given an array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE, this function will return + * the current FPU registers. + */ + +void arch_getfpu(FAR uint32_t *fpusave) +{ + irqstate_t flags; + + /* Take a snapshot of the thread context right now */ + + flags = enter_critical_section(); + up_saveusercontext(g_saveregs); + + /* Return only the floating register values */ + + memcpy(fpusave, &g_saveregs[REG_S0], (4*SW_FPU_REGS)); + leave_critical_section(flags); +} + +/* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this function + * will compare them and return true if they are identical. + */ + +bool arch_cmpfpu(FAR const uint32_t *fpusave1, FAR const uint32_t *fpusave2) +{ + return memcmp(fpusave1, fpusave2, (4*SW_FPU_REGS)) == 0; +} + +#endif /* HAVE_FPU */ diff --git a/configs/stm32f769i-disco/src/stm32_spi.c b/configs/stm32f769i-disco/src/stm32_spi.c new file mode 100644 index 00000000000..17fda9da1f3 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_spi.c @@ -0,0 +1,221 @@ +/************************************************************************************ + * configs/stm32f769i-disco/src/stm32_spi.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_spi.h" + +#include "stm32f769i-disco.h" + +#if defined(CONFIG_STM32F7_SPI1) || defined(CONFIG_STM32F7_SPI2) || \ + defined(CONFIG_STM32F7_SPI3) || defined(CONFIG_STM32F7_SPI4) || \ + defined(CONFIG_STM32F7_SPI5) + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the stm32f769i-disco board. + * + ************************************************************************************/ + +void weak_function stm32_spidev_initialize(void) +{ +} + +/**************************************************************************** + * Name: stm32_spi1/2/3/4/5select and stm32_spi1/2/3/4/5status + * + * Description: + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi/spi.h). All other methods (including stm32_spibus_initialize()) + * are provided by common STM32 logic. To use this common SPI logic on your + * board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * status operations using GPIOs in the way your board is configured. + * 3. Add a calls to stm32_spibus_initialize() in your low level application + * initialization logic + * 4. The handle returned by stm32_spibus_initialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_STM32F7_SPI1 +void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32F7_SPI2 +void stm32_spi2select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32F7_SPI3 +void stm32_spi3select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32F7_SPI4 +void stm32_spi4select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi4status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32F7_SPI5 +void stm32_spi5select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi5status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +/**************************************************************************** + * Name: stm32_spi1cmddata + * + * Description: + * Set or clear the SH1101A A0 or SD1306 D/C n bit to select data (true) + * or command (false). This function must be provided by platform-specific + * logic. This is an implementation of the cmddata method of the SPI + * interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h). + * + * Input Parameters: + * + * spi - SPI device that controls the bus the device that requires the CMD/ + * DATA selection. + * devid - If there are multiple devices on the bus, this selects which one + * to select cmd or data. NOTE: This design restricts, for example, + * one one SPI display per SPI bus. + * cmd - true: select command; false: select data + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +#ifdef CONFIG_STM32F7_SPI1 +int stm32_spi1cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32F7_SPI2 +int stm32_spi2cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32F7_SPI3 +int stm32_spi3cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32F7_SPI4 +int stm32_spi4cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32F7_SPI5 +int stm32_spi5cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#endif /* CONFIG_SPI_CMDDATA */ +#endif /* CONFIG_STM32F7_SPI1 || ... CONFIG_STM32F7_SPI5 */ diff --git a/configs/stm32f769i-disco/src/stm32_sporadic.c b/configs/stm32f769i-disco/src/stm32_sporadic.c new file mode 100644 index 00000000000..2960362f589 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_sporadic.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * configs/stm32f769i-disco/src/stm32_sporadic.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "stm32_gpio.h" +#include "stm32f769i-disco.h" + +#ifdef CONFIG_SPORADIC_INSTRUMENTATION + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arch_sporadic_* + * + * Description: + * This configuration has been used for evaluating the NuttX sporadic + * scheduler. This only makes sense when uses with the sporadic test + * which is a part of apps/examples/ostest. If would make generate + * meaningful output in its current state if there were multiple sporadic + * threads + * + ****************************************************************************/ + +void arch_sporadic_initialize(void) +{ + stm32_configgpio(GPIO_SCHED_HIGHPRI); + stm32_configgpio(GPIO_SCHED_RUNNING); +} + +void arch_sporadic_start(FAR struct tcb_s *tcb) +{ + stm32_gpiowrite(GPIO_SCHED_HIGHPRI, true); +} + +void arch_sporadic_lowpriority(FAR struct tcb_s *tcb) +{ + stm32_gpiowrite(GPIO_SCHED_HIGHPRI, false); +} + +void arch_sporadic_suspend(FAR struct tcb_s *tcb) +{ + stm32_gpiowrite(GPIO_SCHED_RUNNING, false); +} + +void arch_sporadic_resume(FAR struct tcb_s *tcb) +{ + stm32_gpiowrite(GPIO_SCHED_RUNNING, true); +} + +#endif /* CONFIG_SPORADIC_INSTRUMENTATION */ \ No newline at end of file diff --git a/configs/stm32f769i-disco/src/stm32_userleds.c b/configs/stm32f769i-disco/src/stm32_userleds.c new file mode 100644 index 00000000000..c61f06ae660 --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32_userleds.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * configs/stm32f769i-disco/src/stm32_userleds.c + * + * Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "stm32_gpio.h" +#include "stm32f769i-disco.h" + +#ifndef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the + * board_userled_initialize() is available to initialize the LED from user + * application logic. + * + ****************************************************************************/ + +void board_userled_initialize(void) +{ + stm32_configgpio(GPIO_LD3); +} + +/**************************************************************************** + * Name: board_userled + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the board_userled() is + * available to control the LED from user application logic. + * + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if (led == BOARD_STATUS_LED) + { + stm32_gpiowrite(GPIO_LD3, !ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the board_userled_all() is + * available to control the LED from user application logic. NOTE: since + * there is only a single LED on-board, this is function is not very useful. + * + ****************************************************************************/ + +void board_userled_all(uint8_t ledset) +{ + stm32_gpiowrite(GPIO_LD3, (ledset & BOARD_STATUS_LED_BIT) != 0); +} + +#endif /* !CONFIG_ARCH_LEDS */ diff --git a/configs/stm32f769i-disco/src/stm32f769i-disco.h b/configs/stm32f769i-disco/src/stm32f769i-disco.h new file mode 100644 index 00000000000..7565fa27a5f --- /dev/null +++ b/configs/stm32f769i-disco/src/stm32f769i-disco.h @@ -0,0 +1,125 @@ +/**************************************************************************************************** + * configs/stm32f769i-disco/src/stm32f769i-disco.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __CONFIGS_STM32F769I_DISCO_SRC_STM32F769I_DISCO__H +#define __CONFIGS_STM32F769I_DISCO_SRC_STM32F769I_DISCO__H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ +/* procfs File System */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define STM32_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define STM32_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + +/* STM32F769 Discovery GPIOs ***********************************************************************/ +/* The STM32F769I-DISCO has one user controllable LED: LD3. + * + * LD3 is controlled by PA12 which is also the SPI2_SCK at the Arduino interface. + * LD3 is on when PA12 is high. + */ + +#define GPIO_LD3 (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | GPIO_OUTPUT_CLEAR | \ + GPIO_PORTA | GPIO_PIN12) + +/* Pushbutton B1, labelled "User", is connected to GPIO PA0. A high value will be sensed when the + * button is depressed. Note that the EXTI interrupt is configured. + */ + +#define GPIO_BTN_USER (GPIO_INPUT | GPIO_FLOAT | GPIO_EXTI | GPIO_PORTA | GPIO_PIN0) + +/* Sporadic scheduler instrumentation. This configuration has been used for evaluating the NuttX + * sporadic scheduler. In this evaluation, two GPIO outputs are used. One indicating the priority + * (high or low) of the sporadic thread and one indicating where the thread is running or not. + * + * There is nothing special about the pin selections: + * + * Arduino D2 PJ1 - Indicates priority1 + * Arduino D4 PJ0 - Indicates that the thread is running + */ + +#define GPIO_SCHED_HIGHPRI (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | GPIO_OUTPUT_CLEAR | \ + GPIO_PORTJ | GPIO_PIN1) +#define GPIO_SCHED_RUNNING (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | GPIO_OUTPUT_CLEAR | \ + GPIO_PORTJ | GPIO_PIN0) + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +/**************************************************************************************************** + * Name: stm32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the stm32f769i-disco board. + * + ****************************************************************************************************/ + +void weak_function stm32_spidev_initialize(void); + +/**************************************************************************************************** + * Name: arch_sporadic_initialize + * + * Description: + * This configuration has been used for evaluating the NuttX sporadic scheduler. + * + ****************************************************************************************************/ + +#ifdef CONFIG_SPORADIC_INSTRUMENTATION +void arch_sporadic_initialize(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIGS_STM32F769I_DISCO_SRC_STM32F769I_DISCO_H */ +